Merge remote-tracking branch 'origin/master'
This commit is contained in:
131
app/InvitationCodeUtil.php
Normal file
131
app/InvitationCodeUtil.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace app;
|
||||
|
||||
use extend\ba\Random;
|
||||
|
||||
class InvitationCodeUtil
|
||||
{
|
||||
/**
|
||||
* 自定义进制字符集(30进制)
|
||||
* 避免 0、1、O、I 混淆字符
|
||||
*/
|
||||
private static array $r = ['M', 'J', 'U', 'D', 'Z', 'X', '9', 'C', '7', 'P', 'E', '8', '6', 'B', 'G', 'H', 'S', '2', '5', 'F', 'R', '4', 'Q', 'W', 'K', '3', 'V', 'Y', 'T', 'N'];
|
||||
|
||||
/**
|
||||
* 补位字符
|
||||
*/
|
||||
private static string $b = 'A';
|
||||
|
||||
/**
|
||||
* 进制长度
|
||||
*/
|
||||
private static int $binLen = 30;
|
||||
|
||||
/**
|
||||
* 最小长度
|
||||
*/
|
||||
private static int $s = 6;
|
||||
|
||||
/**
|
||||
* 补位字符串 - 生成注册码用
|
||||
*/
|
||||
private static string $re = 'REGISTER';
|
||||
|
||||
/**
|
||||
* 补位字符串 - 生成序列码用
|
||||
*/
|
||||
private static string $e = 'KSLFXFR';
|
||||
|
||||
/**
|
||||
* 根据ID生成六位注册邀请码
|
||||
*
|
||||
* @param int $id
|
||||
* @return string
|
||||
*/
|
||||
public static function toRegisteredCode(int $id): string
|
||||
{
|
||||
$str = self::encodeBase($id);
|
||||
if (strlen($str) < self::$s) {
|
||||
$pad = substr(self::$re, 0, self::$s - strlen($str));
|
||||
$str .= $pad;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID生成六位序列码
|
||||
*
|
||||
* @param int $id
|
||||
* @return string
|
||||
*/
|
||||
public static function toSerialCode(int $id): string
|
||||
{
|
||||
$str = self::encodeBase($id);
|
||||
if (strlen($str) < self::$s) {
|
||||
$pad = substr(self::$e, 0, self::$s - strlen($str));
|
||||
$str .= $pad;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将邀请码还原为 ID
|
||||
*
|
||||
* @param string $code
|
||||
* @return int
|
||||
*/
|
||||
public static function codeToId(string $code): int
|
||||
{
|
||||
$chars = str_split($code);
|
||||
$res = 0;
|
||||
|
||||
foreach ($chars as $i => $ch) {
|
||||
if ($ch === self::$b) {
|
||||
break;
|
||||
}
|
||||
|
||||
$index = array_search($ch, self::$r, true);
|
||||
if ($index === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$res = $i === 0 ? $index : $res * self::$binLen + $index;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 雪花 ID(需引入 PHP 雪花 ID 工具)
|
||||
* 推荐使用: https://github.com/Gerardojbaez/laravel-snowflake 或你自己的封装
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getSnowFlakeId(): int
|
||||
{
|
||||
// 简化版本,实际应使用类库如 Godruoyi\Snowflake
|
||||
if (!class_exists('Snowflake')) {
|
||||
throw new \RuntimeException("Snowflake class not found.");
|
||||
}
|
||||
return Random::generateRandomPrefixedId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 进制转换编码主逻辑
|
||||
*
|
||||
* @param int $id
|
||||
* @return string
|
||||
*/
|
||||
private static function encodeBase(int $id): string
|
||||
{
|
||||
$buf = [];
|
||||
do {
|
||||
$index = $id % self::$binLen;
|
||||
array_unshift($buf, self::$r[$index]);
|
||||
$id = intdiv($id, self::$binLen);
|
||||
} while ($id > 0);
|
||||
|
||||
return implode('', $buf);
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,10 @@ use think\facade\Log;
|
||||
use Throwable;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
use think\facade\Config;
|
||||
use app\admin\model\Admin;
|
||||
use app\common\facade\Token;
|
||||
use app\admin\model\AdminGroup;
|
||||
use Webman\Config;
|
||||
|
||||
/**
|
||||
* 管理员权限类
|
||||
@@ -23,7 +23,7 @@ use app\admin\model\AdminGroup;
|
||||
* @property string $email 管理员邮箱
|
||||
* @property string $mobile 管理员手机号
|
||||
*/
|
||||
class Auth extends \ba\Auth
|
||||
class Auth extends \extend\ba\Auth
|
||||
{
|
||||
/**
|
||||
* 需要登录时/无需登录时的响应状态代码
|
||||
@@ -352,38 +352,9 @@ class Auth extends \ba\Auth
|
||||
}
|
||||
|
||||
|
||||
public function checkmenus($url, $uid): bool
|
||||
{
|
||||
return parent::checkmenus($url, $uid ?: $this->user_id);
|
||||
}
|
||||
public function getUserMenus($uid):array
|
||||
{
|
||||
return parent::getUserMenus($uid);
|
||||
}
|
||||
public function check(string $name, int $uid = 0, string $relation = 'or', string $mode = 'url'): bool
|
||||
{
|
||||
return parent::check($name, $uid ?: $this->id, $relation, $mode);
|
||||
}
|
||||
|
||||
public function getGroups(int $uid = 0): array
|
||||
{
|
||||
return parent::getGroups($uid ?: $this->id);
|
||||
}
|
||||
|
||||
public function getRuleList(int $uid = 0): array
|
||||
{
|
||||
return parent::getRuleList($uid ?: $this->id);
|
||||
}
|
||||
|
||||
public function getRuleIds(int $uid = 0): array
|
||||
{
|
||||
return parent::getRuleIds($uid ?: $this->id);
|
||||
}
|
||||
|
||||
public function getMenus(int $uid = 0): array
|
||||
{
|
||||
return parent::getMenus($uid ?: $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是超级管理员
|
||||
|
||||
@@ -3,19 +3,25 @@
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
use think\captcha\facade\Captcha as thinkCaptcha;
|
||||
use Webman\Captcha\CaptchaBuilder;
|
||||
use support\Request;
|
||||
|
||||
class SysCaptcha extends Model
|
||||
{
|
||||
public static function getCode($uuid)
|
||||
public static function getCode($uuid, $request)
|
||||
{
|
||||
$code_data = thinkCaptcha::create('czg');
|
||||
// 初始化验证码类
|
||||
$builder = new CaptchaBuilder;
|
||||
// 生成验证码
|
||||
$builder->build();
|
||||
// 获得验证码图片二进制数据
|
||||
$img_content = $builder->inline();
|
||||
// 保存至数据库
|
||||
self::create([
|
||||
'uuid' => $uuid,
|
||||
'code' => $code_data['code'],
|
||||
'expire_time' => date('Y-m-d H:i:s', time() + config('captcha.expire_time')),
|
||||
'code' => $builder->getPhrase(),
|
||||
'expire_time' => date('Y-m-d H:i:s', time() + 600),
|
||||
]);
|
||||
return ['img' => $code_data['img']];
|
||||
return ['img' => $img_content];
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Cache;
|
||||
use support\think\Cache;
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
use think\model\relation\BelongsTo;
|
||||
|
||||
526
app/common/controller/Backend.php
Normal file
526
app/common/controller/Backend.php
Normal file
@@ -0,0 +1,526 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\controller;
|
||||
|
||||
use app\exception\MyBusinessException;
|
||||
use support\Request;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Response;
|
||||
use Throwable;
|
||||
use think\Model;
|
||||
use think\facade\Event;
|
||||
use app\admin\library\Auth;
|
||||
use app\common\library\token\TokenExpirationException;
|
||||
|
||||
class Backend
|
||||
{
|
||||
/**
|
||||
* 无需登录的方法,访问本控制器的此方法,无需管理员登录
|
||||
* @var array
|
||||
*/
|
||||
protected array $noNeedLogin = [];
|
||||
|
||||
/**
|
||||
* 无需鉴权的方法
|
||||
* @var array
|
||||
*/
|
||||
protected array $noNeedPermission = [];
|
||||
|
||||
/**
|
||||
* 新增/编辑时,对前端发送的字段进行排除(忽略不入库)
|
||||
* @var array|string
|
||||
*/
|
||||
protected array|string $preExcludeFields = [];
|
||||
|
||||
/**
|
||||
* 权限类实例
|
||||
* @var Auth
|
||||
*/
|
||||
protected Auth $auth;
|
||||
|
||||
/**
|
||||
* 模型类实例
|
||||
* @var object
|
||||
* @phpstan-var Model
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
/**
|
||||
* 权重字段
|
||||
* @var string
|
||||
*/
|
||||
protected string $weighField = 'weigh';
|
||||
|
||||
/**
|
||||
* 默认排序
|
||||
* @var string|array id,desc 或 ['id' => 'desc']
|
||||
*/
|
||||
protected string|array $defaultSortField = [];
|
||||
|
||||
/**
|
||||
* 有序保证
|
||||
* 查询数据时总是需要指定 ORDER BY 子句,否则 MySQL 不保证排序,即先查到哪行就输出哪行且不保证多次查询中的输出顺序
|
||||
* 将以下配置作为数据有序保证(用于无排序字段时、默认排序字段相同时继续保持数据有序),不设置将自动使用 pk 字段
|
||||
* @var string|array id,desc 或 ['id' => 'desc'](有更方便的格式,此处为了保持和 $defaultSortField 属性的配置格式一致)
|
||||
*/
|
||||
protected string|array $orderGuarantee = [];
|
||||
|
||||
/**
|
||||
* 快速搜索字段
|
||||
* @var string|array
|
||||
*/
|
||||
protected string|array $quickSearchField = 'id';
|
||||
|
||||
/**
|
||||
* 是否开启模型验证
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $modelValidate = true;
|
||||
|
||||
/**
|
||||
* 是否开启模型场景验证
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $modelSceneValidate = false;
|
||||
|
||||
/**
|
||||
* 关联查询方法名,方法应定义在模型中
|
||||
* @var array
|
||||
*/
|
||||
protected array $withJoinTable = [];
|
||||
|
||||
/**
|
||||
* 关联查询JOIN方式
|
||||
* @var string
|
||||
*/
|
||||
protected string $withJoinType = 'LEFT';
|
||||
|
||||
/**
|
||||
* 开启数据限制
|
||||
* false=关闭
|
||||
* personal=仅限个人
|
||||
* allAuth=拥有某管理员所有的权限时
|
||||
* allAuthAndOthers=拥有某管理员所有的权限并且还有其他权限时
|
||||
* parent=上级分组中的管理员可查
|
||||
* 指定分组中的管理员可查,比如 $dataLimit = 2;
|
||||
* 启用请确保数据表内存在 admin_id 字段,可以查询/编辑数据的管理员为admin_id对应的管理员+数据限制所表示的管理员们
|
||||
* @var bool|string|int
|
||||
*/
|
||||
protected bool|string|int $dataLimit = false;
|
||||
|
||||
/**
|
||||
* 数据限制字段
|
||||
* @var string
|
||||
*/
|
||||
protected string $dataLimitField = 'admin_id';
|
||||
|
||||
/**
|
||||
* 数据限制开启时自动填充字段值为当前管理员id
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $dataLimitFieldAutoFill = true;
|
||||
|
||||
/**
|
||||
* 查看请求返回的主表字段控制
|
||||
* @var string|array
|
||||
*/
|
||||
protected string|array $indexField = ['*'];
|
||||
|
||||
protected Request $request;
|
||||
/**
|
||||
* 引入traits
|
||||
* traits内实现了index、add、edit等方法
|
||||
*/
|
||||
use \app\admin\library\traits\Backend;
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->request = request();
|
||||
$needLogin = !action_in_arr($this->noNeedLogin);
|
||||
|
||||
try {
|
||||
|
||||
// 初始化管理员鉴权实例
|
||||
$this->auth = Auth::instance();
|
||||
$token = request()->header('token');
|
||||
if ($token) $this->auth->init($token);
|
||||
} catch (TokenExpirationException) {
|
||||
if ($needLogin) {
|
||||
$this->error(__('Token expiration'), [], 409);
|
||||
}
|
||||
}
|
||||
|
||||
if ($needLogin) {
|
||||
if (!$this->auth->isLogin()) {
|
||||
$this->error('Please login first', [
|
||||
'type' => $this->auth::NEED_LOGIN
|
||||
], $this->auth::LOGIN_RESPONSE_CODE);
|
||||
}
|
||||
|
||||
if (!action_in_arr($this->noNeedPermission)) {
|
||||
// $routePath = ($this->app->request->controllerPath ?? '') . '/' . $this->request->action(true);
|
||||
$routePath = substr(request()->path(), 5);
|
||||
|
||||
if (!$this->auth->checkmenus($routePath, $this->auth->user_id)) {
|
||||
$this->error('You have no permission', []);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询参数构建器
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function queryBuilder(): array
|
||||
{
|
||||
if (empty($this->model)) {
|
||||
return [];
|
||||
}
|
||||
$pk = $this->model->getPk();
|
||||
$quickSearch = $this->request->get("quickSearch/s", '');
|
||||
$limit = $this->request->get("limit/d", 10);
|
||||
$search = $this->request->get("search/a", []);
|
||||
$initKey = $this->request->get("initKey/s", $pk);
|
||||
$initValue = $this->request->get("initValue", '');
|
||||
$initOperator = $this->request->get("initOperator/s", 'in');
|
||||
|
||||
$where = [];
|
||||
$modelTable = strtolower($this->model->getTable());
|
||||
$alias[$modelTable] = parse_name(basename(str_replace('\\', '/', get_class($this->model))));
|
||||
$mainTableAlias = $alias[$modelTable] . '.';
|
||||
|
||||
// 快速搜索
|
||||
if ($quickSearch) {
|
||||
$quickSearchArr = is_array($this->quickSearchField) ? $this->quickSearchField : explode(',', $this->quickSearchField);
|
||||
foreach ($quickSearchArr as $k => $v) {
|
||||
$quickSearchArr[$k] = str_contains($v, '.') ? $v : $mainTableAlias . $v;
|
||||
}
|
||||
$where[] = [implode("|", $quickSearchArr), "LIKE", '%' . str_replace('%', '\%', $quickSearch) . '%'];
|
||||
}
|
||||
if ($initValue) {
|
||||
$where[] = [$initKey, $initOperator, $initValue];
|
||||
$limit = 999999;
|
||||
}
|
||||
|
||||
// 通用搜索组装
|
||||
foreach ($search as $field) {
|
||||
if (!is_array($field) || !isset($field['operator']) || !isset($field['field']) || !isset($field['val'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field['operator'] = $this->getOperatorByAlias($field['operator']);
|
||||
|
||||
// 查询关联表字段,转换表别名(驼峰转小写下划线)
|
||||
if (str_contains($field['field'], '.')) {
|
||||
$fieldNameParts = explode('.', $field['field']);
|
||||
$fieldNamePartsLastKey = array_key_last($fieldNameParts);
|
||||
|
||||
// 忽略最后一个元素(字段名)
|
||||
foreach ($fieldNameParts as $fieldNamePartsKey => $fieldNamePart) {
|
||||
if ($fieldNamePartsKey !== $fieldNamePartsLastKey) {
|
||||
$fieldNameParts[$fieldNamePartsKey] = parse_name($fieldNamePart);
|
||||
}
|
||||
}
|
||||
|
||||
$fieldName = implode('.', $fieldNameParts);
|
||||
} else {
|
||||
$fieldName = $mainTableAlias . $field['field'];
|
||||
}
|
||||
|
||||
// 日期时间
|
||||
if (isset($field['render']) && $field['render'] == 'datetime') {
|
||||
if ($field['operator'] == 'RANGE') {
|
||||
$datetimeArr = explode(',', $field['val']);
|
||||
if (!isset($datetimeArr[1])) {
|
||||
continue;
|
||||
}
|
||||
$datetimeArr = array_filter(array_map("strtotime", $datetimeArr));
|
||||
$where[] = [$fieldName, str_replace('RANGE', 'BETWEEN', $field['operator']), $datetimeArr];
|
||||
continue;
|
||||
}
|
||||
$where[] = [$fieldName, '=', strtotime($field['val'])];
|
||||
continue;
|
||||
}
|
||||
|
||||
// 范围查询
|
||||
if ($field['operator'] == 'RANGE' || $field['operator'] == 'NOT RANGE') {
|
||||
$arr = explode(',', $field['val']);
|
||||
// 重新确定操作符
|
||||
if (!isset($arr[0]) || $arr[0] === '') {
|
||||
$operator = $field['operator'] == 'RANGE' ? '<=' : '>';
|
||||
$arr = $arr[1];
|
||||
} elseif (!isset($arr[1]) || $arr[1] === '') {
|
||||
$operator = $field['operator'] == 'RANGE' ? '>=' : '<';
|
||||
$arr = $arr[0];
|
||||
} else {
|
||||
$operator = str_replace('RANGE', 'BETWEEN', $field['operator']);
|
||||
}
|
||||
$where[] = [$fieldName, $operator, $arr];
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($field['operator']) {
|
||||
case '=':
|
||||
case '<>':
|
||||
$where[] = [$fieldName, $field['operator'], (string)$field['val']];
|
||||
break;
|
||||
case 'LIKE':
|
||||
case 'NOT LIKE':
|
||||
$where[] = [$fieldName, $field['operator'], '%' . str_replace('%', '\%', $field['val']) . '%'];
|
||||
break;
|
||||
case '>':
|
||||
case '>=':
|
||||
case '<':
|
||||
case '<=':
|
||||
$where[] = [$fieldName, $field['operator'], intval($field['val'])];
|
||||
break;
|
||||
case 'FIND_IN_SET':
|
||||
if (is_array($field['val'])) {
|
||||
foreach ($field['val'] as $val) {
|
||||
$where[] = [$fieldName, 'find in set', $val];
|
||||
}
|
||||
} else {
|
||||
$where[] = [$fieldName, 'find in set', $field['val']];
|
||||
}
|
||||
break;
|
||||
case 'IN':
|
||||
case 'NOT IN':
|
||||
$where[] = [$fieldName, $field['operator'], is_array($field['val']) ? $field['val'] : explode(',', $field['val'])];
|
||||
break;
|
||||
case 'NULL':
|
||||
case 'NOT NULL':
|
||||
$where[] = [$fieldName, strtolower($field['operator']), ''];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 数据权限
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds) {
|
||||
$where[] = [$mainTableAlias . $this->dataLimitField, 'in', $dataLimitAdminIds];
|
||||
}
|
||||
|
||||
return [$where, $alias, $limit, $this->queryOrderBuilder()];
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询的排序参数构建器
|
||||
*/
|
||||
public function queryOrderBuilder()
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$order = $this->request->get("order/s") ?: $this->defaultSortField;
|
||||
|
||||
if ($order && is_string($order)) {
|
||||
$order = explode(',', $order);
|
||||
$order = [$order[0] => $order[1] ?? 'asc'];
|
||||
}
|
||||
if (!$this->orderGuarantee) {
|
||||
$this->orderGuarantee = [$pk => 'desc'];
|
||||
} elseif (is_string($this->orderGuarantee)) {
|
||||
$this->orderGuarantee = explode(',', $this->orderGuarantee);
|
||||
$this->orderGuarantee = [$this->orderGuarantee[0] => $this->orderGuarantee[1] ?? 'asc'];
|
||||
}
|
||||
$orderGuaranteeKey = array_key_first($this->orderGuarantee);
|
||||
if (!array_key_exists($orderGuaranteeKey, $order)) {
|
||||
$order[$orderGuaranteeKey] = $this->orderGuarantee[$orderGuaranteeKey];
|
||||
}
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据权限控制-获取有权限访问的管理员Ids
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected function getDataLimitAdminIds(): array
|
||||
{
|
||||
if (!$this->dataLimit || $this->auth->isSuperAdmin()) {
|
||||
return [];
|
||||
}
|
||||
$adminIds = [];
|
||||
if ($this->dataLimit == 'parent') {
|
||||
// 取得当前管理员的下级分组们
|
||||
$parentGroups = $this->auth->getAdminChildGroups();
|
||||
if ($parentGroups) {
|
||||
// 取得分组内的所有管理员
|
||||
$adminIds = $this->auth->getGroupAdmins($parentGroups);
|
||||
}
|
||||
} elseif (is_numeric($this->dataLimit) && $this->dataLimit > 0) {
|
||||
// 在组内,可查看所有,不在组内,可查看自己的
|
||||
$adminIds = $this->auth->getGroupAdmins([$this->dataLimit]);
|
||||
return in_array($this->auth->id, $adminIds) ? [] : [$this->auth->id];
|
||||
} elseif ($this->dataLimit == 'allAuth' || $this->dataLimit == 'allAuthAndOthers') {
|
||||
// 取得拥有他所有权限的分组
|
||||
$allAuthGroups = $this->auth->getAllAuthGroups($this->dataLimit);
|
||||
// 取得分组内的所有管理员
|
||||
$adminIds = $this->auth->getGroupAdmins($allAuthGroups);
|
||||
}
|
||||
$adminIds[] = $this->auth->id;
|
||||
return array_unique($adminIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从别名获取原始的逻辑运算符
|
||||
* @param string $operator 逻辑运算符别名
|
||||
* @return string 原始的逻辑运算符,无别名则原样返回
|
||||
*/
|
||||
protected function getOperatorByAlias(string $operator): string
|
||||
{
|
||||
$alias = [
|
||||
'ne' => '<>',
|
||||
'eq' => '=',
|
||||
'gt' => '>',
|
||||
'egt' => '>=',
|
||||
'lt' => '<',
|
||||
'elt' => '<=',
|
||||
];
|
||||
|
||||
return $alias[$operator] ?? $operator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 操作成功
|
||||
* @param string $msg 提示消息
|
||||
* @param mixed $data 返回数据
|
||||
* @param int $code 错误码
|
||||
* @param string|null $type 输出类型
|
||||
* @param array $header 发送的 header 信息
|
||||
* @param array $options Response 输出参数
|
||||
*/
|
||||
protected function success(string $msg = '', mixed $data = null, int $code = 0, string $type = null, array $header = [], array $options = []): void
|
||||
{
|
||||
$this->result($msg, $data, $code, $type, $header, $options);
|
||||
}
|
||||
|
||||
|
||||
protected function successWithData(mixed $data = null, string $msg = '', int $code = 0, string $type = null, array $header = [], array $options = []): void
|
||||
{
|
||||
$this->result($msg, $data, $code, $type, $header, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作失败
|
||||
* @param string $msg 提示消息
|
||||
* @param mixed $data 返回数据
|
||||
* @param int $code 错误码
|
||||
* @param string|null $type 输出类型
|
||||
* @param array $header 发送的 header 信息
|
||||
* @param array $options Response 输出参数
|
||||
*/
|
||||
protected function error(string $msg = '', mixed $data = null, int $code = -1, string $type = null, array $header = [], array $options = []): void
|
||||
{
|
||||
$this->result($msg, $data, $code, $type, $header, $options);
|
||||
}
|
||||
|
||||
protected function errorMsg(string $msg = '', mixed $data = null, int $code = -1, string $type = null, array $header = [], array $options = []): void
|
||||
{
|
||||
$this->result($msg, $data, $code, $type, $header, $options, 'data', 'msg');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 操作成功
|
||||
* @param string $msg 提示消息
|
||||
* @param mixed $data 返回数据
|
||||
* @param int $code 错误码
|
||||
* @param string|null $type 输出类型
|
||||
* @param array $header 发送的 header 信息
|
||||
* @param array $options Response 输出参数
|
||||
*/
|
||||
protected function n_success(array $data, string $msg = 'ok', int $code = 0, string $type = null, array $header = [], array $options = []): void
|
||||
{
|
||||
$this->resultApi($data, $msg, $code, $type, $header, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作失败
|
||||
* @param string $msg 提示消息
|
||||
* @param mixed $data 返回数据
|
||||
* @param int $code 错误码
|
||||
* @param string|null $type 输出类型
|
||||
* @param array $header 发送的 header 信息
|
||||
* @param array $options Response 输出参数
|
||||
*/
|
||||
protected function n_error(string $msg, array $data = [], int $code = -1, string $type = null, array $header = [], array $options = []): void
|
||||
{
|
||||
$this->resultApi($data, $msg, $code, $type, $header, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 多种操作结果
|
||||
*/
|
||||
public function resultApi(array $data = [], string $msg = 'ok', int $code = 0, string $type = null, array $header = [], array $options = [])
|
||||
{
|
||||
$data['code'] = $code;
|
||||
$data['message'] = $msg;
|
||||
$data['time'] = time();
|
||||
if(isset($data['data']['records'])) {
|
||||
$data['data']['records'] = apiconvertToCamelCase($data['data']['records']);
|
||||
}
|
||||
if(isset($data['page']['list'])) {
|
||||
$data['page']['list'] = apiconvertToCamelCase($data['page']['list']);
|
||||
}
|
||||
if(isset($data['data']['list'])) {
|
||||
$data['data']['list'] = apiconvertToCamelCase($data['data']['list']);
|
||||
}
|
||||
if(isset($data['data']['userEntity'])) {
|
||||
$data['data']['userEntity'] = apiconvertToCamelCase($data['data']['userEntity']);
|
||||
}
|
||||
$result = $data;
|
||||
|
||||
throw new MyBusinessException(json_encode($result));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 返回 API 数据
|
||||
* @param string $msg 提示消息
|
||||
* @param mixed $data 返回数据
|
||||
* @param int $code 错误码
|
||||
* @param string|null $type 输出类型
|
||||
* @param array $header 发送的 header 信息
|
||||
* @param array $options Response 输出参数
|
||||
*/
|
||||
public function result(string $msg, mixed $data = null, int $code = 0, string $type = null, array $header = [], array $options = [], string $dataKey = 'data', string $msgKey = 'message')
|
||||
{
|
||||
if(isset($data['records'])) {
|
||||
$data['records'] = apiconvertToCamelCase($data['records']);
|
||||
}
|
||||
if(isset($data['page'])) {
|
||||
$data['page'] = apiconvertToCamelCase($data['page']);
|
||||
}
|
||||
if(isset($data['list'])) {
|
||||
$data['list'] = apiconvertToCamelCase($data['list']);
|
||||
}
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'message' => $msg,
|
||||
'time' => time(),
|
||||
$dataKey => $data,
|
||||
];
|
||||
throw new MyBusinessException(json_encode($result));
|
||||
}
|
||||
|
||||
public function ApiDataReturn($data)
|
||||
{
|
||||
return json($data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace app\common\model;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use extend\ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
use support\think\Cache;
|
||||
class SysUser extends BaseModel
|
||||
{
|
||||
|
||||
|
||||
260
app/czg/auth/controller/AdminController.php
Normal file
260
app/czg/auth/controller/AdminController.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\auth\controller;
|
||||
use Throwable;
|
||||
use think\facade\Db;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\Admin as AdminModel;
|
||||
|
||||
class AdminController extends Backend
|
||||
{
|
||||
/**
|
||||
* 模型
|
||||
* @var object
|
||||
* @phpstan-var AdminModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected array|string $preExcludeFields = ['create_time', 'update_time', 'password', 'salt', 'login_failure', 'last_login_time', 'last_login_ip'];
|
||||
|
||||
protected array|string $quickSearchField = ['username', 'nickname'];
|
||||
|
||||
/**
|
||||
* 开启数据限制
|
||||
*/
|
||||
protected string|int|bool $dataLimit = 'allAuthAndOthers';
|
||||
|
||||
protected string $dataLimitField = 'id';
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new AdminModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('login_failure,password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
if ($this->modelValidate) {
|
||||
try {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = new $validate();
|
||||
$validate->scene('add')->check($data);
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$passwd = $data['password']; // 密码将被排除不直接入库
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
if ($data['group_arr']) $this->checkGroupAuth($data['group_arr']);
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
$result = $this->model->save($data);
|
||||
if ($data['group_arr']) {
|
||||
$groupAccess = [];
|
||||
foreach ($data['group_arr'] as $datum) {
|
||||
$groupAccess[] = [
|
||||
'uid' => $this->model->id,
|
||||
'group_id' => $datum,
|
||||
];
|
||||
}
|
||||
Db::name('admin_group_access')->insertAll($groupAccess);
|
||||
}
|
||||
$this->model->commit();
|
||||
|
||||
if (!empty($passwd)) {
|
||||
$this->model->resetPassword($this->model->id, $passwd);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
if ($this->modelValidate) {
|
||||
try {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = new $validate();
|
||||
$validate->scene('edit')->check($data);
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->auth->id == $data['id'] && $data['status'] == 'disable') {
|
||||
$this->error(__('Please use another administrator account to disable the current account!'));
|
||||
}
|
||||
|
||||
if (!empty($data['password'])) {
|
||||
$this->model->resetPassword($row->id, $data['password']);
|
||||
}
|
||||
|
||||
$groupAccess = [];
|
||||
if ($data['group_arr']) {
|
||||
$checkGroups = [];
|
||||
foreach ($data['group_arr'] as $datum) {
|
||||
if (!in_array($datum, $row->group_arr)) {
|
||||
$checkGroups[] = $datum;
|
||||
}
|
||||
$groupAccess[] = [
|
||||
'uid' => $id,
|
||||
'group_id' => $datum,
|
||||
];
|
||||
}
|
||||
$this->checkGroupAuth($checkGroups);
|
||||
}
|
||||
|
||||
Db::name('admin_group_access')
|
||||
->where('uid', $id)
|
||||
->delete();
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
$result = $row->save($data);
|
||||
if ($groupAccess) Db::name('admin_group_access')->insertAll($groupAccess);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
|
||||
unset($row['salt'], $row['login_failure']);
|
||||
$row['password'] = '';
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function del(): void
|
||||
{
|
||||
$where = [];
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds) {
|
||||
$where[] = [$this->dataLimitField, 'in', $dataLimitAdminIds];
|
||||
}
|
||||
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
$where[] = [$this->model->getPk(), 'in', $ids];
|
||||
$data = $this->model->where($where)->select();
|
||||
|
||||
$count = 0;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
foreach ($data as $v) {
|
||||
if ($v->id != $this->auth->id) {
|
||||
$count += $v->delete();
|
||||
Db::name('admin_group_access')
|
||||
->where('uid', $v['id'])
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success(__('Deleted successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查分组权限
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function checkGroupAuth(array $groups): void
|
||||
{
|
||||
if ($this->auth->isSuperAdmin()) {
|
||||
return;
|
||||
}
|
||||
$authGroups = $this->auth->getAllAuthGroups('allAuthAndOthers');
|
||||
foreach ($groups as $group) {
|
||||
if (!in_array($group, $authGroups)) {
|
||||
$this->error(__('You have no permission to add an administrator to this group!'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
app/czg/auth/controller/AdminLogController.php
Normal file
54
app/czg/auth/controller/AdminLogController.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\auth\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\AdminLog as AdminLogModel;
|
||||
|
||||
class AdminLogController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var AdminLogModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected string|array $preExcludeFields = ['create_time', 'admin_id', 'username'];
|
||||
|
||||
protected string|array $quickSearchField = ['title'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new AdminLogModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
if (!$this->auth->isSuperAdmin()) {
|
||||
$where[] = ['admin_id', '=', $this->auth->id];
|
||||
}
|
||||
$res = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
379
app/czg/auth/controller/GroupController.php
Normal file
379
app/czg/auth/controller/GroupController.php
Normal file
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\auth\controller;
|
||||
|
||||
use ba\Tree;
|
||||
use Throwable;
|
||||
use think\facade\Db;
|
||||
use app\admin\model\AdminRule;
|
||||
use app\admin\model\AdminGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class GroupController extends Backend
|
||||
{
|
||||
/**
|
||||
* 修改、删除分组时对操作管理员进行鉴权
|
||||
* 本管理功能部分场景对数据权限有要求,修改此值请额外确定以下的 absoluteAuth 实现的功能
|
||||
* allAuthAndOthers=管理员拥有该分组所有权限并拥有额外权限时允许
|
||||
*/
|
||||
protected string $authMethod = 'allAuthAndOthers';
|
||||
|
||||
/**
|
||||
* 数据模型
|
||||
* @var object
|
||||
* @phpstan-var AdminGroup
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected string|array $preExcludeFields = ['create_time', 'update_time'];
|
||||
|
||||
protected string|array $quickSearchField = 'name';
|
||||
|
||||
/**
|
||||
* @var Tree
|
||||
*/
|
||||
protected Tree $tree;
|
||||
|
||||
/**
|
||||
* 远程select初始化传值
|
||||
* @var array
|
||||
*/
|
||||
protected array $initValue;
|
||||
|
||||
/**
|
||||
* 搜索关键词
|
||||
* @var string
|
||||
*/
|
||||
protected string $keyword;
|
||||
|
||||
/**
|
||||
* 是否组装Tree
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $assembleTree;
|
||||
|
||||
/**
|
||||
* 登录管理员的角色组
|
||||
* @var array
|
||||
*/
|
||||
protected array $adminGroups = [];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new AdminGroup();
|
||||
$this->tree = Tree::instance();
|
||||
|
||||
$isTree = $this->request->param('isTree', true);
|
||||
$this->initValue = $this->request->get("initValue/a", []);
|
||||
$this->initValue = array_filter($this->initValue);
|
||||
$this->keyword = $this->request->request("quickSearch", '');
|
||||
|
||||
// 有初始化值时不组装树状(初始化出来的值更好看)
|
||||
$this->assembleTree = $isTree && !$this->initValue;
|
||||
|
||||
$this->adminGroups = Db::name('admin_group_access')->where('uid', $this->auth->id)->column('group_id');
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $this->getGroups(),
|
||||
'group' => $this->adminGroups,
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data = $this->handleRules($data);
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
$validate->scene('add')->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$this->checkAuth($id);
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$adminGroup = Db::name('admin_group_access')->where('uid', $this->auth->id)->column('group_id');
|
||||
if (in_array($data['id'], $adminGroup)) {
|
||||
$this->error(__('You cannot modify your own management group!'));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data = $this->handleRules($data);
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
$validate->scene('edit')->check($data);
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
|
||||
// 读取所有pid,全部从节点数组移除,父级选择状态由子级决定
|
||||
$pidArr = AdminRule::field('pid')
|
||||
->distinct()
|
||||
->where('id', 'in', $row->rules)
|
||||
->select()
|
||||
->toArray();
|
||||
$rules = $row->rules ? explode(',', $row->rules) : [];
|
||||
foreach ($pidArr as $item) {
|
||||
$ruKey = array_search($item['pid'], $rules);
|
||||
if ($ruKey !== false) {
|
||||
unset($rules[$ruKey]);
|
||||
}
|
||||
}
|
||||
$row->rules = array_values($rules);
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function del(): void
|
||||
{
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
$data = $this->model->where($this->model->getPk(), 'in', $ids)->select();
|
||||
foreach ($data as $v) {
|
||||
$this->checkAuth($v->id);
|
||||
}
|
||||
$subData = $this->model->where('pid', 'in', $ids)->column('pid', 'id');
|
||||
foreach ($subData as $key => $subDatum) {
|
||||
if (!in_array($key, $ids)) {
|
||||
$this->error(__('Please delete the child element first, or use batch deletion'));
|
||||
}
|
||||
}
|
||||
|
||||
$adminGroup = Db::name('admin_group_access')->where('uid', $this->auth->id)->column('group_id');
|
||||
$count = 0;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
foreach ($data as $v) {
|
||||
if (!in_array($v['id'], $adminGroup)) {
|
||||
$count += $v->delete();
|
||||
}
|
||||
}
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success(__('Deleted successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程下拉
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function select(): void
|
||||
{
|
||||
$data = $this->getGroups([['status', '=', 1]]);
|
||||
|
||||
if ($this->assembleTree) {
|
||||
$data = $this->tree->assembleTree($this->tree->getTreeArray($data));
|
||||
}
|
||||
$this->success('', [
|
||||
'options' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限节点入库前处理
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function handleRules(array &$data): array
|
||||
{
|
||||
if (!empty($data['rules']) && is_array($data['rules'])) {
|
||||
$superAdmin = true;
|
||||
$checkedRules = [];
|
||||
$allRuleIds = AdminRule::column('id');
|
||||
|
||||
// 遍历检查权限ID是否存在(以免传递了可预测的未来权限ID号)
|
||||
foreach ($data['rules'] as $postRuleId) {
|
||||
if (in_array($postRuleId, $allRuleIds)) {
|
||||
$checkedRules[] = $postRuleId;
|
||||
}
|
||||
}
|
||||
|
||||
// 正在建立超管级分组?
|
||||
foreach ($allRuleIds as $ruleId) {
|
||||
if (!in_array($ruleId, $checkedRules)) {
|
||||
$superAdmin = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($superAdmin && $this->auth->isSuperAdmin()) {
|
||||
// 允许超管建立超管级分组
|
||||
$data['rules'] = '*';
|
||||
} else {
|
||||
// 当前管理员所拥有的权限节点
|
||||
$ownedRuleIds = $this->auth->getRuleIds();
|
||||
|
||||
// 禁止添加`拥有自己全部权限`的分组
|
||||
if (!array_diff($ownedRuleIds, $checkedRules)) {
|
||||
$this->error(__('Role group has all your rights, please contact the upper administrator to add or do not need to add!'));
|
||||
}
|
||||
|
||||
// 检查分组权限是否超出了自己的权限(超管的 $ownedRuleIds 为 ['*'],不便且可以不做此项检查)
|
||||
if (array_diff($checkedRules, $ownedRuleIds) && !$this->auth->isSuperAdmin()) {
|
||||
$this->error(__('The group permission node exceeds the range that can be allocated'));
|
||||
}
|
||||
|
||||
$data['rules'] = implode(',', $checkedRules);
|
||||
}
|
||||
} else {
|
||||
unset($data['rules']);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分组
|
||||
* @param array $where
|
||||
* @return array
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function getGroups(array $where = []): array
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$initKey = $this->request->get("initKey/s", $pk);
|
||||
|
||||
// 下拉选择时只获取:拥有所有权限并且有额外权限的分组
|
||||
$absoluteAuth = $this->request->get('absoluteAuth/b', false);
|
||||
|
||||
if ($this->keyword) {
|
||||
$keyword = explode(' ', $this->keyword);
|
||||
foreach ($keyword as $item) {
|
||||
$where[] = [$this->quickSearchField, 'like', '%' . $item . '%'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->initValue) {
|
||||
$where[] = [$initKey, 'in', $this->initValue];
|
||||
}
|
||||
|
||||
if (!$this->auth->isSuperAdmin()) {
|
||||
$authGroups = $this->auth->getAllAuthGroups($this->authMethod, $where);
|
||||
if (!$absoluteAuth) $authGroups = array_merge($this->adminGroups, $authGroups);
|
||||
$where[] = ['id', 'in', $authGroups];
|
||||
}
|
||||
$data = $this->model->where($where)->select()->toArray();
|
||||
|
||||
// 获取第一个权限的名称供列表显示-s
|
||||
foreach ($data as &$datum) {
|
||||
if ($datum['rules']) {
|
||||
if ($datum['rules'] == '*') {
|
||||
$datum['rules'] = __('Super administrator');
|
||||
} else {
|
||||
$rules = explode(',', $datum['rules']);
|
||||
if ($rules) {
|
||||
$rulesFirstTitle = AdminRule::where('id', $rules[0])->value('title');
|
||||
$datum['rules'] = count($rules) == 1 ? $rulesFirstTitle : $rulesFirstTitle . '等 ' . count($rules) . ' 项';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$datum['rules'] = __('No permission');
|
||||
}
|
||||
}
|
||||
// 获取第一个权限的名称供列表显示-e
|
||||
|
||||
// 如果要求树状,此处先组装好 children
|
||||
return $this->assembleTree ? $this->tree->assembleChild($data) : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查权限
|
||||
* @param $groupId
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function checkAuth($groupId): void
|
||||
{
|
||||
$authGroups = $this->auth->getAllAuthGroups($this->authMethod, []);
|
||||
if (!$this->auth->isSuperAdmin() && !in_array($groupId, $authGroups)) {
|
||||
$this->error(__($this->authMethod == 'allAuth' ? 'You need to have all permissions of this group to operate this group~' : 'You need to have all the permissions of the group and have additional permissions before you can operate the group~'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
274
app/czg/auth/controller/RuleController.php
Normal file
274
app/czg/auth/controller/RuleController.php
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\auth\controller;
|
||||
|
||||
use ba\Tree;
|
||||
use Throwable;
|
||||
use app\admin\model\AdminRule;
|
||||
use app\admin\model\AdminGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class RuleController extends Backend
|
||||
{
|
||||
protected string|array $preExcludeFields = ['create_time', 'update_time'];
|
||||
|
||||
protected string|array $defaultSortField = ['weigh' => 'desc'];
|
||||
|
||||
protected string|array $quickSearchField = 'title';
|
||||
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var AdminRule
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
/**
|
||||
* @var Tree
|
||||
*/
|
||||
protected Tree $tree;
|
||||
|
||||
/**
|
||||
* 远程select初始化传值
|
||||
* @var array
|
||||
*/
|
||||
protected array $initValue;
|
||||
|
||||
/**
|
||||
* 搜索关键词
|
||||
* @var string
|
||||
*/
|
||||
protected string $keyword;
|
||||
|
||||
/**
|
||||
* 是否组装Tree
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $assembleTree;
|
||||
|
||||
/**
|
||||
* 开启模型验证
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $modelValidate = false;
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
// 防止 URL 中的特殊符号被默认的 filter 函数转义
|
||||
$this->request->filter('clean_xss');
|
||||
|
||||
$this->model = new AdminRule();
|
||||
$this->tree = Tree::instance();
|
||||
$isTree = $this->request->param('isTree', true);
|
||||
$this->initValue = $this->request->get('initValue/a', []);
|
||||
$this->initValue = array_filter($this->initValue);
|
||||
$this->keyword = $this->request->request('quickSearch', '');
|
||||
$this->assembleTree = $isTree && !$this->initValue; // 有初始化值时不组装树状(初始化出来的值更好看)
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $this->getMenus(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
|
||||
$data[$this->dataLimitField] = $this->auth->id;
|
||||
}
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
|
||||
// 检查所有非超管的分组是否应该拥有此权限
|
||||
if (!empty($data['pid'])) {
|
||||
$groups = AdminGroup::where('rules', '<>', '*')->select();
|
||||
foreach ($groups as $group) {
|
||||
$rules = explode(',', $group->rules);
|
||||
if (in_array($data['pid'], $rules) && !in_array($this->model->id, $rules)) {
|
||||
$rules[] = $this->model->id;
|
||||
$group->rules = implode(',', $rules);
|
||||
$group->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$id = $this->request->param($this->model->getPk());
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('edit');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
if (isset($data['pid']) && $data['pid'] > 0) {
|
||||
// 满足意图并消除副作用
|
||||
$parent = $this->model->where('id', $data['pid'])->find();
|
||||
if ($parent['pid'] == $row['id']) {
|
||||
$parent->pid = 0;
|
||||
$parent->save();
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function del(): void
|
||||
{
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
|
||||
// 子级元素检查
|
||||
$subData = $this->model->where('pid', 'in', $ids)->column('pid', 'id');
|
||||
foreach ($subData as $key => $subDatum) {
|
||||
if (!in_array($key, $ids)) {
|
||||
$this->error(__('Please delete the child element first, or use batch deletion'));
|
||||
}
|
||||
}
|
||||
|
||||
parent::del();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写select方法
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function select(): void
|
||||
{
|
||||
$data = $this->getMenus([['type', 'in', ['menu_dir', 'menu']], ['status', '=', 1]]);
|
||||
|
||||
if ($this->assembleTree) {
|
||||
$data = $this->tree->assembleTree($this->tree->getTreeArray($data, 'title'));
|
||||
}
|
||||
$this->success('', [
|
||||
'options' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单列表
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected function getMenus($where = []): array
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$initKey = $this->request->get("initKey/s", $pk);
|
||||
|
||||
$ids = $this->auth->getRuleIds();
|
||||
|
||||
// 如果没有 * 则只获取用户拥有的规则
|
||||
if (!in_array('*', $ids)) {
|
||||
$where[] = ['id', 'in', $ids];
|
||||
}
|
||||
|
||||
if ($this->keyword) {
|
||||
$keyword = explode(' ', $this->keyword);
|
||||
foreach ($keyword as $item) {
|
||||
$where[] = [$this->quickSearchField, 'like', '%' . $item . '%'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->initValue) {
|
||||
$where[] = [$initKey, 'in', $this->initValue];
|
||||
}
|
||||
|
||||
// 读取用户组所有权限规则
|
||||
$rules = $this->model
|
||||
->where($where)
|
||||
->order($this->queryOrderBuilder())
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 如果要求树状,此处先组装好 children
|
||||
return $this->assembleTree ? $this->tree->assembleChild($rules) : $rules;
|
||||
}
|
||||
}
|
||||
217
app/czg/controller/AjaxController.php
Normal file
217
app/czg/controller/AjaxController.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\Terminal;
|
||||
use think\Response;
|
||||
use ba\TableManager;
|
||||
use think\facade\Db;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Event;
|
||||
use app\admin\model\AdminLog;
|
||||
use app\common\library\Upload;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class AjaxController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['*'];
|
||||
|
||||
/**
|
||||
* 无需登录的方法
|
||||
* terminal 内部自带验权
|
||||
*/
|
||||
protected array $noNeedLogin = ['terminal'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function upload(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('upload'));
|
||||
$file = $this->request->file('file');
|
||||
$driver = $this->request->param('driver', 'local');
|
||||
$topic = $this->request->param('topic', 'default');
|
||||
try {
|
||||
$upload = new Upload();
|
||||
$attachment = $upload
|
||||
->setFile($file)
|
||||
->setDriver($driver)
|
||||
->setTopic($topic)
|
||||
->upload(null, $this->auth->id);
|
||||
unset($attachment['create_time'], $attachment['quote']);
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$this->success(__('File uploaded successfully'), [
|
||||
'file' => $attachment ?? []
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取省市区数据
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function area(): void
|
||||
{
|
||||
$this->success('', get_area());
|
||||
}
|
||||
|
||||
public function buildSuffixSvg(): Response
|
||||
{
|
||||
$suffix = $this->request->param('suffix', 'file');
|
||||
$background = $this->request->param('background');
|
||||
$content = build_suffix_svg((string)$suffix, (string)$background);
|
||||
return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/svg+xml');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已脱敏的数据库连接配置列表
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getDatabaseConnectionList(): void
|
||||
{
|
||||
$quickSearch = $this->request->get("quickSearch/s", '');
|
||||
$connections = config('database.connections');
|
||||
$desensitization = [];
|
||||
foreach ($connections as $key => $connection) {
|
||||
$connection = TableManager::getConnectionConfig($key);
|
||||
$desensitization[] = [
|
||||
'type' => $connection['type'],
|
||||
'database' => substr_replace($connection['database'], '****', 1, strlen($connection['database']) > 4 ? 2 : 1),
|
||||
'key' => $key,
|
||||
];
|
||||
}
|
||||
|
||||
if ($quickSearch) {
|
||||
$desensitization = array_filter($desensitization, function ($item) use ($quickSearch) {
|
||||
return preg_match("/$quickSearch/i", $item['key']);
|
||||
});
|
||||
$desensitization = array_values($desensitization);
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $desensitization,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表主键字段
|
||||
* @param ?string $table
|
||||
* @param ?string $connection
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getTablePk(?string $table = null, ?string $connection = null): void
|
||||
{
|
||||
if (!$table) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$table = TableManager::tableName($table, true, $connection);
|
||||
if (!TableManager::phinxAdapter(false, $connection)->hasTable($table)) {
|
||||
$this->error(__('Data table does not exist'));
|
||||
}
|
||||
|
||||
$tablePk = Db::connect(TableManager::getConnection($connection))
|
||||
->table($table)
|
||||
->getPk();
|
||||
$this->success('', ['pk' => $tablePk]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据表列表
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getTableList(): void
|
||||
{
|
||||
$quickSearch = $this->request->get("quickSearch/s", '');
|
||||
$connection = $this->request->request('connection');// 数据库连接配置标识
|
||||
$samePrefix = $this->request->request('samePrefix/b', true);// 是否仅返回项目数据表(前缀同项目一致的)
|
||||
$excludeTable = $this->request->request('excludeTable/a', []);// 要排除的数据表数组(表名无需带前缀)
|
||||
|
||||
$outTables = [];
|
||||
$dbConfig = TableManager::getConnectionConfig($connection);
|
||||
$tables = TableManager::getTableList($connection);
|
||||
|
||||
if ($quickSearch) {
|
||||
$tables = array_filter($tables, function ($comment) use ($quickSearch) {
|
||||
return preg_match("/$quickSearch/i", $comment);
|
||||
});
|
||||
}
|
||||
|
||||
$pattern = '/^' . $dbConfig['prefix'] . '/i';
|
||||
foreach ($tables as $table => $comment) {
|
||||
if ($samePrefix && !preg_match($pattern, $table)) continue;
|
||||
|
||||
$table = preg_replace($pattern, '', $table);
|
||||
if (!in_array($table, $excludeTable)) {
|
||||
$outTables[] = [
|
||||
'table' => $table,
|
||||
'comment' => $comment,
|
||||
'connection' => $connection,
|
||||
'prefix' => $dbConfig['prefix'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $outTables,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据表字段列表
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getTableFieldList(): void
|
||||
{
|
||||
$table = $this->request->param('table');
|
||||
$clean = $this->request->param('clean', true);
|
||||
$connection = $this->request->request('connection');
|
||||
if (!$table) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
$connection = TableManager::getConnection($connection);
|
||||
$tablePk = Db::connect($connection)->name($table)->getPk();
|
||||
$this->success('', [
|
||||
'pk' => $tablePk,
|
||||
'fieldList' => TableManager::getTableColumns($table, $clean, $connection),
|
||||
]);
|
||||
}
|
||||
|
||||
public function changeTerminalConfig(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Change terminal config'));
|
||||
if (Terminal::changeTerminalConfig()) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('Failed to modify the terminal configuration. Please modify the configuration file manually:%s', ['/config/buildadmin.php']));
|
||||
}
|
||||
}
|
||||
|
||||
public function clearCache(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Clear cache'));
|
||||
$type = $this->request->post('type');
|
||||
if ($type == 'tp' || $type == 'all') {
|
||||
Cache::clear();
|
||||
} else {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
Event::trigger('cacheClearAfter', $this->app);
|
||||
$this->success(__('Cache cleaned~'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 终端
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function terminal(): void
|
||||
{
|
||||
(new Terminal())->exec();
|
||||
}
|
||||
}
|
||||
116
app/czg/controller/AliossController.php
Normal file
116
app/czg/controller/AliossController.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use OSS\Core\OssException;
|
||||
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
|
||||
use OSS\OssClient;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
use AlibabaCloud\Client\AlibabaCloud;
|
||||
use AlibabaCloud\Client\Exception\ClientException;
|
||||
use AlibabaCloud\Client\Exception\ServerException;
|
||||
class AliossController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function upload()
|
||||
{
|
||||
$file = request()->file('file');
|
||||
if(empty($file)) {
|
||||
$this->error('参数不能为空');
|
||||
}
|
||||
$commoninfo = Db::connect(config('database.search_library'));
|
||||
$endpoint = $commoninfo->name('common_info')->where(['type' => 68])->find()['value'];
|
||||
$accessKeyId = $commoninfo->name('common_info')->where(['type' => 69])->find()['value'];
|
||||
$secretAccessKey = $commoninfo->name('common_info')->where(['type' => 70])->find()['value'];
|
||||
$bucket = $commoninfo->name('common_info')->where(['type' => 71])->find()['value'];
|
||||
$befor_url = $commoninfo->name('common_info')->where(['type' => 72])->find()['value'];
|
||||
|
||||
putenv('OSS_ACCESS_KEY_ID=' . $accessKeyId);
|
||||
putenv('OSS_ACCESS_KEY_SECRET='. $secretAccessKey);
|
||||
$provider = new EnvironmentVariableCredentialsProvider();
|
||||
|
||||
$object = date('Ymd') . '/' . uniqid() . '.' .$file->getOriginalExtension();
|
||||
try{
|
||||
$config = array(
|
||||
"provider" => $provider,
|
||||
"endpoint" => $endpoint,
|
||||
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V1,
|
||||
);
|
||||
$ossClient = new OssClient($config);
|
||||
// 以二进制模式读取文件内容
|
||||
$handle = fopen($file->getRealPath(), 'rb');
|
||||
$content = stream_get_contents($handle);
|
||||
fclose($handle);
|
||||
|
||||
// 上传二进制内容,明确指定Content-Type
|
||||
$options = [
|
||||
OssClient::OSS_CONTENT_LENGTH => strlen($content),
|
||||
OssClient::OSS_CONTENT_TYPE => $file->getMime(),
|
||||
// 禁用字符编码转换
|
||||
'Content-Encoding' => 'binary',
|
||||
];
|
||||
$res = $ossClient->putObject($bucket, $object, $content, $options);
|
||||
Log::write('上传文件结果' . json_encode($res));
|
||||
if(!empty($res['info'])) {
|
||||
return $this->ApiDataReturn(['data' => $befor_url . '/' . $object, 'msg' => 'success', 'code' => 0]);
|
||||
}else {
|
||||
$this->error('上传失败');
|
||||
}
|
||||
} catch(OssException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取阿里云oss存储相关配置
|
||||
public function getCredentials()
|
||||
{
|
||||
$commoninfo = Db::connect(config('database.search_library'));
|
||||
$configItems = $commoninfo->name('common_info')->whereIn('type', [66, 67, 69, 70])
|
||||
->column('value', 'type');
|
||||
AlibabaCloud::accessKeyClient($configItems[69], $configItems[70])
|
||||
->regionId('cn-nanjing')
|
||||
->asDefaultClient();
|
||||
try {
|
||||
$result = AlibabaCloud::rpc()->product('Sts')
|
||||
->options([
|
||||
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V1
|
||||
])
|
||||
->version('2015-04-01')
|
||||
->action('AssumeRole')
|
||||
->method('POST')
|
||||
->host($configItems[66]) // Endpoint
|
||||
->scheme('https')
|
||||
->options([
|
||||
'query' => [
|
||||
'RoleArn' => $configItems[67], // 角色ARN
|
||||
'RoleSessionName' => 'test', // 会话名称
|
||||
'DurationSeconds' => 3600, // 凭证有效期(秒)
|
||||
],
|
||||
])
|
||||
->request();
|
||||
// 获取响应中的凭证信息。
|
||||
$credentials = $result['Credentials'];
|
||||
$this->n_success(['data' => [
|
||||
'accessKeyId' => $credentials['AccessKeyId'],
|
||||
'accessKeySecret' => $credentials['AccessKeySecret'],
|
||||
'expiration' => $credentials['Expiration'],
|
||||
'securityToken' => $credentials['SecurityToken'],
|
||||
]]);
|
||||
} catch (ClientException $e) {
|
||||
// 处理客户端异常。
|
||||
echo $e->getErrorMessage() . PHP_EOL;
|
||||
} catch (ServerException $e) {
|
||||
// 处理服务端异常。
|
||||
echo $e->getErrorMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
70
app/czg/controller/AnnouncementController.php
Normal file
70
app/czg/controller/AnnouncementController.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class AnnouncementController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$where = [];
|
||||
if (!empty($params['title'])) {
|
||||
$where[] = ['title', '=', $params['title']];
|
||||
}
|
||||
|
||||
if (!empty($params['type'])) {
|
||||
$where[] = ['type', '=', $params['type']];
|
||||
}
|
||||
|
||||
if (!empty($params['state'])) {
|
||||
$where[] = ['state', '=', $params['state']];
|
||||
}
|
||||
|
||||
if (!empty($params['id'])) {
|
||||
$where[] = ['id', '=', $params['id']];
|
||||
}
|
||||
|
||||
$this->successWithData(apiconvertToCamelCase(Db::name('announcement')->where($where)->select()->toArray()));
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['create_time'] = getNormalDate();
|
||||
Db::name('announcement')->insert($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
Db::name('announcement')->where([
|
||||
'id' => $params['id']
|
||||
])->update($params);
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$id = $this->request->post('id');
|
||||
Db::name('announcement')->delete([
|
||||
'id' => $id
|
||||
]);
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
48
app/czg/controller/AppinfoController.php
Normal file
48
app/czg/controller/AppinfoController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class AppinfoController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$list = Db::name('app')->paginate([
|
||||
'page' => $params['page'],
|
||||
'list_rows' => $params['limit']
|
||||
]);
|
||||
$this->successWithData([
|
||||
'records' => convertToCamelCase($list->items()), // 当前页数据
|
||||
'totalCount' => $list->total(), // 总记录数
|
||||
'currPage' => $list->currentPage(),
|
||||
'last_page' => $list->lastPage(),
|
||||
'pageSize' => $params['limit']
|
||||
]);
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
if (empty($params['id'])) {
|
||||
$params['create_at'] = getNormalDate();
|
||||
Db::name('app')->insert($params);
|
||||
}else {
|
||||
Db::name('app')->where([
|
||||
'id' => $params['id']
|
||||
])->update($params);
|
||||
}
|
||||
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
99
app/czg/controller/BannerController.php
Normal file
99
app/czg/controller/BannerController.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class BannerController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
public function selectBannerPage()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$info = cache('banner'.$params['page'].$params['limit']);
|
||||
if ($info) {
|
||||
$this->successWithData($info);
|
||||
}
|
||||
$info = DatabaseRoute::paginateDb('banner', function ($query) use ($params) {
|
||||
if (!empty($params['classify'])) {
|
||||
$query->where([
|
||||
'classify' => $params['classify']
|
||||
]);
|
||||
}
|
||||
|
||||
if (!empty($params['state'])) {
|
||||
// $query->where([
|
||||
// 'state' => $params['state']
|
||||
// ]);
|
||||
}
|
||||
return $query;
|
||||
}, $params['page'], $params['limit']);
|
||||
cache('banner'.$params['page'].$params['limit'], $info, -1);
|
||||
$this->successWithData($info);
|
||||
|
||||
}
|
||||
|
||||
public function updateBannerById()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
unset($params['course']);
|
||||
Db::name('banner')->where([
|
||||
'id' => $params['id']
|
||||
])->update($params);
|
||||
deleteRedisKeysByPattern('banner*');
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function insertBanner()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['state'] = 2;
|
||||
$params['create_time'] = getNormalDate();
|
||||
unset($params['id']);
|
||||
Db::name('banner')->insert($params);
|
||||
deleteRedisKeysByPattern('banner*');
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
public function deleteBannerById()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$params['ids'] = explode(',', $params['ids']);
|
||||
foreach ($params['ids'] as $id) {
|
||||
Db::name('banner')->delete([
|
||||
'id' => $id
|
||||
]);
|
||||
}
|
||||
deleteRedisKeysByPattern('banner*');
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
// 隐藏banner图
|
||||
public function updateBannerStateById()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['id'])) {
|
||||
$this->error('参数不玩这');
|
||||
}
|
||||
$id = $get['id'];
|
||||
$banner = Db::connect(get_slave_connect_name())->name('banner')->where(['id' => $id])->find();
|
||||
if(!$banner) {
|
||||
$this->error('记录不存在');
|
||||
}
|
||||
Db::connect(get_master_connect_name())->name('banner')->where(['id' => $id])->update([
|
||||
'state' => $banner['state'] == 1 ? 2 : 1,
|
||||
]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
270
app/czg/controller/CashController.php
Normal file
270
app/czg/controller/CashController.php
Normal file
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\PayDetails;
|
||||
use app\api\model\CommonInfo;
|
||||
use app\api\model\WithDraw;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\exception\SysException;
|
||||
use think\facade\Db;
|
||||
|
||||
class CashController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
public function selectUserRechargeByUserId()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$this->successWithData(DatabaseRoute::paginateAllDb('pay_details', function ($query) use ($params) {
|
||||
$query->alias('s')
|
||||
->leftJoin('tb_user u', 'u.user_id = s.user_id')
|
||||
->field([
|
||||
's.id', 's.classify',
|
||||
's.order_id' => 'orderId',
|
||||
's.money',
|
||||
's.user_id' => 'userId',
|
||||
's.pay_diamond' => 'payDiamond',
|
||||
's.diamond',
|
||||
's.state',
|
||||
's.create_time' => 'createTime',
|
||||
's.pay_time' => 'payTime',
|
||||
'u.user_name' => 'userName',
|
||||
'u.phone',
|
||||
]);
|
||||
// 动态条件拼接
|
||||
if (!empty($params['startTime']) && !empty($params['endTime'])) {
|
||||
$query->whereBetween('s.create_time', [$params['startTime'], $params['endTime']]);
|
||||
}
|
||||
|
||||
if (!empty($params['userName'])) {
|
||||
$query->whereLike('u.user_name', '%' . $params['userName'] . '%');
|
||||
}
|
||||
|
||||
if (!empty($params['orderId'])) {
|
||||
$query->whereLike('s.order_id', '%' . $params['orderId'] . '%');
|
||||
}
|
||||
|
||||
if (isset($params['userId'])) {
|
||||
$query->where('u.user_id', $params['userId']);
|
||||
}
|
||||
|
||||
if (isset($params['state']) && $params['state'] !== -1) {
|
||||
$query->where('s.state', $params['state']);
|
||||
} else {
|
||||
$query->where('s.state', '<>', -1);
|
||||
}
|
||||
|
||||
|
||||
return $query;
|
||||
}, $params['page'], $params['limit'], 's.create_time'));
|
||||
}
|
||||
|
||||
|
||||
public function statisticsIncomeMoney()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
// 调用统计服务方法
|
||||
$sumMoney = \app\admin\model\Cash::statisticsIncomeMoney($get['time'], $get['flag'], null);
|
||||
$courseMoney = \app\admin\model\Cash::statisticsIncomeMoney($get['time'], $get['flag'], 1);
|
||||
$vipMoney = \app\admin\model\Cash::statisticsIncomeMoney($get['time'], $get['flag'], 2);
|
||||
|
||||
// 构建返回数据
|
||||
$map = [
|
||||
'sumMoney' => is_null($sumMoney) ? 0.00 : $sumMoney,
|
||||
'courseMoney' => is_null($courseMoney) ? 0.00 : $courseMoney,
|
||||
'vipMoney' => is_null($vipMoney) ? 0.00 : $vipMoney
|
||||
];
|
||||
$this->n_success(['data' => $map]); ;
|
||||
}
|
||||
|
||||
// 财务提现统计
|
||||
public function statisticsCashMoney()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$time = $get['time'];
|
||||
$flag = $get['flag'];
|
||||
// 验证时间格式并转换为时间戳
|
||||
$timestamp = strtotime($time);
|
||||
if ($timestamp === false) {
|
||||
$this->error('无效的时间格式,请使用 yyyy-MM-dd 格式');
|
||||
}
|
||||
|
||||
// 初始化开始和结束时间(默认按日)
|
||||
$startTime = date('Y-m-d 00:00:00', $timestamp);
|
||||
$endTime = date('Y-m-d 23:59:59', $timestamp);
|
||||
|
||||
// 根据flag调整时间范围
|
||||
if ($flag == 2) {
|
||||
// 按月:当月第一天 00:00:00 至 当月最后一天 23:59:59
|
||||
$startTime = date('Y-m-01 00:00:00', $timestamp); // 当月1号
|
||||
$lastDay = date('t', $timestamp); // 获取当月总天数(t是原生格式化符)
|
||||
$endTime = date('Y-m-' . $lastDay . ' 23:59:59', $timestamp);
|
||||
} elseif ($flag == 3) {
|
||||
// 按年:当年第一天 00:00:00 至 当年最后一天 23:59:59
|
||||
$startTime = date('Y-01-01 00:00:00', $timestamp); // 当年1月1号
|
||||
$endTime = date('Y-12-31 23:59:59', $timestamp); // 当年12月31号
|
||||
}
|
||||
|
||||
$sumMoney = DatabaseRoute::getAllDbData('cash_out', function($query) use ($startTime, $endTime) {
|
||||
$query->where(['state' => 1]);
|
||||
$query->whereBetween('create_at', [$startTime, $endTime]);
|
||||
return $query;
|
||||
})->sum('money');
|
||||
|
||||
$countMoney = DatabaseRoute::getAllDbData('cash_out', function($query) use ($startTime, $endTime) {
|
||||
$query->whereBetween('create_at', [$startTime, $endTime]);
|
||||
return $query;
|
||||
})->count();
|
||||
|
||||
$stayMoney = DatabaseRoute::getAllDbData('cash_out', function($query) use ($startTime, $endTime) {
|
||||
$query->where(['state' => 0]);
|
||||
$query->whereBetween('create_at', [$startTime, $endTime]);
|
||||
return $query;
|
||||
})->count();
|
||||
|
||||
$map = [
|
||||
// 金额字段,若为null则赋值0.00(保留两位小数)
|
||||
'sumMoney' => is_null($sumMoney) ? 0.00 : (float)$sumMoney,
|
||||
// 计数字段,若为null则赋值0(整数)
|
||||
'countMoney' => is_null($countMoney) ? 0 : (int)$countMoney,
|
||||
// 待处理金额字段,处理逻辑同上
|
||||
'stayMoney' => is_null($stayMoney) ? 0 : (int)$stayMoney
|
||||
];
|
||||
$this->n_success(['data' => $map]);
|
||||
}
|
||||
|
||||
// 查询所有用户充值信息列表
|
||||
public function selectUserRecharge()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(!empty($get['state']) && $get['state'] == -1) {
|
||||
$get['state'] = null;
|
||||
}
|
||||
$get['startTime'] = date('Y-m-d 00:00:00', strtotime($get['startTime']));
|
||||
$get['endTime'] = date('Y-m-d 23:59:59', strtotime($get['endTime']));
|
||||
$this->n_success(['data' => \app\admin\model\Cash::selectPayDetails($get)]);
|
||||
}
|
||||
|
||||
|
||||
public function payMember()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$time = $get['time'];$flag = $get['flag'];$payClassify = empty($get['payClassify'])?null:$get['payClassify'];
|
||||
// 1. 统计总支付金额(不指定分类)
|
||||
$sumMoney = PayDetails::selectSumPayByClassify(null, $flag, $time, $payClassify);
|
||||
|
||||
// 2. 按支付渠道分别统计(1-8对应不同渠道)
|
||||
$channelMoneys = [
|
||||
1 => PayDetails::selectSumPayByClassify(1, $flag, $time, $payClassify), // 微信App
|
||||
2 => PayDetails::selectSumPayByClassify(2, $flag, $time, $payClassify), // 微信公众号
|
||||
3 => PayDetails::selectSumPayByClassify(3, $flag, $time, $payClassify), // 微信小程序
|
||||
4 => PayDetails::selectSumPayByClassify(4, $flag, $time, $payClassify), // 支付宝App
|
||||
5 => PayDetails::selectSumPayByClassify(5, $flag, $time, $payClassify), // 支付宝H5
|
||||
6 => PayDetails::selectSumPayByClassify(6, $flag, $time, $payClassify), // 抖音
|
||||
7 => PayDetails::selectSumPayByClassify(7, $flag, $time, $payClassify), // 苹果
|
||||
8 => PayDetails::selectSumPayByClassify(8, $flag, $time, $payClassify) // 快手
|
||||
];
|
||||
|
||||
// 3. 构建结果映射(处理null值,默认为0.00)
|
||||
$result = [
|
||||
'sumMoney' => $sumMoney ?? 0.00,
|
||||
'weiXinAppMoney' => $channelMoneys[1] ?? 0.00,
|
||||
'weiXinGZHMoney' => $channelMoneys[2] ?? 0.00,
|
||||
'weiXinXCXMoney' => $channelMoneys[3] ?? 0.00,
|
||||
'zhiFuBaoAppMoney' => $channelMoneys[4] ?? 0.00,
|
||||
'zhiFuBaoH5Money' => $channelMoneys[5] ?? 0.00,
|
||||
'dyMoney' => $channelMoneys[6] ?? 0.00,
|
||||
'iosMoney' => $channelMoneys[7] ?? 0.00,
|
||||
'ksMoney' => $channelMoneys[8] ?? 0.00
|
||||
];
|
||||
$this->n_success(['data' => $result]);
|
||||
}
|
||||
|
||||
public static function send($userInfo, $title, $content)
|
||||
{
|
||||
if (!empty($userInfo['client_id'])) {
|
||||
|
||||
}
|
||||
|
||||
Db::name('message_info')->insert([
|
||||
'content' => $content,
|
||||
'title' => $title,
|
||||
'state' => 5,
|
||||
'is_see' => 0,
|
||||
'user_name' => $userInfo['user_name'],
|
||||
'user_id' => $userInfo['user_id']
|
||||
]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function sendMsg()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
if ($params['flag'] == 1) {
|
||||
$userInfo = DatabaseRoute::getAllDbData('tb_user', function ($query) use ($params) {
|
||||
return $query->where([
|
||||
'phone' => $params['phone']
|
||||
]);
|
||||
})->find();
|
||||
|
||||
if (!$userInfo) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
$this->send($userInfo, $params['title'], $params['content']);
|
||||
|
||||
}else{
|
||||
$userList = DatabaseRoute::getAllDbData('tb_user', function ($query) use ($params) {
|
||||
return $query;
|
||||
})->list();
|
||||
$chunks = array_chunk($userList, ceil(count($userList) / 3));
|
||||
pushQueue($chunks[0]);
|
||||
pushQueue($chunks[1]);
|
||||
pushQueue($chunks[2]);
|
||||
|
||||
}
|
||||
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 用户提现记录
|
||||
public function selectPayDetails()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$cashOut = [];
|
||||
if(isset($get['userId'])) {
|
||||
$cashOut['userId'] = $get['userId'];
|
||||
}
|
||||
$res = \app\admin\model\Cash::selectCashOutList($get['page'], $get['limit'], $cashOut);
|
||||
$this->n_success(['data' => $res]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提现接口
|
||||
*/
|
||||
public function withdraw()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$userId = $get['userId'] ?? null;
|
||||
$money = $get['money'] ?? null;
|
||||
$msg = $get['msg'] ?? null;
|
||||
// 验证验证码是否为空
|
||||
if (empty($msg)) {
|
||||
$this->error('请输入验证码');
|
||||
}
|
||||
debounce("withdraw:".$userId, 30);
|
||||
runWithLock("lock:withdraw:{$userId}", 300, function () use ($userId, $money, $msg) {
|
||||
WithDraw::goWithDraw($userId, $money, $msg, true, true);
|
||||
});
|
||||
$this->success('提现成功,将在三个工作日内到账,请耐心等待!');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
325
app/czg/controller/CashOutAuditController.php
Normal file
325
app/czg/controller/CashOutAuditController.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\facade\Token;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\utils\WuYouPayUtils;
|
||||
use extend\ba\Random;
|
||||
use think\facade\Db;
|
||||
use think\Collection;
|
||||
|
||||
class CashOutAuditController extends Backend
|
||||
{
|
||||
|
||||
protected array $noNeedPermission = ['page', 'alipaytransfersummaryquery'];
|
||||
|
||||
// 提现列表
|
||||
public function page()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$cashOut = [];
|
||||
if (!empty($params)) {
|
||||
$cashOut = array_intersect_key($params, array_flip([
|
||||
'user_id', 'user_name', 'zhifubao_name', 'zhifubao',
|
||||
'bank_name', 'user_type', 'state', 'start_time', 'end_time'
|
||||
]));
|
||||
}
|
||||
$cashOutList = DatabaseRoute::paginateAllDb('cash_out', function ($query) use($cashOut) {
|
||||
if (!empty($cashOut['user_id'])) {
|
||||
$query->where('user_id', $cashOut['user_id']);
|
||||
}
|
||||
// 用户名模糊查询(对应Java的userName匹配zhifubaoName)
|
||||
if (!empty($cashOut['user_name'])) {
|
||||
$query->whereLike('zhifubao_name', "%{$cashOut['user_name']}%");
|
||||
}
|
||||
// 支付宝姓名模糊查询
|
||||
if (!empty($cashOut['zhifubao_name'])) {
|
||||
$query->whereLike('zhifubao_name', "%{$cashOut['zhifubao_name']}%");
|
||||
}
|
||||
// 支付宝账号模糊查询
|
||||
if (!empty($cashOut['zhifubao'])) {
|
||||
$query->whereLike('zhifubao', "%{$cashOut['zhifubao']}%");
|
||||
}
|
||||
// 银行名称模糊查询
|
||||
if (!empty($cashOut['bank_name'])) {
|
||||
$query->whereLike('bank_name', "%{$cashOut['bank_name']}%");
|
||||
}
|
||||
// 用户类型条件
|
||||
if (isset($cashOut['user_type']) && $cashOut['user_type'] !== '') {
|
||||
$query->where('user_type', $cashOut['user_type']);
|
||||
}
|
||||
// 状态条件
|
||||
if (isset($cashOut['state']) && $cashOut['state'] !== '') {
|
||||
$query->where('state', $cashOut['state']);
|
||||
}
|
||||
// 时间范围条件
|
||||
$startTime = isset($cashOut['start_time']) ? $cashOut['start_time'] : '';
|
||||
$endTime = isset($cashOut['end_time']) ? $cashOut['end_time'] : '';
|
||||
if ($startTime && $endTime) {
|
||||
$query->whereBetween('create_at', $startTime, $endTime);
|
||||
} elseif ($startTime) {
|
||||
$query->where('create_at', '>=', $startTime);
|
||||
} elseif ($endTime) {
|
||||
$query->where('create_at', '<=', $endTime);
|
||||
}
|
||||
return $query;
|
||||
}, $params['page'], $params['limit'], 'create_at');
|
||||
|
||||
// 补充关联数据
|
||||
if (!empty($cashOutList['list'])) {
|
||||
// 提取所有用户ID
|
||||
$userIdList = Collection::make($cashOutList['list'])->column('user_id');
|
||||
$userIdList = array_unique(array_filter($userIdList)); // 去重并过滤空值
|
||||
if($userIdList) {
|
||||
$countInfoList_n = [];
|
||||
foreach ($userIdList as $k => $user_id) {
|
||||
$db_name = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $user_id]));
|
||||
$userNameMap[] = $db_name->name('tb_user')->where(['user_id' => $user_id])->field('user_id, user_name')
|
||||
->select()
|
||||
->column('user_name', 'user_id');
|
||||
|
||||
$countInfoList[] = $db_name
|
||||
->query("SELECT user_id as userId,
|
||||
ROUND(SUM(CASE WHEN state = 1 THEN money ELSE 0 END), 2) AS total,
|
||||
COUNT(CASE WHEN state = 1 THEN 1 END) AS count,
|
||||
ROUND(SUM(CASE WHEN state = 3 THEN money ELSE 0 END), 2) AS verifyTotal,
|
||||
COUNT(CASE WHEN state = 3 THEN 1 END) AS verifyCount
|
||||
FROM cash_out
|
||||
WHERE user_id=" . $user_id . "
|
||||
GROUP BY user_id")[0];
|
||||
}
|
||||
$countInfoMap = [];
|
||||
foreach ($countInfoList as $item) {
|
||||
|
||||
$countInfoMap[$item['userId']] = $item;
|
||||
}
|
||||
|
||||
// 补充字段到结果集
|
||||
foreach ($cashOutList['list'] as &$item) {
|
||||
// 补充用户名
|
||||
$item['user_name'] = $userNameMap[$item['user_id']] ?? '';
|
||||
|
||||
// 补充统计信息
|
||||
if (isset($countInfoMap[$item['user_id']])) {
|
||||
$countInfo = $countInfoMap[$item['user_id']];
|
||||
$item['total'] = $countInfo['total'];
|
||||
$item['count'] = $countInfo['count'];
|
||||
$item['verify_count'] = $countInfo['verifyCount'];
|
||||
$item['verify_total'] = $countInfo['verifyTotal'];
|
||||
} else {
|
||||
$item['total'] = 0;
|
||||
$item['count'] = 0;
|
||||
$item['verify_count'] = 0;
|
||||
$item['verify_total'] = 0;
|
||||
}
|
||||
}
|
||||
unset($item); // 解除引用
|
||||
}
|
||||
}
|
||||
$this->n_success(['page' => $cashOutList]);
|
||||
}
|
||||
|
||||
//
|
||||
public function alipaytransfersummaryquery()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
// 校验支付宝账户名
|
||||
if (empty($get['alipayAccountName'])) {
|
||||
$this->error('支付宝账号不能为空');
|
||||
}
|
||||
$alipayAccountName = $get['alipayAccountName'];
|
||||
// 初始化返回数据结构
|
||||
$data = [
|
||||
'alipayAccountName' => $alipayAccountName,
|
||||
'sum' => 0.00,
|
||||
'count' => 0,
|
||||
'list' => []
|
||||
];
|
||||
|
||||
$cashOutList = DatabaseRoute::getAllDbData('cash_out', function ($query) use($alipayAccountName) {
|
||||
return $query->where('state', 1)
|
||||
->where('zhifubao_name', $alipayAccountName);
|
||||
})->select()->toArray();
|
||||
// 无记录则直接返回
|
||||
if (empty($cashOutList)) {
|
||||
$this->n_success($data);
|
||||
}
|
||||
// 按用户ID分组(替代Java的Collectors.groupingBy)
|
||||
$groupedByUserId = [];
|
||||
foreach ($cashOutList as $record) {
|
||||
$userId = $record['user_id'];
|
||||
$groupedByUserId[$userId][] = $record;
|
||||
}
|
||||
|
||||
|
||||
// 处理每个用户的汇总数据
|
||||
foreach ($groupedByUserId as $userId => $userRecords) {
|
||||
// 计算该用户的提现总金额
|
||||
$subSum = array_sum(array_column($userRecords, 'money'));
|
||||
|
||||
// 初始化用户记录
|
||||
$record = [
|
||||
'userId' => $userId,
|
||||
'userName' => '未知',
|
||||
'inviterCode' => '',
|
||||
'phone' => '',
|
||||
'zhiFuBaoName' => implode(' / ', array_unique(array_column($userRecords, 'zhifubao_name'))),
|
||||
'zhiFuBao' => implode(' / ', array_unique(array_column($userRecords, 'zhifubao'))),
|
||||
'subTotal' => $subSum,
|
||||
'subCount' => count($userRecords)
|
||||
];
|
||||
|
||||
// 查询用户信息
|
||||
$userEntity = Db::name('user')
|
||||
->where('user_id', $userId)
|
||||
->find();
|
||||
|
||||
// 补充用户信息
|
||||
if ($userEntity) {
|
||||
$record['userId'] = $userEntity['user_id'];
|
||||
$record['userName'] = $userEntity['user_name'];
|
||||
$record['inviterCode'] = $userEntity['inviter_code'];
|
||||
$record['phone'] = $userEntity['phone'];
|
||||
}
|
||||
|
||||
// 添加到结果列表
|
||||
$data['list'][] = $record;
|
||||
|
||||
// 更新总统计
|
||||
$data['sum'] += $subSum;
|
||||
$data['count'] += count($userRecords);
|
||||
}
|
||||
$this->n_success($data);
|
||||
}
|
||||
|
||||
|
||||
public function audit()
|
||||
{
|
||||
$cashOut = $this->request->post();
|
||||
// 1. 验证审核状态
|
||||
$isAgree = $cashOut['isAgree'] ?? null;
|
||||
|
||||
if ($isAgree === null) {
|
||||
$this->error("请选择同意或者拒绝!");
|
||||
}
|
||||
// 拒绝时必须填写原因
|
||||
if ($isAgree == 0 && trim($cashOut['refund'] ?? '') === '') {
|
||||
$this->error("请输入拒绝原因!");
|
||||
}
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('cash_out', ['user_id' => $cashOut['userId']], true));
|
||||
|
||||
// 2. 查询提现申请实体
|
||||
$entity = $db->name('cash_out')
|
||||
->where('user_id', $cashOut['userId'])
|
||||
->where('id', $cashOut['id'])
|
||||
->find();
|
||||
if (!$entity) {
|
||||
$this->error("提现申请不存在!");
|
||||
}
|
||||
|
||||
// 3. 验证申请状态(必须为待审核状态:state=3)
|
||||
if ($entity['state'] != 3) {
|
||||
$this->error("提现申请状态无效,请刷新后重试!");
|
||||
}
|
||||
|
||||
// 4. 根据审核结果更新状态
|
||||
if ($isAgree == 1) {
|
||||
$entity['state'] = 0; // 同意
|
||||
} else {
|
||||
$entity['state'] = 2; // 拒绝
|
||||
$entity['refund'] = $cashOut['refund']; // 拒绝原因
|
||||
}
|
||||
|
||||
// 5. 验证用户/代理信息是否存在
|
||||
$isUser = true;
|
||||
if ($entity['user_type'] == 2) {
|
||||
$isUser = false; // 代理用户
|
||||
}
|
||||
|
||||
if ($isUser) {
|
||||
// 普通用户
|
||||
$user = $db->name('tb_user')->where('user_id', $entity['user_id'])->find();
|
||||
if (!$user) {
|
||||
$this->error("提现用户信息不存在!");
|
||||
}
|
||||
} else {
|
||||
// 代理用户
|
||||
$sysUser = $db->name('sys_user')->where('user_id', $entity['user_id'])->find();
|
||||
if (!$sysUser) {
|
||||
$this->error("提现代理信息不存在!");
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 拒绝时退回金额并返回
|
||||
if ($isAgree == 0) {
|
||||
\app\admin\model\Cash::backCashAmount($entity, $db);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
// 7. 同意时处理提现逻辑
|
||||
$isHistoryData = false;
|
||||
// 历史数据判断(无银行名称的普通用户)
|
||||
if ($isUser && trim($entity['bank_name'] ?? '') === '') {
|
||||
$isHistoryData = true;
|
||||
}
|
||||
|
||||
// 更新状态为处理中
|
||||
$entity['state'] = 4;
|
||||
$db->name('cash_out')
|
||||
->where('user_id', $entity['user_id'])
|
||||
->where('id', $entity['id'])
|
||||
->update([
|
||||
'state' => 4
|
||||
]);
|
||||
|
||||
// 生成订单号(为空时)
|
||||
if (trim($entity['order_number'] ?? '') === '') {
|
||||
$entity['order_number'] = Random::generateRandomPrefixedId(19);
|
||||
$db->name('cash_out')
|
||||
->where('id', $entity['id'])
|
||||
->update(['order_number' => $entity['order_number']]);
|
||||
}
|
||||
|
||||
// 8. 调用支付接口执行提现
|
||||
$baseResp = WuYouPayUtils::extractOrder(
|
||||
$isHistoryData,
|
||||
$entity['order_number'],
|
||||
$entity['user_id'],
|
||||
$entity['money'],
|
||||
$isUser,
|
||||
$entity['zhifubao'] ?? '',
|
||||
$entity['zhifubao_name'] ?? '',
|
||||
$entity['bank_name'] ?? '',
|
||||
empty($entity['province']) ? '1' : $entity['province'],
|
||||
empty($entity['city']) ? '1' : $entity['city'],
|
||||
empty($entity['bank_branch']) ? '1' : $entity['bank_branch']
|
||||
);
|
||||
|
||||
// 9. 根据支付结果更新状态
|
||||
$updateData = [];
|
||||
if (isset($baseResp['status']) && ($baseResp['status'] == 2 || $baseResp['status'] == 10000)) {
|
||||
$entity['state'] = 1; // 提现成功
|
||||
} elseif (!empty($baseResp['error_msg'])) {
|
||||
$entity['state'] = 2; // 提现失败
|
||||
if (strpos($baseResp['error_msg'], '收款人账户号出款属性不匹配') !== false) {
|
||||
$entity['refund'] = "提现失败,请检查收款账号与收款人姓名后重试。";
|
||||
} else {
|
||||
$entity['refund'] = $baseResp['error_msg'];
|
||||
}
|
||||
\app\admin\model\Cash::backCashAmount($entity, $db); // 失败时退回金额
|
||||
} elseif (!empty($baseResp['msg'])) {
|
||||
$entity['state'] = 2; // 提现失败
|
||||
$entity['refund'] = "提现失败,请检查收款账号与收款人姓名后重试。";
|
||||
\app\admin\model\Cash::backCashAmount($entity, $db); // 失败时退回金额
|
||||
}
|
||||
// 调用用户ID更新方法(原updateByUserId)
|
||||
\app\admin\model\Cash::updateByUserId($entity, $db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
44
app/czg/controller/CommonController.php
Normal file
44
app/czg/controller/CommonController.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class CommonController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function info()
|
||||
{
|
||||
$condition = $this->request->param();
|
||||
$this->successWithData(Db::name('common_info')->where([
|
||||
'condition_from' => $condition['condition']
|
||||
])->select()->toArray());
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params['create_at'] = getNormalDate();
|
||||
Db::name('common_info')->where([
|
||||
'id' => $params['id']
|
||||
])->update(convertKeysCamelToSnakeRecursive($params));
|
||||
|
||||
$info = Db::name('common_info')->where([
|
||||
'id' => $params['id']
|
||||
])->find();
|
||||
cache('common_info:'.$info['type'], null);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function type()
|
||||
{
|
||||
$get = $this->request->param();
|
||||
if(empty($get['num'])) {
|
||||
$this->error('type 不能为空');
|
||||
}
|
||||
$data = convertToCamelCase(Db::connect(config('database.search_library'))->name('common_info')->where('type', $get['num'])->find());
|
||||
$this->success('ok', $data);
|
||||
}
|
||||
}
|
||||
34
app/czg/controller/CompletAwardController.php
Normal file
34
app/czg/controller/CompletAwardController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use OSS\Core\OssException;
|
||||
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
|
||||
use OSS\OssClient;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
use AlibabaCloud\Client\AlibabaCloud;
|
||||
use AlibabaCloud\Client\Exception\ClientException;
|
||||
use AlibabaCloud\Client\Exception\ServerException;
|
||||
class CompletAwardController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['insertCompletAward'];
|
||||
public function insertCompletAward()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
$post['create_time'] = date('Y-m-d H:i:s');
|
||||
$data = [];
|
||||
foreach ($post as $k => $v) {
|
||||
$data[toSnakeCase($k)] = $v;
|
||||
}
|
||||
unset($data['invite_img']);
|
||||
unset($data['id']);
|
||||
$db->name('complet_award')->insert($data);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
}
|
||||
62
app/czg/controller/CourseClassificationController.php
Normal file
62
app/czg/controller/CourseClassificationController.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseClassificationController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'selectCourseClassification', 'updateCourseClassification', 'insertCourseClassification', 'updateDelete'];
|
||||
|
||||
public function selectCourseClassification()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
if (!isset($params['page'])) {
|
||||
$params['page'] = 1;
|
||||
}
|
||||
if (!isset($params['limit'])) {
|
||||
$params['limit'] = 10;
|
||||
}
|
||||
|
||||
$this->n_success(['data' => DatabaseRoute::paginateDb('course_classification', function ($query) use ($params) {
|
||||
if (isset($params['classificationName'])) {
|
||||
$query->whereLike('classification_name', '%' . $params['classificationName'] . '%');
|
||||
}
|
||||
return $query->where([
|
||||
'is_delete' => 0
|
||||
]);
|
||||
}, $params['page'], $params['limit'])]);
|
||||
}
|
||||
|
||||
public function insertCourseClassification()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['is_delete'] = 0;
|
||||
Db::name('course_classification')->insert($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function updateCourseClassification()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
Db::name('course_classification')->where([
|
||||
'classification_id' => $params['classification_id']
|
||||
])->update($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function updateDelete()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
Db::name('course_classification')->where([
|
||||
'classification_id' => $params['id']
|
||||
])->delete();
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
23
app/czg/controller/CourseCollectController.php
Normal file
23
app/czg/controller/CourseCollectController.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseCollectController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['selectByUserId'];
|
||||
|
||||
|
||||
public function selectByUserId()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
return $this->ApiDataReturn(\app\api\model\Course::selectByUserId($get, $this->auth->user_id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
139
app/czg/controller/CourseController.php
Normal file
139
app/czg/controller/CourseController.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney'];
|
||||
|
||||
|
||||
public function selectCourse()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$res = \app\api\model\Course::selectCourse($params);
|
||||
$this->successWithData($res['data']);
|
||||
}
|
||||
|
||||
public function insertCourse()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['is_delete'] = 0;
|
||||
$params['create_time'] = getNormalDate();
|
||||
$params['course_id'] = Random::generateRandomPrefixedId();
|
||||
$params['banner_id'] = empty($params['banner_id']) ? null : $params['banner_id'];
|
||||
if ($params['course_type'] == 2 || $params['course_type'] == 3) {
|
||||
$copy = unserialize(serialize($params));
|
||||
unset($copy['remark']);
|
||||
$id = Db::name('course')->insert($copy);
|
||||
DatabaseRoute::getDb('course_details', $id, true)->insert([
|
||||
'course_id' => $id,
|
||||
'video_url' => $params['remark'] ?? '',
|
||||
'view_count' => 0,
|
||||
'play_complete_count' => 0,
|
||||
]);
|
||||
}else {
|
||||
unset($params['remark']);
|
||||
$id = Db::name('course')->insert($params);
|
||||
}
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function updateCourse()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
unset($params['banner_id']);
|
||||
Db::name('course')->where([
|
||||
'course_id' => $params['course_id']
|
||||
])->update($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function selectCourseById()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$where = [
|
||||
'course_id' => $params['id']
|
||||
];
|
||||
if (!empty($params['good'])) {
|
||||
if ($params['good'] == 1) {
|
||||
$where['good'] = $params['good'];
|
||||
}else{
|
||||
$where['good'] = $params['good'];
|
||||
}
|
||||
}
|
||||
$this->successWithData(DatabaseRoute::paginateDb('course_details', function ($query) use($where) {
|
||||
$query->where($where);
|
||||
return $query->order('sort', false);
|
||||
}, $params['page'], $params['limit'], [
|
||||
'course_id' => $params['id']
|
||||
]));
|
||||
|
||||
}
|
||||
|
||||
public function updateDelete()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
Db::name('course')->where([
|
||||
'course_id' => $params['id']
|
||||
])->delete();
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function updateCourseStatus()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$params['ids'] = explode(',', $params['ids']);
|
||||
foreach ($params['ids'] as $id) {
|
||||
Db::name('course')->where([
|
||||
'course_id' => $id
|
||||
])->update([
|
||||
'status' => $params['status']
|
||||
]);
|
||||
}
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function updateCourseDetails()
|
||||
{
|
||||
$param = $this->request->param();
|
||||
$param['ids'] = explode(',', $param['ids']);
|
||||
foreach ($param['ids'] as $id) {
|
||||
DatabaseRoute::getAllDbData('course_details', function ($query) use ($id, $param) {
|
||||
return $query->where([
|
||||
'course_details_id' => $id
|
||||
]);
|
||||
})->update([
|
||||
'is_price' => bccomp($param['price'],0, 4) == 0 ? 2 : 1,
|
||||
'content' => $param['content'],
|
||||
'title_img' => $param['titleImg'],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function deleteCourseDetailsByIds()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$params['ids'] = explode(',', $params['ids']);
|
||||
foreach ($params['ids'] as $id) {
|
||||
DatabaseRoute::getAllDbData('course_details', function ($query) use ($id) {
|
||||
return $query->where([
|
||||
'course_details_id' => $id
|
||||
]);
|
||||
})->delete();
|
||||
}
|
||||
|
||||
$this->success();
|
||||
}
|
||||
}
|
||||
56
app/czg/controller/CourseDetailsController.php
Normal file
56
app/czg/controller/CourseDetailsController.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseDetailsController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney'];
|
||||
|
||||
public function insertCourseDetails()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['create_time'] = getNormalDate();
|
||||
$params['course_details_id'] = Random::generateRandomPrefixedId();
|
||||
if (empty($params['good_num'])) {
|
||||
$params['good_num'] = 0;
|
||||
}
|
||||
DatabaseRoute::getDb('course_details', [
|
||||
'course_id' => $params['course_id']
|
||||
], true)->insert($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function updateCourseDetails()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$db = Db::connect(DatabaseRoute::getConnection('course_details', ['course_id' => $params['course_id']], true));
|
||||
$course_details_id = $params['course_details_id'];
|
||||
unset($params['course_id']);
|
||||
unset($params['course_details_id']);
|
||||
$db->name('course_details')->where('course_details_id', $course_details_id)->update($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function deleteCourseDetails()
|
||||
{
|
||||
$ids = $this->request->param('ids');
|
||||
$ids = explode(',', $ids);
|
||||
foreach ($ids as $id) {
|
||||
DatabaseRoute::deleteAllDbDirect('course_details', function ($query) use ($id) {
|
||||
return $query->where([
|
||||
'course_details_id' => $id
|
||||
]);
|
||||
});
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
}
|
||||
20
app/czg/controller/DashboardController.php
Normal file
20
app/czg/controller/DashboardController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class DashboardController extends Backend
|
||||
{
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$this->success('', [
|
||||
'remark' => get_route_remark()
|
||||
]);
|
||||
}
|
||||
}
|
||||
122
app/czg/controller/DiscSpinningAmountController.php
Normal file
122
app/czg/controller/DiscSpinningAmountController.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Db;
|
||||
|
||||
class DiscSpinningAmountController extends Backend
|
||||
{
|
||||
|
||||
|
||||
protected array $noNeedPermission = ['selectDiscSpinningAmount', 'insertDiscSpinningAmount', 'updateDiscSpinningAmount', 'deleteDiscSpinningAmount'];
|
||||
|
||||
// 查询现金红包 抽奖配置
|
||||
public function selectDiscSpinningAmount()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['page'])) {
|
||||
$get['page'] = 1;
|
||||
}
|
||||
if(empty($get['limit'])) {
|
||||
$get['limit'] = 20;
|
||||
}
|
||||
$db = Db::connect(get_slave_connect_name());
|
||||
$count = $db->name('disc_spinning_amount')->where('type', $get['type'])->count();
|
||||
// 构建查询条件
|
||||
$res = $db->name('disc_spinning_amount')
|
||||
->where('type', $get['type'])
|
||||
->order('status', 'desc')
|
||||
->order('num', 'asc')
|
||||
->order('random', 'asc')
|
||||
->order('max_amount', 'asc')
|
||||
->limit(page($get['page'], $get['limit']))
|
||||
->select()
|
||||
->toArray();
|
||||
foreach ($res as $k => &$v) {
|
||||
$scaleFactor = 100;
|
||||
$intValue = (int)round($v['max_amount'] * $scaleFactor, 0);
|
||||
$v['max_amount'] = $intValue / $scaleFactor;
|
||||
|
||||
$intValue = (int)round($v['random'] * $scaleFactor, 0);
|
||||
$v['random'] = $intValue / $scaleFactor;
|
||||
|
||||
}
|
||||
// 转换为前端需要的格式
|
||||
$data = [
|
||||
'totalCount' => $count,
|
||||
'pageSize' => $get['limit'],
|
||||
'totalPage' => ceil($count / $get['limit']),
|
||||
'currPage' => $get['page'],
|
||||
'list' => null,
|
||||
'records' => $res
|
||||
];
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
|
||||
// 添加现金红包 抽奖配置
|
||||
public function insertDiscSpinningAmount()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
// 保存数据到数据库
|
||||
$result = Db::name('disc_spinning_amount')->insert([
|
||||
'name' => $post['name'],
|
||||
'random' => $post['random'],
|
||||
'max_amount' => $post['maxAmount'],
|
||||
'type' => $post['type'],
|
||||
'status' => $post['status'],
|
||||
'num' => $post['num'] ?? 0,
|
||||
]);
|
||||
if (!$result) {
|
||||
$this->error("保存转盘金额配置失败");
|
||||
}
|
||||
// 删除Redis缓存(使用Cache门面)
|
||||
$cacheKey = "spinning:amount:{$post['type']}";
|
||||
Cache::delete($cacheKey);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
// 修改现金红包 抽奖配置
|
||||
public function updateDiscSpinningAmount()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
// 保存数据到数据库
|
||||
Db::name('disc_spinning_amount')->where(['id' => $post['id']])->update([
|
||||
'name' => $post['name'],
|
||||
'random' => $post['random'],
|
||||
'max_amount' => $post['maxAmount'],
|
||||
'type' => $post['type'],
|
||||
'status' => $post['status'],
|
||||
'num' => $post['num'],
|
||||
]);
|
||||
// if (!$result) {
|
||||
// $this->error("保存转盘金额配置失败");
|
||||
// }
|
||||
// 删除Redis缓存(使用Cache门面)
|
||||
$cacheKey = "spinning:amount:{$post['type']}";
|
||||
Cache::delete($cacheKey);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function deleteDiscSpinningAmount()
|
||||
{
|
||||
$post = $this->request->param();
|
||||
// 保存数据到数据库
|
||||
$result = Db::name('disc_spinning_amount')->where(['id' => $post['id']])->delete();
|
||||
if (!$result) {
|
||||
$this->error("保存转盘金额配置失败");
|
||||
}
|
||||
// 删除Redis缓存(使用Cache门面)
|
||||
$cacheKey = "spinning:amount";
|
||||
Cache::delete($cacheKey);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
126
app/czg/controller/DiscSpinningController.php
Normal file
126
app/czg/controller/DiscSpinningController.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class DiscSpinningController extends Backend
|
||||
{
|
||||
|
||||
protected array $noNeedPermission = ['selectDiscSpinning', 'updateDiscSpinning', 'deleteDiscSpinning', 'insertDiscSpinning'];
|
||||
|
||||
// 查询大转盘
|
||||
public function selectDiscSpinning()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$db = Db::connect(get_slave_connect_name());
|
||||
$count = $db->name('disc_spinning')->where(['disc_type' => $get['source']])->count();
|
||||
$res = $db->name('disc_spinning')->where(['disc_type' => $get['source']])->limit(page($get['page'], $get['limit']), $get['limit'])->order('disc_type', 'asc')->order('odds', 'asc')->select()->toArray();
|
||||
$this->n_success(['data' => [
|
||||
'totalCount' => $count,
|
||||
'pageSize' => $get['limit'],
|
||||
'totalPage' => ceil($count / $get['limit']),
|
||||
'currPage' => $get['page'],
|
||||
'list' => null,
|
||||
'records' => $res
|
||||
]]);
|
||||
}
|
||||
|
||||
|
||||
// 修改大转盘
|
||||
public function updateDiscSpinning()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
// if(empty($post['name']) || empty($post['url']) || empty($post['type']) || empty($post['odds']) || empty($post['discType']) || empty($post['id'])) {
|
||||
// $this->error('参数不完整');
|
||||
// }
|
||||
|
||||
// 查询指定类型的奖品列表(按type和id升序排列)
|
||||
$prizes = Db::name('disc_spinning')
|
||||
->where('disc_type', $post['discType'])
|
||||
->order('type', 'asc')
|
||||
->order('id', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
// 处理奖品概率累加
|
||||
$upPrizes = [];
|
||||
$number = 0; // 概率累加值(PHP使用浮点数,需注意精度问题)
|
||||
|
||||
foreach ($prizes as $key => $prize) {
|
||||
// 如果是当前编辑的奖品,使用传入的数据覆盖
|
||||
if ($prize['id'] == $post['id']) {
|
||||
$prizes[$key] = $post;
|
||||
$prize = $post;
|
||||
}
|
||||
|
||||
// 累加概率
|
||||
$number += $prize['odds'];
|
||||
$prizes[$key]['number'] = $number; // 记录累加后的概率值
|
||||
|
||||
// 添加到结果列表
|
||||
$upPrizes[] = convertKeysCamelToSnakeRecursive($prizes[$key]);
|
||||
}
|
||||
|
||||
// 验证概率总和是否超过100
|
||||
if ($number > 100) {
|
||||
$this->error("中奖概率总和 不可超过100");
|
||||
}
|
||||
|
||||
\app\admin\model\DiscSpinning::updateBatchById($upPrizes);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
// 删除大转盘
|
||||
public function deleteDiscSpinning()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
if(empty($post['id'])) {
|
||||
$this->error('id不能为空');
|
||||
}
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
if($db->name('disc_spinning')->where(['id' => $post['id']])->delete()) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error();
|
||||
}
|
||||
|
||||
// 转盘添加抽奖项
|
||||
public function insertDiscSpinning()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
if(empty($post['name']) || empty($post['url']) || empty($post['type']) || empty($post['odds']) || empty($post['discType'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
// 查询指定类型的奖品列表(按type和id升序排列)
|
||||
$prizes = Db::name('disc_spinning')
|
||||
->where('disc_type', $post['discType'])
|
||||
->order('type', 'asc')
|
||||
->order('id', 'asc')
|
||||
->select()
|
||||
->toArray();
|
||||
// 计算当前奖品总概率
|
||||
$totalOdds = 0;
|
||||
foreach ($prizes as &$prize) {
|
||||
$totalOdds += $prize['odds'];
|
||||
$prize['number'] = $totalOdds;
|
||||
}
|
||||
unset($prize); // 释放引用
|
||||
// 计算新增奖品后的总概率
|
||||
$newTotalOdds = $totalOdds + $post['odds'];
|
||||
// 验证概率总和是否超过100
|
||||
if ($newTotalOdds > 100) {
|
||||
$this->error("中奖概率总和 不可超过100");
|
||||
}
|
||||
// 设置创建时间(使用当前时间戳)
|
||||
$post['create_time'] = date('Y-m-d H:i:s');
|
||||
$post['number'] = $post['odds'];
|
||||
\app\admin\model\DiscSpinning::updateBatchById($prizes);
|
||||
Db::name('disc_spinning')->insert($post);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
78
app/czg/controller/ExtSysController.php
Normal file
78
app/czg/controller/ExtSysController.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class ExtSysController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function friendConfig()
|
||||
{
|
||||
$code = 999;
|
||||
$commonInfo = cache('common_info:'.$code);
|
||||
if (!$commonInfo) {
|
||||
$commonInfo = CommonInfo::where([
|
||||
'type' => $code
|
||||
])->find();
|
||||
if($commonInfo) {
|
||||
$commonInfo = $commonInfo->toArray();
|
||||
}
|
||||
cache('common_info:'.$code, $commonInfo, 60 * 60 * 24);
|
||||
}
|
||||
if (!$commonInfo) {
|
||||
$this->success();
|
||||
}
|
||||
|
||||
$this->successWithData([
|
||||
'imageUrl' => $commonInfo['value'],
|
||||
'tips' => $commonInfo['max']
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function friendConfigSave()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
if (empty($params['imageUrl'])) {
|
||||
$this->error('顶部图片地址不能为空');
|
||||
}
|
||||
|
||||
if (empty($params['tips'])) {
|
||||
$this->error('邀请文案不能为空');
|
||||
}
|
||||
|
||||
if (strlen($params['tips']) > 20) {
|
||||
$this->error('邀请文案不能大于20个字符');
|
||||
}
|
||||
|
||||
$commonInfo = (new CommonInfo())->getByCode(999);
|
||||
if ($commonInfo) {
|
||||
Db::name('common_info')->where([
|
||||
'id' => $commonInfo['id']
|
||||
])->update([
|
||||
'max' => $params['tips'],
|
||||
'value' => $params['imageUrl']
|
||||
]);
|
||||
}else{
|
||||
Db::name('common_info')->insert([
|
||||
'code' => 999,
|
||||
'max' => $params['tips'],
|
||||
'value' => $params['imageUrl'],
|
||||
'min' => '邀请好友配置',
|
||||
'is_app_use' => 1,
|
||||
'create_at' => getNormalDate()
|
||||
]);
|
||||
}
|
||||
cache('common_info:999', Db::name('common_info')->where([
|
||||
'type' => 999
|
||||
])->find());
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
119
app/czg/controller/HelpWordController.php
Normal file
119
app/czg/controller/HelpWordController.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SysCaptcha;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class HelpWordController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['selectHelpClassifyList', 'deleteHelpClassify', 'insertHelpClassify', 'selectHelpWordList'];
|
||||
public function selectHelpClassifyList()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$page = $get['page'] ?? 1;
|
||||
$limit = $get['limit'] ?? 10;
|
||||
$types = $get['types'] ?? null;
|
||||
$helpClassifyName = $get['helpClassifyName'] ?? null;
|
||||
$parentId = $get['parentId'] ?? null;
|
||||
$db = Db::connect(get_slave_connect_name());
|
||||
// 构建查询
|
||||
$query = $db->name('help_classify');
|
||||
$query = $query->when($types !== null, function ($query) use ($types) {
|
||||
return $query->where('types', $types);
|
||||
});
|
||||
$query = $query->when(!empty($helpClassifyName), function ($query) use ($helpClassifyName) {
|
||||
return $query->where('help_classify_name', $helpClassifyName);
|
||||
});
|
||||
|
||||
$query = $query->when($parentId !== null, function ($query) use ($parentId) {
|
||||
return $query->where('parent_id', $parentId);
|
||||
});
|
||||
$count = $query->count();
|
||||
$res = $query->order('sort', 'asc')->limit(page($page, $limit), $limit)->select()->toArray();
|
||||
$data = [
|
||||
'totalCount' => $count,
|
||||
'pageSize' => $limit,
|
||||
'totalPage' => ceil($count / $limit),
|
||||
'currPage' => $page,
|
||||
'list' => $res,
|
||||
'records' => $res
|
||||
];
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
// 删除帮助分类
|
||||
public function deleteHelpClassify()
|
||||
{
|
||||
$post = $this->request->param();
|
||||
if(empty($post['helpClassifyId'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
$db->name('help_classify')->where(['help_classify_id' => $post['helpClassifyId']])->delete();
|
||||
$this->success();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 添加帮助分类
|
||||
public function insertHelpClassify()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
$createTime = date('Y-m-d H:i:s');
|
||||
if(empty($post['helpClassifyName']) || !isset($post['sort']) || empty($post['state']) || empty($post['types'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
Db::name('help_classify')->insert([
|
||||
'help_classify_id' => Random::generateRandomPrefixedId(),
|
||||
'help_classify_name' => $post['helpClassifyName'],
|
||||
'sort' => $post['sort'],
|
||||
'types' => $post['types'],
|
||||
'create_time' => $createTime,
|
||||
]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
public function selectHelpWordList()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$helpClassifyId = $get['helpClassifyId'] ?? null;
|
||||
$helpWordTitle = $get['helpWordTitle'] ?? null;
|
||||
$page = $get['page'] ?? null;
|
||||
$limit = $get['limit'] ?? null;
|
||||
$query = Db::name('help_word');
|
||||
// 条件筛选
|
||||
if (!is_null($helpClassifyId)) {
|
||||
$query->where('help_classify_id', $helpClassifyId);
|
||||
}
|
||||
if (!empty($helpWordTitle)) {
|
||||
$query->where('help_word_title', $helpWordTitle);
|
||||
}
|
||||
// 排序和分页
|
||||
$list = $query->order('sort', 'asc')
|
||||
->page($page, $limit)
|
||||
->limit(page($page, $limit), $limit)
|
||||
->select()
|
||||
->toArray();
|
||||
// 获取总数(用于分页信息)
|
||||
$count = $query->count();
|
||||
$this->n_success(['data' => [
|
||||
'totalCount' => $count,
|
||||
'pageSize' => $get['limit'],
|
||||
'totalPage' => ceil($count / $get['limit']),
|
||||
'currPage' => $get['page'],
|
||||
'list' => $list,
|
||||
]]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
18
app/czg/controller/IndetcodeController.php
Normal file
18
app/czg/controller/IndetcodeController.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SysCaptcha;
|
||||
use support\Request;
|
||||
|
||||
class IndetcodeController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function getCode(Request $request)
|
||||
{
|
||||
$data = $request->get();
|
||||
if(empty($data['uuid']))$this->error('参数不完整');
|
||||
$this->success('ok', SysCaptcha::getCode($data['uuid'], $request));
|
||||
}
|
||||
}
|
||||
133
app/czg/controller/IndexController.php
Normal file
133
app/czg/controller/IndexController.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\ClickCaptcha;
|
||||
use think\facade\Config;
|
||||
use think\facade\Validate;
|
||||
use app\common\facade\Token;
|
||||
use app\admin\model\AdminLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class IndexController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['logout', 'login'];
|
||||
protected array $noNeedPermission = ['index'];
|
||||
|
||||
/**
|
||||
* 后台初始化请求
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
$adminInfo = $this->auth->getInfo();
|
||||
$adminInfo['super'] = $this->auth->isSuperAdmin();
|
||||
unset($adminInfo['token'], $adminInfo['refresh_token']);
|
||||
|
||||
$menus = $this->auth->getMenus();
|
||||
if (!$menus) {
|
||||
$this->error(__('No background menu, please contact super administrator!'));
|
||||
}
|
||||
$this->success('', [
|
||||
'adminInfo' => $adminInfo,
|
||||
'menus' => $menus,
|
||||
'siteConfig' => [
|
||||
'siteName' => get_sys_config('site_name'),
|
||||
'version' => get_sys_config('version'),
|
||||
'apiUrl' => Config::get('buildadmin.api_url'),
|
||||
'upload' => keys_to_camel_case(get_upload_config(), ['max_size', 'save_name', 'allowed_suffixes', 'allowed_mime_types']),
|
||||
'cdnUrl' => full_url(),
|
||||
'cdnUrlParams' => Config::get('buildadmin.cdn_url_params'),
|
||||
],
|
||||
'terminal' => [
|
||||
'phpDevelopmentServer' => str_contains($_SERVER['SERVER_SOFTWARE'], 'Development Server'),
|
||||
'npmPackageManager' => Config::get('terminal.npm_package_manager'),
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员登录
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function login(): void
|
||||
{
|
||||
// 检查登录态
|
||||
if ($this->auth->isLogin()) {
|
||||
$this->success(__('You have already logged in. There is no need to log in again~'), [
|
||||
'type' => $this->auth::LOGGED_IN
|
||||
], $this->auth::LOGIN_RESPONSE_CODE);
|
||||
}
|
||||
|
||||
$captchaSwitch = Config::get('buildadmin.admin_login_captcha');
|
||||
|
||||
// 检查提交
|
||||
if ($this->request->isPost()) {
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$keep = $this->request->post('keep');
|
||||
|
||||
$rule = [
|
||||
'username|' . __('Username') => 'require|length:3,30',
|
||||
'password|' . __('Password') => 'require|regex:^(?!.*[&<>"\'\n\r]).{6,32}$',
|
||||
];
|
||||
$data = [
|
||||
'username' => $username,
|
||||
'password' => $password,
|
||||
];
|
||||
if ($captchaSwitch) {
|
||||
$rule['captchaId|' . __('CaptchaId')] = 'require';
|
||||
$rule['captchaInfo|' . __('Captcha')] = 'require';
|
||||
|
||||
$data['captchaId'] = $this->request->post('captchaId');
|
||||
$data['captchaInfo'] = $this->request->post('captchaInfo');
|
||||
}
|
||||
$validate = Validate::rule($rule);
|
||||
if (!$validate->check($data)) {
|
||||
$this->error($validate->getError());
|
||||
}
|
||||
|
||||
if ($captchaSwitch) {
|
||||
$captchaObj = new ClickCaptcha();
|
||||
if (!$captchaObj->check($data['captchaId'], $data['captchaInfo'])) {
|
||||
$this->error(__('Captcha error'));
|
||||
}
|
||||
}
|
||||
|
||||
AdminLog::instance()->setTitle(__('Login'));
|
||||
|
||||
$res = $this->auth->login($username, $password, (bool)$keep);
|
||||
if ($res === true) {
|
||||
$this->success(__('Login succeeded!'), [
|
||||
'userInfo' => $this->auth->getInfo()
|
||||
]);
|
||||
} else {
|
||||
$msg = $this->auth->getError();
|
||||
$msg = $msg ?: __('Incorrect user name or password!');
|
||||
$this->error($msg);
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'captcha' => $captchaSwitch
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员注销
|
||||
* @return void
|
||||
*/
|
||||
public function logout(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$refreshToken = $this->request->post('refreshToken', '');
|
||||
if ($refreshToken) Token::delete((string)$refreshToken);
|
||||
$this->auth->logout();
|
||||
$this->success();
|
||||
}
|
||||
}
|
||||
}
|
||||
83
app/czg/controller/IntegralController.php
Normal file
83
app/czg/controller/IntegralController.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Exception;
|
||||
use think\facade\Db;
|
||||
|
||||
class IntegralController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['selectByUserId', 'details'];
|
||||
|
||||
|
||||
public function selectByUserId()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId is not empty');
|
||||
}
|
||||
|
||||
$data = Db::connect(get_slave_connect_name())->name('user_integral')->where(['user_id' => $get['userId']])->find();
|
||||
$data = [
|
||||
'user_id' => (string)$get['userId'],
|
||||
'integral_num' => !empty($data['integral_num'])?$data['integral_num']:'0',
|
||||
];
|
||||
$this->n_success(['data' => convertToCamelCase($data)]);
|
||||
}
|
||||
|
||||
public function details()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId is not empty');
|
||||
}
|
||||
$this->n_success(['data' => UserIntegral::selectUserIntegralDetailsByUserId($get['page'], $get['limit'], $get['userId'])]);
|
||||
}
|
||||
|
||||
public function updateUserIntegral()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
$userId = $post['userId'] ?? $this->error('参数不完整');
|
||||
$type = $post['type'] ?? $this->error('参数不完整');
|
||||
$integral = $post['integral'] ?? $this->error('参数不完整');
|
||||
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
if(UserIntegral::updateIntegral($type, $userId, $integral, $db)) {
|
||||
// 记录积分变动明细
|
||||
$details['classify'] = 2;
|
||||
$details['content'] = $type == 1
|
||||
? "系统增加积分:{$integral}"
|
||||
: "系统减少积分:{$integral}";
|
||||
|
||||
$currentTime = time();
|
||||
$details['create_time'] = date('Y-m-d H:i:s', $currentTime);
|
||||
|
||||
$details['num'] = $integral;
|
||||
$details['type'] = $type;
|
||||
$details['user_id'] = $userId;
|
||||
$db->name('user_integral_details')->insert($details);
|
||||
Db::commit();
|
||||
}
|
||||
$this->success();
|
||||
}catch (Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
31
app/czg/controller/InviteAwardController.php
Normal file
31
app/czg/controller/InviteAwardController.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class InviteAwardController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
|
||||
public function selectInviteAwardList()
|
||||
{
|
||||
$inviteList = Db::name('invite_award')->order('invite_count', 'asc')->select();
|
||||
$this->successWithData(buildPageInfo(convertToCamelCase($inviteList->toArray()), true));
|
||||
}
|
||||
|
||||
public function deleteInviteAward()
|
||||
{
|
||||
$post = $this->request->param();
|
||||
$inviteAwardId = !empty($post['inviteAwardId'])?$post['inviteAwardId']:$this->error('参数不完整');
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
if($db->name('invite_award')->where(['invite_award_id' => $inviteAwardId])->delete()) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error();
|
||||
}
|
||||
|
||||
}
|
||||
29
app/czg/controller/InviteController.php
Normal file
29
app/czg/controller/InviteController.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class InviteController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['selectInviteByUserIdLists'];
|
||||
|
||||
|
||||
public function selectInviteByUserIdLists()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
$user = DatabaseRoute::getDb('tb_user', $get['userId'])->find();
|
||||
if(empty($user)) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
return $this->ApiDataReturn(\app\api\model\Invite::selectInviteByUserIdLists($user, $get, 'admin'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
28
app/czg/controller/LoginController.php
Normal file
28
app/czg/controller/LoginController.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\Msg;
|
||||
use app\api\model\TbUser;
|
||||
use app\common\model\SysUser;
|
||||
use think\facade\Db;
|
||||
use think\Request;
|
||||
use Throwable;
|
||||
use ba\Captcha;
|
||||
use ba\ClickCaptcha;
|
||||
use think\facade\Config;
|
||||
use app\common\facade\Token;
|
||||
use app\common\controller\Frontend;
|
||||
use app\api\validate\User as UserValidate;
|
||||
|
||||
class LoginController extends Frontend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
// 发送验证码
|
||||
public function sendMsg()
|
||||
{
|
||||
$get = $this->request->route->param();
|
||||
return $this->ApiDataReturn(Msg::sendMsg($get['phone'], $get['event']));
|
||||
}
|
||||
}
|
||||
85
app/czg/controller/MessageController.php
Normal file
85
app/czg/controller/MessageController.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\MessageInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class MessageController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney', 'selectMessageByUserId'];
|
||||
|
||||
|
||||
public function page()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$pageInfo = DatabaseRoute::paginateDb('message_info', function ($query) use ($params) {
|
||||
if (!empty($params['state'])) {
|
||||
$query->where([
|
||||
'state' => $params['state']
|
||||
]);
|
||||
}
|
||||
return $query;
|
||||
}, $params['page'], $params['limit']);
|
||||
foreach ($pageInfo['list'] as &$info) {
|
||||
if (!empty($info['user_id'])) {
|
||||
$info['userEntity'] = DatabaseRoute::getDb('tb_user', $info['user_id'])->find();
|
||||
}
|
||||
}
|
||||
|
||||
$this->successWithData($pageInfo);
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params['create_at'] = getNormalDate();
|
||||
Db::name('message_info')->insert(convertKeysCamelToSnakeRecursive($params));
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
Db::name('message_info')->where([
|
||||
'id' => $params['id']
|
||||
])->update($params);
|
||||
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
Db::name('message_info')->delete([
|
||||
'id' => $params['id']
|
||||
]);
|
||||
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function selectMessageByUserId()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$this->n_success(['data' => MessageInfo::selectMessageList($get)]);
|
||||
}
|
||||
|
||||
public function selectMessageByType()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$this->n_success(['data' => MessageInfo::selectMessageList($get)]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
156
app/czg/controller/ModuleController.php
Normal file
156
app/czg/controller/ModuleController.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\Exception;
|
||||
use think\facade\Config;
|
||||
use app\admin\model\AdminLog;
|
||||
use app\admin\library\module\Server;
|
||||
use app\admin\library\module\Manage;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class ModuleController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['state', 'dependentInstallComplete'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$this->success('', [
|
||||
'sysVersion' => Config::get('buildadmin.version'),
|
||||
'installed' => Server::installedList(root_path() . 'modules' . DIRECTORY_SEPARATOR),
|
||||
]);
|
||||
}
|
||||
|
||||
public function state(): void
|
||||
{
|
||||
$uid = $this->request->get("uid/s", '');
|
||||
if (!$uid) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
$this->success('', [
|
||||
'state' => Manage::instance($uid)->getInstallState()
|
||||
]);
|
||||
}
|
||||
|
||||
public function install(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Install module'));
|
||||
$uid = $this->request->get("uid/s", '');
|
||||
$token = $this->request->get("token/s", '');
|
||||
$orderId = $this->request->get("orderId/d", 0);
|
||||
if (!$uid) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
$res = [];
|
||||
try {
|
||||
$res = Manage::instance($uid)->install($token, $orderId);
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getData(), $e->getCode());
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success('', [
|
||||
'data' => $res,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dependentInstallComplete(): void
|
||||
{
|
||||
$uid = $this->request->get("uid/s", '');
|
||||
if (!$uid) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
try {
|
||||
Manage::instance($uid)->dependentInstallComplete('all');
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getData(), $e->getCode());
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function changeState(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Change module state'));
|
||||
$uid = $this->request->post("uid/s", '');
|
||||
$state = $this->request->post("state/b", false);
|
||||
if (!$uid) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
$info = [];
|
||||
try {
|
||||
$info = Manage::instance($uid)->changeState($state);
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getData(), $e->getCode());
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success('', [
|
||||
'info' => $info,
|
||||
]);
|
||||
}
|
||||
|
||||
public function uninstall(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Unload module'));
|
||||
$uid = $this->request->get("uid/s", '');
|
||||
if (!$uid) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
try {
|
||||
Manage::instance($uid)->uninstall();
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getData(), $e->getCode());
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function update(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Update module'));
|
||||
$uid = $this->request->get("uid/s", '');
|
||||
$token = $this->request->get("token/s", '');
|
||||
$orderId = $this->request->get("orderId/d", 0);
|
||||
if (!$token || !$uid) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
try {
|
||||
Manage::instance($uid)->update($token, $orderId);
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getData(), $e->getCode());
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function upload(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Upload install module'));
|
||||
$file = $this->request->get("file/s", '');
|
||||
$token = $this->request->get("token/s", '');
|
||||
if (!$file) $this->error(__('Parameter error'));
|
||||
if (!$token) $this->error(__('Please login to the official website account first'));
|
||||
|
||||
$info = [];
|
||||
try {
|
||||
$info = Manage::instance()->upload($token, $file);
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getData(), $e->getCode());
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success('', [
|
||||
'info' => $info
|
||||
]);
|
||||
}
|
||||
}
|
||||
52
app/czg/controller/MoneyDetailsController.php
Normal file
52
app/czg/controller/MoneyDetailsController.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\SysUserMoney;
|
||||
use app\admin\model\SysUserMoneyDetails;
|
||||
use app\admin\model\User;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class MoneyDetailsController extends Backend
|
||||
{
|
||||
|
||||
protected array $noNeedPermission = ['selectUserMoney', 'queryUserMoneyDetails', 'selectSysUserMoney'];
|
||||
|
||||
public function selectUserMoney()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId is not empty');
|
||||
}
|
||||
|
||||
$this->n_success(['data' => User::selectUserMoneyByUserId($get['userId'])]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function queryUserMoneyDetails()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$page = $get['page'];
|
||||
$limit = $get['limit'];
|
||||
$userId = $get['userId'] ?? '';
|
||||
$classify = $get['classify'] ?? null;
|
||||
|
||||
$this->n_success(['data' => SysUserMoneyDetails::queryUserMoneyDetails($page, $limit, $get['sysUserId'] ?? '', $userId, $classify, null, null, null)]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function selectSysUserMoney()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId is not empty');
|
||||
}
|
||||
$this->n_success(['data' => SysUserMoney::selectSysUserMoneyByUserId($get['userId'])]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
498
app/czg/controller/OrderController.php
Normal file
498
app/czg/controller/OrderController.php
Normal file
@@ -0,0 +1,498 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\TbUser;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Exception;
|
||||
|
||||
class OrderController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
public function deleteOrders($ids)
|
||||
{
|
||||
$idS = explode(",", $ids);
|
||||
foreach ($idS as $id) {
|
||||
DatabaseRoute::deleteAllDbDirect('orders', function ($query) use ($id) {
|
||||
return $query->where([
|
||||
'orders_id' => $id
|
||||
]);
|
||||
});
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function selectOrders()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$this->successWithData(DatabaseRoute::paginateAllDb('orders', function ($query) use ($params) {
|
||||
// 动态拼接查询条件
|
||||
if (!empty($params['userName'])) {
|
||||
$query->whereLike('u.user_name', '%' . $params['userName'] . '%');
|
||||
}
|
||||
|
||||
if (!empty($params['qdCode'])) {
|
||||
$query->where('s.qd_code', $params['qdCode']);
|
||||
}
|
||||
|
||||
if (!empty($params['sysUserName'])) {
|
||||
$query->whereLike('s.username', '%' . $params['sysUserName'] . '%');
|
||||
}
|
||||
|
||||
if (!empty($params['ordersNo'])) {
|
||||
$query->whereLike('o.orders_no', '%' . $params['ordersNo'] . '%');
|
||||
}
|
||||
|
||||
if (isset($params['status']) && $params['status'] !== -1) {
|
||||
$query->where('o.status', $params['status']);
|
||||
}
|
||||
|
||||
if (!empty($params['userId'])) {
|
||||
$query->where('o.user_id', $params['userId']);
|
||||
}
|
||||
|
||||
if (!empty($params['ordersType'])) {
|
||||
$query->where('o.orders_type', $params['ordersType']);
|
||||
}
|
||||
|
||||
if (!empty($params['courseId'])) {
|
||||
$query->where('o.course_id', $params['courseId']);
|
||||
}
|
||||
|
||||
if (!empty($params['sysUserId'])) {
|
||||
$query->where('o.sys_user_id', $params['sysUserId']);
|
||||
}
|
||||
|
||||
// 时间范围
|
||||
if (!empty($params['startTime']) && !empty($params['endTime'])) {
|
||||
$query->whereBetween('o.create_time', [$params['startTime'], $params['endTime']]);
|
||||
} elseif (!empty($params['startTime'])) {
|
||||
$query->where('o.create_time', '>=', $params['startTime']);
|
||||
} elseif (!empty($params['endTime'])) {
|
||||
$query->where('o.create_time', '<=', $params['endTime']);
|
||||
}
|
||||
|
||||
// 排序
|
||||
$query->order('o.create_time', 'desc');
|
||||
return $query->alias('o')
|
||||
->field('o.*, u.user_name as userName, s.username as sysUserName, s.qd_code as qdCode')
|
||||
->leftJoin('tb_user u', 'o.user_id = u.user_id')
|
||||
->leftJoin('sys_user s', 's.user_id = o.sys_user_id');
|
||||
}, $params['page'], $params['limit']));
|
||||
}
|
||||
|
||||
private function sumOrder($params)
|
||||
{
|
||||
// 总收益
|
||||
return DatabaseRoute::getAllDbData('orders', function ($query) use ($params) {
|
||||
// 条件拼接
|
||||
if (!empty($params['sysUserId']) && $params['sysUserId'] != 1) {
|
||||
$query->where('sys_user_id', $params['sysUserId']);
|
||||
}
|
||||
|
||||
if (isset($params['status'])) {
|
||||
$query->where('status', $params['status']);
|
||||
}
|
||||
|
||||
if (isset($params['courseId'])) {
|
||||
$query->where('course_id', $params['courseId']);
|
||||
}
|
||||
|
||||
if (isset($params['ordersType'])) {
|
||||
$query->where('orders_type', $params['ordersType']);
|
||||
}
|
||||
|
||||
if (isset($params['flag']) && !empty($params['time'])) {
|
||||
switch ((int)$params['flag']) {
|
||||
case 1:
|
||||
// 按日
|
||||
$query->whereRaw("DATE_FORMAT(create_time, '%Y-%m-%d') = DATE_FORMAT(:time, '%Y-%m-%d')", ['time' => $params['time']]);
|
||||
break;
|
||||
case 2:
|
||||
// 按月
|
||||
$query->whereRaw("DATE_FORMAT(create_time, '%Y-%m') = DATE_FORMAT(:time, '%Y-%m')", ['time' => $params['time']]);
|
||||
break;
|
||||
case 3:
|
||||
// 按年
|
||||
$query->whereRaw("DATE_FORMAT(create_time, '%Y') = DATE_FORMAT(:time, '%Y')", ['time' => $params['time']]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$query->where('pay_way', 9)
|
||||
->where('status', 1); // 强制条件
|
||||
return $query;
|
||||
})->sum('pay_money');
|
||||
}
|
||||
|
||||
|
||||
public function selectCourseOrdersMoneyCount()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
|
||||
$params['ordersType'] = 1;
|
||||
$params['time'] = date('Y-m-d 00:00:00');
|
||||
// 总收益
|
||||
$sumMoney = $this->sumOrder($params);
|
||||
$params['flag'] = 3;
|
||||
$yearMoney = $this->sumOrder($params);
|
||||
$params['flag'] = 2;
|
||||
$monthMoney = $this->sumOrder($params);
|
||||
$params['flag'] = 1;
|
||||
$dayMoney = $this->sumOrder($params);
|
||||
$this->successWithData([
|
||||
'sumMoney' => $sumMoney ?? 0,
|
||||
'yearMoney' => $yearMoney ?? 0,
|
||||
'monthMoney' => $monthMoney ?? 0,
|
||||
'dayMoney' => $dayMoney ?? 0
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
// 订单数量统计
|
||||
public function selectOrdersCountStatisticsByYear()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$startTime = $get['startTime'];
|
||||
$endTime = $get['endTime'];
|
||||
|
||||
// 初始化结果数组
|
||||
$ordersCountList = [];
|
||||
$ordersDaiFuKuanCountList = [];
|
||||
$ordersYiZhiFuCountList = [];
|
||||
$ordersYiTuiKuanLunCountList = [];
|
||||
$dateList = [];
|
||||
|
||||
// 日期处理
|
||||
$currentDate = strtotime($startTime);
|
||||
$endDate = strtotime($endTime);
|
||||
|
||||
// 循环遍历日期范围
|
||||
while ($currentDate <= $endDate) {
|
||||
$date = date('Y-m-d', $currentDate);
|
||||
|
||||
// 总订单数
|
||||
$ordersCount = \app\admin\model\Order::selectOrdersCountStatisticsByYear(1, $date, null);
|
||||
$ordersCountList[] = $ordersCount;
|
||||
|
||||
// 0待支付
|
||||
$ordersDaiFuKuanCount = \app\admin\model\Order::selectOrdersCountStatisticsByYear(1, $date, 0);
|
||||
$ordersDaiFuKuanCountList[] = $ordersDaiFuKuanCount;
|
||||
|
||||
// 1已支付
|
||||
$ordersJinXinCount = \app\admin\model\Order::selectOrdersCountStatisticsByYear(1, $date, 1);
|
||||
$ordersYiZhiFuCountList[] = $ordersJinXinCount;
|
||||
|
||||
// 2已退款
|
||||
$ordersQuXiaoCount = \app\admin\model\Order::selectOrdersCountStatisticsByYear(1, $date, 2);
|
||||
$ordersYiTuiKuanLunCountList[] = $ordersQuXiaoCount;
|
||||
|
||||
// 记录日期
|
||||
$dateList[] = $date;
|
||||
|
||||
// 日期加1天
|
||||
$currentDate = strtotime('+1 day', $currentDate);
|
||||
}
|
||||
$result = [
|
||||
'ordersCountList' => $ordersCountList,
|
||||
'ordersDaiFuKuanCountList' => $ordersDaiFuKuanCountList,
|
||||
'ordersYiZhiFuCountList' => $ordersYiZhiFuCountList,
|
||||
'ordersYiTuiKuanLunCountList' => $ordersYiTuiKuanLunCountList,
|
||||
'year' => $dateList
|
||||
];
|
||||
$this->n_success(['data' => $result]);
|
||||
}
|
||||
|
||||
// 统计分销金币
|
||||
public function selectFenXiaoMoney()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$admin = $this->auth->getAdmin();
|
||||
$sysUserId = $admin['user_id'];
|
||||
$flag = $get['flag'];
|
||||
$time = $get['time'];
|
||||
|
||||
// 1. 分别查询一级、二级和渠道分销金额
|
||||
$oneMoney = \app\admin\model\Order::selectFenXiaoMoney(1, $sysUserId, $flag, $time);
|
||||
$twoMoney = \app\admin\model\Order::selectFenXiaoMoney(2, $sysUserId, $flag, $time);
|
||||
$qdMoney = \app\admin\model\Order::selectFenXiaoMoney(3, $sysUserId, $flag, $time);
|
||||
|
||||
// 2. 计算总分销金额(使用BCMath确保精度)
|
||||
$sumMoney = bcadd(
|
||||
bcadd($oneMoney, $twoMoney, 2), // 一级 + 二级
|
||||
$qdMoney, // + 渠道
|
||||
2 // 精度保留两位小数
|
||||
);
|
||||
|
||||
$result = [
|
||||
'oneMoney' => $oneMoney,
|
||||
'twoMoney' => $twoMoney,
|
||||
'qdMoney' => $qdMoney,
|
||||
'sumMoney' => $sumMoney
|
||||
];
|
||||
$this->n_success(['data' => $result]);
|
||||
}
|
||||
|
||||
// 订单统计
|
||||
public function selectOrdersCount()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$admin = $this->auth->getAdmin();
|
||||
$sysUserId = $admin['user_id'];
|
||||
$flag = $get['flag'];
|
||||
$time = $get['time'];
|
||||
|
||||
// 1. 短剧订单统计(数量)
|
||||
$sumCourseOrdersCount = \app\admin\model\Order::selectOrdersCount(null, 1, $flag, $time, $sysUserId);
|
||||
$daiCourseKeOrdersCount = \app\admin\model\Order::selectOrdersCount(0, 1, $flag, $time, $sysUserId);
|
||||
$wanCourseKeOrdersCount = \app\admin\model\Order::selectOrdersCount(1, 1, $flag, $time, $sysUserId);
|
||||
$tuiCourseOrdersCount = \app\admin\model\Order::selectOrdersCount(2, 1, $flag, $time, $sysUserId);
|
||||
|
||||
// 2. 短剧订单统计(金额)
|
||||
$sumCourseOrdersMoney = \app\admin\model\Order::selectOrdersMoney(null, 1, $flag, $time, null, $sysUserId);
|
||||
$daiCourseOrdersMoney = \app\admin\model\Order::selectOrdersMoney(0, 1, $flag, $time, null, $sysUserId);
|
||||
$wanCourseOrdersMoney = \app\admin\model\Order::selectOrdersMoney(1, 1, $flag, $time, null, $sysUserId);
|
||||
$tuiCourseOrdersMoney = \app\admin\model\Order::selectOrdersMoney(2, 1, $flag, $time, null, $sysUserId);
|
||||
|
||||
// 3. 会员订单统计(数量)
|
||||
$sumMemberOrdersCount = \app\admin\model\Order::selectOrdersCount(null, 2, $flag, $time, $sysUserId);
|
||||
$daiMemberKeOrdersCount = \app\admin\model\Order::selectOrdersCount(0, 2, $flag, $time, $sysUserId);
|
||||
$wanMemberKeOrdersCount = \app\admin\model\Order::selectOrdersCount(1, 2, $flag, $time, $sysUserId);
|
||||
$tuiMemberOrdersCount = \app\admin\model\Order::selectOrdersCount(2, 2, $flag, $time, $sysUserId);
|
||||
|
||||
// 4. 会员订单统计(金额)
|
||||
$sumMemberOrdersMoney = \app\admin\model\Order::selectOrdersMoney(null, 2, $flag, $time, null, $sysUserId);
|
||||
$daiMemberOrdersMoney = \app\admin\model\Order::selectOrdersMoney(0, 2, $flag, $time, null, $sysUserId);
|
||||
$wanMemberOrdersMoney = \app\admin\model\Order::selectOrdersMoney(1, 2, $flag, $time, null, $sysUserId);
|
||||
$tuiMemberOrdersMoney = \app\admin\model\Order::selectOrdersMoney(2, 2, $flag, $time, null, $sysUserId);
|
||||
|
||||
// 5. 提现统计
|
||||
$timestamp = strtotime($time); // 将日期字符串转为时间戳
|
||||
$beginOfDay = date('Y-m-d 00:00:00', $timestamp); // 当天开始时间
|
||||
$endOfDay = date('Y-m-d 23:59:59', $timestamp); // 当天结束时间
|
||||
|
||||
$cashCount = DatabaseRoute::getAllDbData('cash_out', function ($query) use($sysUserId, $beginOfDay) {
|
||||
if (!is_null($sysUserId)) {
|
||||
$query->where(['sys_user_id' => $sysUserId]);
|
||||
}
|
||||
$query->where('state', 1)->where('create_at', '>', $beginOfDay);
|
||||
return $query;
|
||||
})->count();
|
||||
|
||||
|
||||
$cashSum = DatabaseRoute::getAllDbData('cash_out', function ($query) use($sysUserId, $beginOfDay, $endOfDay) {
|
||||
if (!is_null($sysUserId)) {
|
||||
$query->where(['sys_user_id' => $sysUserId]);
|
||||
}
|
||||
$query->whereBetween('create_at', [$beginOfDay, $endOfDay]);
|
||||
return $query;
|
||||
})->sum('money') ?? 0;
|
||||
|
||||
|
||||
|
||||
$cashSum = number_format($cashSum, 2, '.', ''); // 保留两位小数
|
||||
|
||||
// 6. 奖励金额统计
|
||||
$signInAwardMoney = \app\admin\model\Order::selectSignInAwardMoney($flag, $time, $sysUserId);
|
||||
$shareAwardMoney = \app\admin\model\Order::selectShareAwardMoney($flag, $time, $sysUserId);
|
||||
$newUserTaskDoneAwardMoney = \app\admin\model\Order::selectNewUserTaskDoneAwardMoney($flag, $time, $sysUserId);
|
||||
$inviteTaskDoneAwardMoney = \app\admin\model\Order::selectInviteTaskDoneAwardMoney($flag, $time, $sysUserId);
|
||||
|
||||
// 7. 组装结果
|
||||
$result = [
|
||||
// 短剧订单数量
|
||||
'sumCourseOrdersCount' => $sumCourseOrdersCount ?? 0,
|
||||
'daiCourseKeOrdersCount' => $daiCourseKeOrdersCount ?? 0,
|
||||
'wanCourseKeOrdersCount' => $wanCourseKeOrdersCount ?? 0,
|
||||
'tuiCourseOrdersCount' => $tuiCourseOrdersCount ?? 0,
|
||||
// 短剧订单金额
|
||||
'sumCourseOrdersMoney' => $sumCourseOrdersMoney ?? 0.00,
|
||||
'daiCourseOrdersMoney' => $daiCourseOrdersMoney ?? 0.00,
|
||||
'wanCourseOrdersMoney' => $wanCourseOrdersMoney ?? 0.00,
|
||||
'tuiCourseOrdersMoney' => $tuiCourseOrdersMoney ?? 0.00,
|
||||
// 会员订单数量
|
||||
'sumMemberOrdersCount' => $sumMemberOrdersCount ?? 0,
|
||||
'daiMemberKeOrdersCount' => $daiMemberKeOrdersCount ?? 0,
|
||||
'wanMemberKeOrdersCount' => $wanMemberKeOrdersCount ?? 0,
|
||||
'tuiMemberOrdersCount' => $tuiMemberOrdersCount ?? 0,
|
||||
// 会员订单金额
|
||||
'sumMemberOrdersMoney' => $sumMemberOrdersMoney ?? 0.00,
|
||||
'daiMemberOrdersMoney' => $daiMemberOrdersMoney ?? 0.00,
|
||||
'wanMemberOrdersMoney' => $wanMemberOrdersMoney ?? 0.00,
|
||||
'tuiMemberOrdersMoney' => $tuiMemberOrdersMoney ?? 0.00,
|
||||
// 提现数据
|
||||
'cashCount' => $cashCount ?? 0,
|
||||
'cashSum' => $cashSum,
|
||||
// 奖励金额
|
||||
'signInAwardMoney' => $signInAwardMoney ?? 0.00,
|
||||
'shareAwardMoney' => $shareAwardMoney ?? 0.00,
|
||||
'newUserTaskDoneAwardMoney' => $newUserTaskDoneAwardMoney ?? 0.00,
|
||||
'inviteTaskDoneAwardMoney' => $inviteTaskDoneAwardMoney ?? 0.00,
|
||||
];
|
||||
|
||||
$this->n_success(['data' => $result]);
|
||||
}
|
||||
|
||||
public function queryByTradeNo()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if (empty($get['outTradeNo'])) {
|
||||
$this->error('参数不能为空');
|
||||
}
|
||||
$outTradeNo = $get['outTradeNo'];
|
||||
$tradeNo = null;
|
||||
$userId = null;
|
||||
try {
|
||||
// 解析外部交易号(提现回调格式:xxx-xxx:xxx)
|
||||
if (strpos($outTradeNo, '-') !== false && strpos($outTradeNo, ':') !== false) {
|
||||
$parts = explode('-', $outTradeNo);
|
||||
$tradeNo = $parts[0];
|
||||
$userIdPart = explode(':', $parts[1])[0];
|
||||
$userId = (int)$userIdPart;
|
||||
}
|
||||
// 解析支付回调格式(xxx-xxx)
|
||||
elseif (strpos($outTradeNo, '-') !== false) {
|
||||
$parts = explode('-', $outTradeNo);
|
||||
$tradeNo = $parts[0];
|
||||
$userId = (int)$parts[1];
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->error("交易订单号不合法");
|
||||
}
|
||||
|
||||
// 验证解析结果
|
||||
if (empty($tradeNo) || $userId === null) {
|
||||
$this->error("交易订单号不合法");
|
||||
}
|
||||
|
||||
// 初始化汇总数据
|
||||
$data = [];
|
||||
|
||||
// 查询用户基本信息
|
||||
$user = TbUser::selectUserById($userId);
|
||||
$data['user_info'] = $user ?: [];
|
||||
|
||||
// 查询用户实名认证信息
|
||||
$realNameAuth = \app\api\model\UserInfo::getByUserIdOrSave($userId);
|
||||
$data['auth_info'] = $realNameAuth ?: [];
|
||||
|
||||
// 初始化提现统计(success:成功, fail:失败, auditing:审核中, other:其他)
|
||||
$withdrawTotal = [
|
||||
'success' => ['total' => 0.00, 'count' => 0],
|
||||
'fail' => ['total' => 0.00, 'count' => 0],
|
||||
'auditing' => ['total' => 0.00, 'count' => 0],
|
||||
'other' => ['total' => 0.00, 'count' => 0],
|
||||
];
|
||||
|
||||
// 初始化支付统计(success:成功, fail:失败, unpaid:未支付)
|
||||
$payTotal = [
|
||||
'success' => ['total' => 0.00, 'count' => 0],
|
||||
'fail' => ['total' => 0.00, 'count' => 0],
|
||||
'unpaid' => ['total' => 0.00, 'count' => 0],
|
||||
];
|
||||
|
||||
|
||||
// 查询提现记录并统计
|
||||
$cashOutList = DatabaseRoute::getDb('cash_out', $userId)->select()->toArray();
|
||||
if (!empty($cashOutList)) {
|
||||
// 按状态分组统计总金额和数量
|
||||
$cashOutSum = []; // 金额统计:[状态 => 总金额]
|
||||
$cashOutCount = []; // 数量统计:[状态 => 总条数]
|
||||
|
||||
foreach ($cashOutList as $cash) {
|
||||
$state = $cash['state'];
|
||||
$money = (float)$cash['money'];
|
||||
|
||||
// 累加金额
|
||||
if (!isset($cashOutSum[$state])) {
|
||||
$cashOutSum[$state] = 0.00;
|
||||
}
|
||||
$cashOutSum[$state] += $money;
|
||||
|
||||
// 累加数量
|
||||
if (!isset($cashOutCount[$state])) {
|
||||
$cashOutCount[$state] = 0;
|
||||
}
|
||||
$cashOutCount[$state]++;
|
||||
}
|
||||
|
||||
// 更新成功/失败/审核中状态的统计
|
||||
$withdrawTotal['success'] = [
|
||||
'total' => $cashOutSum[1] ?? 0.00,
|
||||
'count' => $cashOutCount[1] ?? 0
|
||||
];
|
||||
$withdrawTotal['fail'] = [
|
||||
'total' => $cashOutSum[2] ?? 0.00,
|
||||
'count' => $cashOutCount[2] ?? 0
|
||||
];
|
||||
$withdrawTotal['auditing'] = [
|
||||
'total' => $cashOutSum[3] ?? 0.00,
|
||||
'count' => $cashOutCount[3] ?? 0
|
||||
];
|
||||
|
||||
// 统计其他状态(排除1/2/3)
|
||||
$otherStates = [1, 2, 3];
|
||||
$otherMoney = 0.00;
|
||||
$otherCount = 0;
|
||||
foreach ($cashOutList as $cash) {
|
||||
if (!in_array($cash['state'], $otherStates)) {
|
||||
$otherMoney += (float)$cash['money'];
|
||||
$otherCount++;
|
||||
}
|
||||
}
|
||||
$withdrawTotal['other'] = [
|
||||
'total' => $otherMoney,
|
||||
'count' => $otherCount
|
||||
];
|
||||
}
|
||||
$data['withdraw_total'] = $withdrawTotal;
|
||||
|
||||
// 查询支付记录并统计
|
||||
$payDetailsList = DatabaseRoute::getDb('pay_details', $userId)->select()->toArray();
|
||||
if (!empty($payDetailsList)) {
|
||||
// 按状态分组统计总金额和数量
|
||||
$paySum = []; // 金额统计:[状态 => 总金额]
|
||||
$payCount = []; // 数量统计:[状态 => 总条数]
|
||||
|
||||
foreach ($payDetailsList as $pay) {
|
||||
$state = $pay['state'];
|
||||
$money = (float)$pay['money'];
|
||||
|
||||
// 累加金额
|
||||
if (!isset($paySum[$state])) {
|
||||
$paySum[$state] = 0.00;
|
||||
}
|
||||
$paySum[$state] += $money;
|
||||
|
||||
// 累加数量
|
||||
if (!isset($payCount[$state])) {
|
||||
$payCount[$state] = 0;
|
||||
}
|
||||
$payCount[$state]++;
|
||||
}
|
||||
|
||||
// 更新支付统计(1:成功, 2:失败, 0:未支付)
|
||||
$payTotal['success'] = [
|
||||
'total' => $paySum[1] ?? 0.00,
|
||||
'count' => $payCount[1] ?? 0
|
||||
];
|
||||
$payTotal['fail'] = [
|
||||
'total' => $paySum[2] ?? 0.00,
|
||||
'count' => $payCount[2] ?? 0
|
||||
];
|
||||
$payTotal['unpaid'] = [
|
||||
'total' => $paySum[0] ?? 0.00,
|
||||
'count' => $payCount[0] ?? 0
|
||||
];
|
||||
}
|
||||
$data['pay_total'] = $payTotal;
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
63
app/czg/controller/PayClassifyController.php
Normal file
63
app/czg/controller/PayClassifyController.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class PayClassifyController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function selectPayClassifyList()
|
||||
{
|
||||
$infos = Db::name('pay_classify')->select()->toArray();
|
||||
foreach ($infos as $k => &$v) {
|
||||
$v['pay_classify_id'] = (string) $v['pay_classify_id'];
|
||||
}
|
||||
$this->successWithData([
|
||||
'currPage' => 1,
|
||||
'pageSize' => count($infos),
|
||||
'totalCount' => count($infos),
|
||||
'totalPage' => 1,
|
||||
'list' => convertToCamelCase($infos)
|
||||
]);
|
||||
}
|
||||
|
||||
public function updatePayClassify()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
if (empty($params['payClassifyId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
unset($params['memberId']);
|
||||
Db::name('pay_classify')->where([
|
||||
'pay_classify_id' => $params['payClassifyId']
|
||||
])->update(convertKeysCamelToSnakeRecursive($params));
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function insertPayClassify()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params['create_time'] = getNormalDate();
|
||||
unset($params['memberId']);
|
||||
unset($params['payClassifyId']);
|
||||
Db::name('pay_classify')->insert(convertKeysCamelToSnakeRecursive($params));
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function deletePayClassify()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
if (empty($params['payClassifyId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
Db::name('pay_classify')->delete([
|
||||
'pay_classify_id' => $params['payClassifyId']
|
||||
]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
38
app/czg/controller/SdkController.php
Normal file
38
app/czg/controller/SdkController.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class SdkController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['getSdkList'];
|
||||
|
||||
|
||||
public function getSdkList()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
$sdkINfo = [
|
||||
'sdkRemarks' => $get['sdkRemarks'] ?? null,
|
||||
'status' => $get['status'] ?? null,
|
||||
'typeId' => $get['typeId'] ?? null,
|
||||
'nickName' => $get['nickName'] ?? null,
|
||||
'sdkContent' => $get['sdkContent'] ?? null,
|
||||
];
|
||||
$this->n_success(['data' => [
|
||||
'list' => [],
|
||||
'totalCount' => 0,
|
||||
'totalPage' => 0,
|
||||
'currPage' => 1,
|
||||
'pageSize' => 0,
|
||||
]]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
242
app/czg/controller/SysController.php
Normal file
242
app/czg/controller/SysController.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\Msg;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\facade\Token;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
use think\Http;
|
||||
|
||||
class SysController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function login()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
if(empty($data['username']) || empty($data['password']) || empty($data['uuid']) || empty($data['captcha']) || empty($data['adminType'])){
|
||||
$this->n_error('参数不完整');
|
||||
}
|
||||
$uuid = $data['uuid'];
|
||||
$connect = Db::connect(get_slave_connect_name());
|
||||
$captcha = $connect->name('sys_captcha')->where(['uuid' => $uuid, 'code' => $data['captcha']])->find();
|
||||
if(!$captcha) {
|
||||
$this->n_error('验证码错误', [], 500);
|
||||
}
|
||||
$ext_time = strtotime($captcha['expire_time']);
|
||||
if(time() > $ext_time) {
|
||||
$this->n_error('验证码已经过期', [], 500);
|
||||
}
|
||||
$res = $this->auth->login($data['username'], $data['password']);
|
||||
if (isset($res) && $res === true) {
|
||||
$user = $this->auth->getAdmin();
|
||||
if($data['adminType'] == 1 && $user['is_channel'] != null && $user['is_channel'] == 1) {
|
||||
$this->n_error('代理账号请登录代理端', [], 500);
|
||||
}
|
||||
if($data['adminType'] == 2 && $user['is_channel'] == null) {
|
||||
$this->n_error('管理员请登录管理端', [], 500);
|
||||
}
|
||||
$this->n_success([
|
||||
'token' => $this->auth->getToken()
|
||||
]);
|
||||
} else {
|
||||
$msg = $this->auth->getError();
|
||||
$msg = $msg ?: __('Check in failed, please try again or contact the website administrator~');
|
||||
$this->n_error($msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员注销
|
||||
* @return void
|
||||
*/
|
||||
public function logout(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$refreshToken = $this->request->post('refreshToken', '');
|
||||
if ($refreshToken) Token::delete((string)$refreshToken);
|
||||
$this->auth->logout();
|
||||
$this->success();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 邀请好友奖励分页
|
||||
* @return void
|
||||
*/
|
||||
public function invitefriendaward()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$subQuery = DatabaseRoute::getAllDbData('user_money_details', function ($query) use ($params) {
|
||||
return $query->field('user_id, SUM(money) as awardAmount, SUM(IF(title = "签到奖励", 1, 0)) as signInNum')
|
||||
->where('classify', 6)->group('user_id');
|
||||
})->buildSql();
|
||||
|
||||
$result = DatabaseRoute::paginateAllDb('tb_user', function ($query) use ($subQuery , $params) {
|
||||
$query->alias('t1')
|
||||
->field([
|
||||
't1.user_id as userId',
|
||||
't1.user_name as userName',
|
||||
't1.phone',
|
||||
't1.avatar',
|
||||
'IFNULL(t2.signInNum, 0) as signInNum',
|
||||
'IFNULL(t2.awardAmount, 0) as awardAmount'
|
||||
])
|
||||
->leftJoin("{$subQuery} t2", 't1.user_id = t2.user_id');
|
||||
if(!empty($params['keywords'])) {
|
||||
$query->where('t1.user_name', $params['keywords'])->whereOr('t1.phone', $params['keywords']);
|
||||
}
|
||||
$query->order('t2.signInNum', 'desc');
|
||||
$query->order('t1.user_id', 'asc');
|
||||
return $query;
|
||||
}, (int)$params['page'], (int)$params['limit']);
|
||||
$this->n_success(['data' => $result]);
|
||||
}
|
||||
/**
|
||||
* 奖励详情
|
||||
* @return void
|
||||
*/
|
||||
public function invitefrienddetail()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$userId = $params['userId'];
|
||||
$result = DatabaseRoute::paginateAllDb('user_money_details', function ($query) use ($params, $userId) {
|
||||
$query->alias('t1')
|
||||
->field([
|
||||
't1.by_user_id AS userId',
|
||||
't1.money AS amount',
|
||||
't2.phone AS userPhone',
|
||||
't1.create_time AS createTime'
|
||||
])
|
||||
->leftJoin('tb_user t2', 't1.by_user_id = t2.user_id')
|
||||
->where('t1.user_id', $userId)
|
||||
->where('t1.classify', 6)
|
||||
->whereNotNull('t1.by_user_id')
|
||||
->whereNotNull('t2.user_id')
|
||||
->order('t1.create_time', 'desc')
|
||||
->order('t1.by_user_id', 'asc');
|
||||
return $query;
|
||||
}, (int)$params['page'], (int)$params['limit'], 'createTime');
|
||||
$this->successWithData($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请好友奖励-签到人数分页
|
||||
* @return void
|
||||
*/
|
||||
public function signindetailpage()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$userId = $params['userId'];
|
||||
// 先获取总数
|
||||
$count = DatabaseRoute::getAllDbData('user_money_details', function ($query) use($userId) {
|
||||
return $query->alias('t')
|
||||
->field('t.by_user_id')
|
||||
->where('t.user_id', $userId)
|
||||
->where('t.classify', 6)
|
||||
->where('t.title', '签到奖励')
|
||||
->group('t.by_user_id');
|
||||
})->count();
|
||||
$v_db_name = config('database.connections.' . get_slave_connect_name() . '.database');
|
||||
$result = DatabaseRoute::paginateAllDbBySqlAutoCount(function () use($userId, $v_db_name) {
|
||||
return "select
|
||||
t1.by_user_id as userId,
|
||||
t1.createTime,
|
||||
t2.user_name as userName,
|
||||
t2.phone,
|
||||
t3.cert_name as realName,
|
||||
t3.cert_no as idCardNo,
|
||||
t3.bank_name as bankName,
|
||||
t3.account_no as bankCardNo,
|
||||
t3.mobile,
|
||||
t3.province,
|
||||
t3.city,
|
||||
t3.bank_branch as bankBranch
|
||||
from (
|
||||
SELECT
|
||||
t.by_user_id,
|
||||
MIN( t.create_time ) as createTime
|
||||
FROM
|
||||
" . $v_db_name . ".v_user_money_details t
|
||||
WHERE 1=1
|
||||
AND t.user_id = ".$userId."
|
||||
AND t.classify = 6
|
||||
AND t.title = '签到奖励'
|
||||
GROUP BY t.by_user_id
|
||||
) t1
|
||||
LEFT JOIN " . $v_db_name . ".v_tb_user t2 on t1.by_user_id = t2.user_id
|
||||
LEFT JOIN " . $v_db_name . ".v_user_info t3 on t1.by_user_id = t3.user_id
|
||||
order by t1.createTime desc,t1.by_user_id asc";
|
||||
}, $params['page'], $params['limit'], null, $count);
|
||||
$this->successWithData($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽奖次数查询-分页
|
||||
* @return void
|
||||
*/
|
||||
public function lotterypage()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$keywords = $params['keywords'];
|
||||
$v_db_name = config('database.connections.' . get_slave_connect_name() . '.database');
|
||||
$result = DatabaseRoute::paginateAllDb('tb_user', function ($query) use($keywords, $v_db_name) {
|
||||
return $query->alias('t1')
|
||||
->field([
|
||||
't1.user_id as userId',
|
||||
't1.avatar',
|
||||
't1.user_name as userName',
|
||||
't1.phone',
|
||||
// 今日解锁订单数
|
||||
'(SELECT COUNT(1) FROM '. $v_db_name .'.v_orders WHERE STATUS = 1 AND pay_way = 9 AND user_id = t1.user_id AND pay_time >= DATE_FORMAT(CURDATE(), "%Y-%m-%d 00:00:00") AND pay_time <= DATE_FORMAT(CURDATE(), "%Y-%m-%d 23:59:59")) as todayUnlocked',
|
||||
// 今日抽奖次数
|
||||
'(SELECT COUNT(1) FROM '. $v_db_name .'.v_disc_spinning_record WHERE user_id = t1.user_id AND DATE_FORMAT(create_time, "%Y-%m-%d") = CURDATE()) as todayDrawCount'
|
||||
])
|
||||
->where(function ($query) use ($keywords) {
|
||||
$query->where('t1.user_name', $keywords)
|
||||
->whereOr('t1.phone', $keywords);
|
||||
})
|
||||
->order('todayUnlocked', 'desc')
|
||||
->order('t1.user_id', 'asc');
|
||||
}, $params['page'], $params['limit']);
|
||||
|
||||
$this->n_success(['data' => $result]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽奖详情-分页
|
||||
* @return void
|
||||
*/
|
||||
public function lotterydetailpage()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$userId = $params['userId'];
|
||||
// 先获取总数
|
||||
$count = Db::connect(get_slave_connect_name())->query("select
|
||||
count(*) count
|
||||
from v_disc_spinning_record t1
|
||||
where t1.user_id = ".$userId);
|
||||
$count = $count[0]['count'];
|
||||
$v_db_name = config('database.connections.' . get_slave_connect_name() . '.database');
|
||||
$result = DatabaseRoute::paginateAllDbBySqlAutoCount(function () use($userId, $v_db_name) {
|
||||
return "select
|
||||
t1.id,
|
||||
t1.name,
|
||||
t1.number,
|
||||
t1.create_time
|
||||
from ". $v_db_name .".v_disc_spinning_record t1
|
||||
where t1.user_id = " . $userId . "
|
||||
order by t1.id desc";
|
||||
}, $params['page'], $params['limit'], null, $count);
|
||||
$this->successWithData($result);
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
public function sendMsg()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
return $this->ApiDataReturn(Msg::sendMsg($get['phone'], $get['event']));
|
||||
}
|
||||
}
|
||||
56
app/czg/controller/TaskCenterController.php
Normal file
56
app/czg/controller/TaskCenterController.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class TaskCenterController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
public function selectTaskCenter()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$this->successWithData(DatabaseRoute::paginateDb('task_center', function ($query) use ($params) {
|
||||
return $query->order('sort');
|
||||
}, $params['page'], $params['limit'], null, true));
|
||||
}
|
||||
|
||||
public function updateTaskCenter()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['update_time'] = getNormalDate();
|
||||
unset($params['disc_number']);
|
||||
unset($params['disabled']);
|
||||
Db::name('task_center')->where([
|
||||
'id' => $params['id']
|
||||
])->update($params);
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
public function insertTaskCenter()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['create_time'] = getNormalDate();
|
||||
unset($params['is_trusted']);
|
||||
Db::name('task_center')->insert($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function deleteTaskCenter()
|
||||
{
|
||||
$id = $this->request->param('id');
|
||||
Db::name('task_center')->delete([
|
||||
'id' => $id
|
||||
]);
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
}
|
||||
69
app/czg/controller/TaskCenterRewardController.php
Normal file
69
app/czg/controller/TaskCenterRewardController.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class TaskCenterRewardController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
public function selectTaskCenterReward()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$this->successWithData(DatabaseRoute::paginateDb('task_center_reward', function ($query) use ($params) {
|
||||
if (!empty($params['taskId'])) {
|
||||
$query->where([
|
||||
'task_id' => $params['taskId']
|
||||
]);
|
||||
}
|
||||
return $query->order('id', false);
|
||||
|
||||
}, $params['page'] ?? 1, $params['limit'] ?? 10));
|
||||
}
|
||||
|
||||
public function updateTaskCenterReward()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$info = Db::name('task_center_reward')->where([
|
||||
'id' => $params['id']
|
||||
]);
|
||||
|
||||
if (!empty($info['total_number']) && !empty($params['total_number']) && $info['total_number'] != $params['total_number']) {
|
||||
$surplusNumber = $params['total_number'] - $info['total_number'];
|
||||
$surplusNumber = $surplusNumber > 0 ?? $params['total_number'];
|
||||
$params['total_number'] = $surplusNumber;
|
||||
}
|
||||
|
||||
$params['update_time'] = getNormalDate();
|
||||
Db::name('task_center_reward')->where([
|
||||
'id' => $params['id']
|
||||
])->update($params);
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function insertTaskCenterReward()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['surplus_number'] = $params['total_number'];
|
||||
unset($params['is_trusted']);
|
||||
unset($params['id']);
|
||||
Db::name('task_center_reward')->insert($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function deleteTaskCenterReward()
|
||||
{
|
||||
$id = $this->request->param('id');
|
||||
Db::name('task_center_reward')->delete([
|
||||
'id' => $id
|
||||
]);
|
||||
$this->success();
|
||||
}
|
||||
}
|
||||
97
app/czg/controller/UrlAddressController.php
Normal file
97
app/czg/controller/UrlAddressController.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use think\facade\Db;
|
||||
|
||||
class UrlAddressController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
public function selectUrlAddress()
|
||||
{
|
||||
$info = Db::name('url_address')->order('num', 'asc')->limit(1)->find();
|
||||
if ($info) {
|
||||
$info['num'] = $info['num'] ? $info['num'] + 1 : 1;
|
||||
Db::name('url_address')->where([
|
||||
'url_id' => $info['url_id']
|
||||
])->update([
|
||||
'num' => $info['num']
|
||||
]);
|
||||
}
|
||||
|
||||
$this->successWithData(convertToCamelCase($info));
|
||||
|
||||
}
|
||||
|
||||
public function selectUrlAddressList()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$page = $get['page']; // 页码,默认1
|
||||
$limit = $get['limit']; // 每页条数,默认10
|
||||
$urlAddress = $get['urlAddress']; // URL地址关键词
|
||||
$status = $get['status']; // 状态值
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
// 构建查询
|
||||
$query = $db->name('url_address');
|
||||
if(!empty($urlAddress)) {
|
||||
$query->where('url_address', 'like', "%{$urlAddress}%");
|
||||
}
|
||||
if(!empty($status)) {
|
||||
$query->where('status', $status);
|
||||
}
|
||||
$count = $query->count();
|
||||
$info = $query->limit(page($page, $limit), $limit)->select()->toArray();
|
||||
$this->n_success(['data' => [
|
||||
'totalCount' => $count,
|
||||
'pageSize' => $get['limit'],
|
||||
'totalPage' => ceil($count / $get['limit']),
|
||||
'currPage' => $get['page'],
|
||||
'list' => $info,
|
||||
'records' => null
|
||||
]]);
|
||||
}
|
||||
|
||||
|
||||
public function updateUrlAddress()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
|
||||
$url_id = $post['urlId'] ?? null;
|
||||
$data['num'] = $post['num'] ?? null;
|
||||
$data['url_address'] = $post['urlAddress'] ?? null;
|
||||
$data['status'] = $post['status'] ?? null;
|
||||
Db::name('url_address')->where(['url_id' => $url_id])->update($data);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
// 创建域名
|
||||
public function insertUrlAddress()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
$data['num'] = $post['num'] ?? null;
|
||||
$data['url_address'] = $post['urlAddress'] ?? null;
|
||||
$data['status'] = $post['status'] ?? null;
|
||||
$data['create_time'] = date('Y-m-d H:i:s');
|
||||
Db::name('url_address')->insert($data);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function deleteUrlAddress()
|
||||
{
|
||||
$param = $this->request->get();
|
||||
if(empty($param['addressId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
Db::name('url_address')->where(['url_id' => $param['addressId']])->delete();
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
542
app/czg/controller/UserController.php
Normal file
542
app/czg/controller/UserController.php
Normal file
@@ -0,0 +1,542 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\api\model\TbUser;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\User as UserModel;
|
||||
|
||||
class UserController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var UserModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected array $withJoinTable = ['userGroup'];
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['last_login_time', 'login_failure', 'password', 'salt'];
|
||||
|
||||
protected string|array $quickSearchField = ['username', 'nickname', 'id'];
|
||||
|
||||
protected array $noNeedPermission = [
|
||||
'courseMessage',
|
||||
'userMessage',
|
||||
'selectUserOnLineCount',
|
||||
'homeMessage',
|
||||
'selectUserCountStatisticsByTime',
|
||||
'selectUserList',
|
||||
'updateUserStatusByUserId',
|
||||
'inviteAmount',
|
||||
'selectUserByInvitationCode',
|
||||
'getuserinfo',
|
||||
'deleteUserByUserId',
|
||||
];
|
||||
protected array $noNeedLogin = ['userListExcel'];
|
||||
public function initialize(): void
|
||||
{
|
||||
// $this->model = new UserModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$result = false;
|
||||
$passwd = $data['password']; // 密码将被排除不直接入库
|
||||
$data = $this->excludeFields($data);
|
||||
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
|
||||
if (!empty($passwd)) {
|
||||
$this->model->resetPassword($this->model->id, $passwd);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$password = $this->request->post('password', '');
|
||||
if ($password) {
|
||||
$this->model->resetPassword($id, $password);
|
||||
}
|
||||
parent::edit();
|
||||
}
|
||||
|
||||
unset($row->salt);
|
||||
$row->password = '';
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写select
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function select(): void
|
||||
{
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($res as $re) {
|
||||
$re->nickname_text = $re->username . '(ID:' . $re->id . ')';
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
// 短剧分析
|
||||
public function courseMessage()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$admin = $this->auth->getAdmin();
|
||||
$pageUtils = \app\admin\model\User::queryCourseOrder($get['page'], $get['limit'], $get['type'], completeStartTime($get['date']), $admin['user_id']);
|
||||
$this->n_success(['data' => $pageUtils]);
|
||||
}
|
||||
|
||||
// 用户分析
|
||||
public function userMessage()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$admin = $this->auth->getAdmin();
|
||||
// 补全开始时间(调用之前实现的函数)
|
||||
$date = completeStartTime($get['date']); // 假设已实现该函数
|
||||
$qdCode = $admin['qd_code'];
|
||||
$sumUserCount = \app\admin\model\User::queryUserCount($get['type'], $date, null, $qdCode);
|
||||
$h5Count = \app\admin\model\User::queryUserCount($get['type'], $date, "h5", $qdCode);
|
||||
$appCount = \app\admin\model\User::queryUserCount($get['type'], $date, "app", $qdCode);
|
||||
$wxCount = \app\admin\model\User::queryUserCount($get['type'], $date, "小程序", $qdCode);
|
||||
$dyCount = \app\admin\model\User::queryUserCount($get['type'], $date, "抖音", $qdCode);
|
||||
$giveMemberCount = \app\admin\model\User::userMessage($date, $get['type'], $qdCode, 1);
|
||||
$moneyMemberCount = \app\admin\model\User::userMessage($date, $get['type'], $qdCode, 2);
|
||||
$memberCount = \app\admin\model\User::userMessage($date, $get['type'], $qdCode, null);
|
||||
$userCount = $sumUserCount - $memberCount;
|
||||
$this->n_success(['data' => [
|
||||
'sumUserCount' => $sumUserCount,
|
||||
'h5Count' => $h5Count,
|
||||
'appCount' => $appCount,
|
||||
'wxCount' => $wxCount,
|
||||
'dyCount' => $dyCount,
|
||||
'memberCount' => $memberCount,
|
||||
'giveMemberCount' => $giveMemberCount,
|
||||
'moneyMemberCount' => $moneyMemberCount,
|
||||
'userCount' => $userCount,
|
||||
]]);
|
||||
}
|
||||
|
||||
// 当前在线人数统计
|
||||
public function selectUserOnLineCount()
|
||||
{
|
||||
$admin = $this->auth->getAdmin();
|
||||
$qdCode = $admin['qd_code'];
|
||||
$selectUserOnLineCount = DatabaseRoute::getAllDbData('tb_user', function($query)use($qdCode) {
|
||||
if($query) {
|
||||
$query->where(['qd_code' => $qdCode]);
|
||||
}
|
||||
return $query->where('on_line_time', '>=', Db::raw('DATE_SUB(NOW(), INTERVAL 10 MINUTE)'));
|
||||
})->count();
|
||||
$this->n_success(['data' => $selectUserOnLineCount]);
|
||||
}
|
||||
|
||||
// 用户统计
|
||||
public function homeMessage()
|
||||
{
|
||||
$admin = $this->auth->getAdmin();
|
||||
$qdCode = $admin['qd_code'];
|
||||
$data = [];
|
||||
$data['totalUsers'] = \app\admin\model\User::queryUserCount(0, null, null, $qdCode);
|
||||
$data['newToday'] = \app\admin\model\User::queryUserCount(1, null, null, $qdCode);
|
||||
$data['newMonth'] = \app\admin\model\User::queryUserCount(2, null, null, $qdCode);
|
||||
$data['newYear'] = \app\admin\model\User::queryUserCount(3, null, null, $qdCode);
|
||||
$data['totalRevenue'] = \app\admin\model\User::queryPayMoney(0, $qdCode);
|
||||
$data['todayRevenue'] = \app\admin\model\User::queryPayMoney(1, $qdCode);
|
||||
$data['monthRevenue'] = \app\admin\model\User::queryPayMoney(2, $qdCode);
|
||||
$data['yearRevenue'] = \app\admin\model\User::queryPayMoney(3, $qdCode);
|
||||
$map = \app\admin\model\User::queryPayAndExtractInfo();
|
||||
$data['todayPayAmount'] = isset($map['payAmount'])
|
||||
? round((float)$map['payAmount'], 2, PHP_ROUND_HALF_UP)
|
||||
: 0.00;
|
||||
$data['todayPayCount'] = isset($map['payCount'])
|
||||
? (int)$map['payCount']
|
||||
: 0;
|
||||
$data['todayExtractAmount'] = isset($map['extractAmount'])
|
||||
? round((float)$map['extractAmount'], 2, PHP_ROUND_HALF_UP)
|
||||
: 0.00;
|
||||
|
||||
$data['todayExtractCount'] = isset($map['extractCount'])
|
||||
? (int)$map['extractCount']
|
||||
: 0;
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
// 用户增长折线图
|
||||
public function selectUserCountStatisticsByTime()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$startTime = $get['startTime'];
|
||||
$endTime = $get['endTime'];
|
||||
|
||||
// 初始化结果数组
|
||||
$userCountList = [];
|
||||
$dateList = [];
|
||||
|
||||
// 日期处理
|
||||
$currentDate = strtotime($startTime);
|
||||
$endDate = strtotime($endTime);
|
||||
|
||||
// 循环遍历日期范围
|
||||
while ($currentDate <= $endDate) {
|
||||
$date = date('Y-m-d', $currentDate);
|
||||
|
||||
// 查询当日用户注册数量
|
||||
$userCount = \app\admin\model\User::queryUserCount(1, $date, null, null);
|
||||
|
||||
// 记录数据
|
||||
$userCountList[] = $userCount;
|
||||
$dateList[] = $date;
|
||||
|
||||
// 日期加1天
|
||||
$currentDate = strtotime('+1 day', $currentDate);
|
||||
}
|
||||
|
||||
// 构建结果数据
|
||||
$result = [
|
||||
'userCountList' => $userCountList,
|
||||
'year' => $dateList // 注:原Java代码中使用year变量,但实际存储的是日期列表
|
||||
];
|
||||
|
||||
$this->n_success(['data' => $result]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 查询所有用户列表
|
||||
public function selectUserList()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
p(2312);
|
||||
$vipType = $params['vipType'] ?? null;
|
||||
$member = $params['member'] ?? null;
|
||||
$status = $params['status'] ?? null;
|
||||
$page = $params['page'] ?? null;
|
||||
$limit = $params['limit'] ?? null;
|
||||
$phone = $params['phone'] ?? null;
|
||||
$sysUserName = $params['sysUserName'] ?? null;
|
||||
$userName = $params['userName'] ?? null;
|
||||
$sex = $params['sex'] ?? null;
|
||||
$platform = $params['platform'] ?? null;
|
||||
$sysPhone = $params['sysPhone'] ?? null;
|
||||
$inviterCode = $params['inviterCode'] ?? null;
|
||||
$invitationCode = $params['invitationCode'] ?? null;
|
||||
$qdCode = $params['qdCode'] ?? null;
|
||||
$startTime = $params['startTime'] ?? null;
|
||||
$endTime = $params['endTime'] ?? null;
|
||||
$delegate = $params['delegate'] ?? null;
|
||||
$this->n_success(['data' => \app\admin\model\User::selectUserPage(
|
||||
$page, $limit, $phone, $sex, $platform, $sysPhone, $status, $member,
|
||||
$inviterCode, $userName, $invitationCode, $startTime, $endTime, $qdCode, $sysUserName, $vipType, $delegate
|
||||
)]);
|
||||
}
|
||||
|
||||
// 修改用户状态
|
||||
public function updateUserStatusByUserId()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
if(empty($get['status']) && $get['status'] == null) {
|
||||
$this->error('status 不能为空');
|
||||
}
|
||||
$status = $get['status'];
|
||||
$userId = $get['userId'];
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId], true));
|
||||
// 查询用户是否存在
|
||||
$user = $db->name('tb_user')->where(['user_id' => $userId])->find();
|
||||
if (is_null($user)) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
|
||||
// 根据状态执行不同操作
|
||||
switch ($status) {
|
||||
case 1:
|
||||
// 状态1:设置状态为1,并调用upUserBlack方法(拉黑)
|
||||
\app\admin\model\User::upUserBlack($user, 1, $db);
|
||||
break;
|
||||
case 2:
|
||||
// 状态2:直接更新状态为2
|
||||
$db->name('tb_user')->where('user_id', $userId)
|
||||
->update(['status' => 2]);
|
||||
break;
|
||||
case 0:
|
||||
// 状态0:调用upUserBlack方法(解封)
|
||||
\app\admin\model\User::upUserBlack($user, 0, $db);
|
||||
break;
|
||||
default:
|
||||
// 无效状态
|
||||
$this->error('状态不正确');
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
// 更新用户邀请奖励金额
|
||||
public function inviteAmount()
|
||||
{
|
||||
$userInviteDTO = $this->request->post();
|
||||
// 验证用户ID不能为空
|
||||
if (empty($userInviteDTO['userId'])) {
|
||||
$this->error('用户id不能为空');
|
||||
}
|
||||
|
||||
// 验证邀请奖励金额必须大于0
|
||||
$inviteAmount = $userInviteDTO['inviteAmount'] ?? null;
|
||||
if (is_null($inviteAmount) || bccomp($inviteAmount, 0) <= 0) {
|
||||
$this->error('邀请奖励金额必须大于0');
|
||||
}
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userInviteDTO['userId']], true))->name('tb_user');
|
||||
// 查询用户是否存在
|
||||
$userEntity = $db->where(['user_id' => $userInviteDTO['userId']])->find($userInviteDTO['userId']);
|
||||
if (is_null($userEntity)) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
// 更新用户邀请奖励金额
|
||||
$db->where(['user_id' => $userInviteDTO['userId']])->update(['invite_amount' => $inviteAmount]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
public function updatePwd()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId']) || empty($get['pwd'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
$userId = $get['userId'];
|
||||
$pwd = $get['pwd'];
|
||||
$db = Db::connect(DatabaseRoute::getConnection('sys_user', ['user_id' => $userId]));
|
||||
$user = $db->name('sys_user')->where(['user_id' => $userId])->find();
|
||||
if(!$user) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
$db = Db::connect(DatabaseRoute::getConnection('sys_user', ['user_id' => $userId], true));
|
||||
$user = $db->name('sys_user')->where(['user_id' => $userId])->update(['password' => shiro_simple_hash_hex_salt('sha256', $pwd, $user['salt'])]);
|
||||
if($user) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error();
|
||||
}
|
||||
|
||||
public function deleteUserByUserId()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
if(empty($post['userId'])) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
$userId = $post['userId'];
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId], true));
|
||||
$user = $db->name('tb_user')->where(['user_id' => $userId])->delete();
|
||||
if($user) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error('操作失败');
|
||||
}
|
||||
|
||||
|
||||
public function getuserinfo()
|
||||
{
|
||||
$userId = $this->request->get('userId');
|
||||
if(empty($userId)) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId]));
|
||||
$user = $db->name('tb_user')->where(['user_id' => $userId])->find();
|
||||
if(!$user) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
|
||||
$inviteMoney = \app\admin\model\User::selectInviteMoneyByUserId($userId, $db);
|
||||
if(empty($inviteMoney)) {
|
||||
$inviteMoney = [
|
||||
'user_id' => $userId,
|
||||
'money_sum' => 0.00,
|
||||
'money' => 0.00,
|
||||
'cash_out' => 0.00,
|
||||
];
|
||||
Db::connect(DatabaseRoute::getConnection('invite_money', ['user_id' => $userId], true), true)->name('invite_money')->insert($inviteMoney);
|
||||
}
|
||||
$money = $inviteMoney['money'];
|
||||
|
||||
// 获取当前日期(格式:YYYY-MM-DD HH:mm:ss)
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
// 查询本月充值(复用之前的instantselectSumPay方法)
|
||||
$consume = \app\admin\model\User::instantselectSumPay(date('Y-m'), $userId, $db);
|
||||
|
||||
// 查询本月提现(假设monthIncome方法已实现)
|
||||
$income = \app\admin\model\User::monthIncome(date('Y-m'), $userId, $db);
|
||||
|
||||
// 查询邀请人数(复用之前的countUsersByInviterCode方法)
|
||||
$count = \app\admin\model\User::queryInviterCount($user['invitation_code']);
|
||||
|
||||
// 查询VIP信息
|
||||
$userVip = \app\admin\model\User::selectUserVipByUserId($userId);
|
||||
if ($userVip) {
|
||||
$user['member'] = $userVip['is_vip'];
|
||||
$user['end_time'] = $userVip['end_time'];
|
||||
$user['vip_type'] = $userVip['vip_type'];
|
||||
}
|
||||
|
||||
// 组装结果数据
|
||||
$resultData = [
|
||||
'userEntity' => $user,
|
||||
'money' => $money,
|
||||
'consume' => $consume,
|
||||
'income' => $income,
|
||||
'count' => $count
|
||||
];
|
||||
$this->n_success(['data' => $resultData]);
|
||||
|
||||
}
|
||||
|
||||
public function userListExcel()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$startTime = $get['startTime'] ?? null;
|
||||
$endTime = $get['endTime'] ?? null;
|
||||
$this->n_success(\app\admin\model\User::userListExcel($startTime, $endTime));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取用户详细信息
|
||||
public function selectUserByInvitationCode()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['invitationCode'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
$invitationCode = $get['invitationCode'];
|
||||
$userEntity = TbUser::GetByusername($invitationCode, 'invitation_code');
|
||||
if(empty($userEntity)) {
|
||||
$this->error('用户信息不存在');
|
||||
}
|
||||
$userId = $userEntity['user_id'];
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('invite_money', ['user_id' => $userId]));
|
||||
// 查询用户钱包
|
||||
$inviteMoney = \app\admin\model\User::selectInviteMoneyByUserId($userId, $db);
|
||||
$money = $inviteMoney['money'];
|
||||
// 获取当前时间(格式:Y-m-d H:i:s)
|
||||
$currentDate = date('Y-m-d H:i:s');
|
||||
// 查询本月充值总额
|
||||
$consume = \app\admin\model\User::instantselectSumPay($currentDate, $userId, $db);
|
||||
$income = \app\admin\model\User::monthIncome($currentDate, $userId, $db);
|
||||
//查询邀请人数
|
||||
$count = \app\admin\model\User::queryInviterCount($userEntity['invitation_code']);
|
||||
$userVip = \app\admin\model\User::selectUserVipByUserId($userId);
|
||||
if ($userVip) {
|
||||
$userEntity['member'] = $userVip['is_vip'];
|
||||
$userEntity['end_time'] = $userVip['end_time'];
|
||||
$userEntity['vip_type'] = $userVip['vip_type'];
|
||||
}
|
||||
$data = [
|
||||
'userEntity' => $userEntity,
|
||||
'money' => $money,
|
||||
'consume' => $consume,
|
||||
'income' => $income,
|
||||
'count' => $count
|
||||
];
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
84
app/czg/controller/UserInfoController.php
Normal file
84
app/czg/controller/UserInfoController.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class UserInfoController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$result = DatabaseRoute::paginateAllDb('user_info', function ($query) use ($params) {
|
||||
if (!empty($params['phone'])) {
|
||||
$user = DatabaseRoute::getAllDbData('tb_user', function ($q) use ($params) {
|
||||
return $q->where('phone', $params['phone']);
|
||||
})->find();
|
||||
$userId = $user ? $user['user_id'] : -99999;
|
||||
$query->where('user_id', $userId);
|
||||
}
|
||||
|
||||
if (!empty($name)) {
|
||||
$query->whereLike('cert_name', "%{$name}%");
|
||||
}
|
||||
|
||||
return $query;
|
||||
}, $params['page'], $params['limit'], 'id', 'id');
|
||||
|
||||
// 用户信息补全
|
||||
$userInfoList = $result['list'];
|
||||
$userIds = array_column($userInfoList, 'user_id');
|
||||
|
||||
if (!empty($userIds)) {
|
||||
$userMap = DatabaseRoute::getAllDbData('tb_user', function ($query) use ($params, $userIds) {
|
||||
return $query
|
||||
->whereIn('user_id', $userIds);
|
||||
})->select();
|
||||
|
||||
foreach ($userInfoList as &$item) {
|
||||
$user = $userMap[$item['user_id']] ?? null;
|
||||
$item['name'] = $user['user_name'] ?? null;
|
||||
$item['phone'] = $user['phone'] ?? null;
|
||||
}
|
||||
unset($item);
|
||||
|
||||
$result['list'] = $userInfoList;
|
||||
}
|
||||
|
||||
$this->successWithData($result);
|
||||
}
|
||||
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = input();
|
||||
if (empty($params['userId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
|
||||
$params['update_time'] = getNormalDate();
|
||||
DatabaseRoute::getDb('user_info', $params['userId'], true, true)->update([
|
||||
'cert_name' => $params['certName'] ?? '',
|
||||
'cert_no' => $params['certNo'] ?? '',
|
||||
'account_no' => $params['accountNo'] ?? '',
|
||||
'mobile' => $params['mobile'] ?? '',
|
||||
'bank_name' => $params['bankName'] ?? '',
|
||||
]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
if (empty($params['userId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
DatabaseRoute::getDb('user_info', $params['userId'], true, true)->delete();
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
84
app/czg/controller/UserPrizeExchangeController.php
Normal file
84
app/czg/controller/UserPrizeExchangeController.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class UserPrizeExchangeController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
|
||||
public function page()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$this->successWithData(DatabaseRoute::paginateDb('user_prize_exchange', function ($query) use ($params) {
|
||||
if (!empty($params['foreignId'])) {
|
||||
$query->where('foreign_id', $params['foreignId']);
|
||||
}
|
||||
if (!empty($params['foreignType'])) {
|
||||
$query->where('foreign_type', $params['foreignType']);
|
||||
}
|
||||
if (!empty($params['userId'])) {
|
||||
$query->where('user_id', $params['userId']);
|
||||
}
|
||||
if (!empty($params['userName'])) {
|
||||
$query->where('user_name', 'like', "%". $params['userName']."%");
|
||||
}
|
||||
if (!empty($params['prizeName'])) {
|
||||
$query->where('prize_name', 'like', "%" . $params['prizeName'] . "%");
|
||||
}
|
||||
if (!empty($params['status'])) {
|
||||
$query->where('status', $params['status']);
|
||||
}
|
||||
if (!empty($params['phone'])) {
|
||||
$query->where('phone', 'like', "%". $params['phone'] ."%");
|
||||
}
|
||||
if (!empty($params['remark'])) {
|
||||
$query->where('remark', 'like', "%" . $params['remark'] . "%");
|
||||
}
|
||||
|
||||
if (!empty($params['beginDate'])) {
|
||||
$query->where('create_time', '>=', $params['beginDate'] . ' 00:00:00');
|
||||
}
|
||||
if (!empty($params['endDate'])) {
|
||||
$query->where('create_time', '<=', $params['endDate'] . ' 23:59:59');
|
||||
}
|
||||
$query->order('id', false);
|
||||
}));
|
||||
}
|
||||
|
||||
public function deliver()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
if (empty($params['id'])) {
|
||||
$this->error('兑奖id不能为空');
|
||||
}
|
||||
|
||||
$info = Db::name('user_prize_exchange')->where([
|
||||
'id' => $params['id']
|
||||
])->find();
|
||||
if (!$info) {
|
||||
$this->error('兑奖订单不存在');
|
||||
}
|
||||
|
||||
Db::name('user_prize_exchange')->where([
|
||||
'id' => $params['id']
|
||||
])->update([
|
||||
'status' => 1,
|
||||
'address' => $params['address'] ?? '',
|
||||
'remark' => $params['remark'] ?? '',
|
||||
'update_time' => getNormalDate()
|
||||
]);
|
||||
|
||||
$this->success();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
128
app/czg/controller/VipDetailsController.php
Normal file
128
app/czg/controller/VipDetailsController.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SysCaptcha;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class VipDetailsController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['selectVipDetailsList'];
|
||||
public function sendVip()
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$userId = $data['userId'] ?? null;
|
||||
$num = $data['num'] ?? null;
|
||||
$userVip = \app\admin\model\User::selectUserVipByUserId($userId);
|
||||
|
||||
// 获取当前时间戳
|
||||
$currentTime = time();
|
||||
|
||||
// 如果用户已有 VIP 记录
|
||||
if ($userVip) {
|
||||
// 如果当前是 VIP 会员(假设 is_vip=2 表示 VIP)
|
||||
if ($userVip['is_vip'] == 2) {
|
||||
// 从现有结束时间开始叠加(转换为时间戳)
|
||||
$endTime = strtotime($userVip['end_time']);
|
||||
} else {
|
||||
// 非 VIP 从当前时间开始
|
||||
$endTime = $currentTime;
|
||||
}
|
||||
} else {
|
||||
// 新建 VIP 记录
|
||||
$userVip = [
|
||||
'user_id' => $userId,
|
||||
'create_time' => date('Y-m-d H:i:s', $currentTime)
|
||||
];
|
||||
$endTime = $currentTime;
|
||||
}
|
||||
|
||||
// 设置 VIP 类型和状态
|
||||
$userVip['vip_type'] = 1;
|
||||
$userVip['is_vip'] = 2;
|
||||
|
||||
// 计算新的结束时间(增加指定天数,每天 86400 秒)
|
||||
$endTime += $num * 86400;
|
||||
$userVip['end_time'] = date('Y-m-d H:i:s', $endTime);
|
||||
$db = Db::connect(get_master_connect_name())->name('user_vip');
|
||||
// 保存或更新记录
|
||||
if (isset($userVip['vip_id'])) {
|
||||
// 更新记录
|
||||
$db->where('vip_id', $userVip['vip_id'])
|
||||
->update($userVip);
|
||||
} else {
|
||||
// 插入新记录
|
||||
$db->insert($userVip);
|
||||
}
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function selectVipDetailsList()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$page = $get['page'] ?? null;
|
||||
$limit = $get['limit'] ?? null;
|
||||
$db = Db::connect(get_slave_connect_name())->name('vip_details');
|
||||
$count = $db->count();
|
||||
$data = $db->limit(page($page, $limit), $limit)->select()->toArray();
|
||||
$this->n_success(['data' => [
|
||||
'currPage' => $get['page'],
|
||||
'pageSize' => $get['limit'],
|
||||
'list' => array_map(function ($item) {
|
||||
$item['id'] = (string)$item['id'];
|
||||
return $item;
|
||||
}, $data),
|
||||
'totalCount' => $count,
|
||||
'totalPage' => ceil($count / $get['limit']),
|
||||
]]);
|
||||
}
|
||||
|
||||
|
||||
public function insertVipDetails()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
$data['vip_name_type'] = $post['vipNameType'] ?? null;
|
||||
$data['money'] = $post['money'] ?? null;
|
||||
$data['pay_diamond'] = $post['payDiamond'] ?? null;
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
$res = $db->name('vip_details')->insert($data);
|
||||
if($res) {
|
||||
$this->success('成功');
|
||||
}else {
|
||||
$this->error('失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function updateVipDetails()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
$id = $post['id'] ?? null;
|
||||
$data['vip_name_type'] = $post['vipNameType'] ?? null;
|
||||
$data['money'] = $post['money'] ?? null;
|
||||
$data['pay_diamond'] = $post['payDiamond'] ?? null;
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
$res = $db->name('vip_details')->where(['id' => $id])->update($data);
|
||||
$this->success('成功');
|
||||
}
|
||||
|
||||
public function deleteVipDetails()
|
||||
{
|
||||
$post = $this->request->param();
|
||||
if(empty($post['id'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
$id = $post['id'];
|
||||
$db = Db::connect(get_master_connect_name());
|
||||
$res = $db->name('vip_details')->where(['id' => $id])->delete();
|
||||
$this->success('成功');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
992
app/czg/crud/controller/CrudController.php
Normal file
992
app/czg/crud/controller/CrudController.php
Normal file
@@ -0,0 +1,992 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\crud\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\Exception;
|
||||
use ba\Filesystem;
|
||||
use think\facade\Db;
|
||||
use ba\TableManager;
|
||||
use app\admin\model\CrudLog;
|
||||
use app\common\library\Menu;
|
||||
use app\admin\model\AdminLog;
|
||||
use app\admin\model\AdminRule;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\library\crud\Helper;
|
||||
|
||||
class CrudController extends Backend
|
||||
{
|
||||
/**
|
||||
* 模型文件数据
|
||||
* @var array
|
||||
*/
|
||||
protected array $modelData = [];
|
||||
|
||||
/**
|
||||
* 控制器文件数据
|
||||
* @var array
|
||||
*/
|
||||
protected array $controllerData = [];
|
||||
|
||||
/**
|
||||
* index.vue文件数据
|
||||
* @var array
|
||||
*/
|
||||
protected array $indexVueData = [];
|
||||
|
||||
/**
|
||||
* form.vue文件数据
|
||||
* @var array
|
||||
*/
|
||||
protected array $formVueData = [];
|
||||
|
||||
/**
|
||||
* 语言翻译前缀
|
||||
* @var string
|
||||
*/
|
||||
protected string $webTranslate = '';
|
||||
|
||||
/**
|
||||
* 语言包数据
|
||||
* @var array
|
||||
*/
|
||||
protected array $langTsData = [];
|
||||
|
||||
/**
|
||||
* 当designType为以下值时:
|
||||
* 1. 出入库字符串到数组转换
|
||||
* 2. 默认值转数组
|
||||
* @var array
|
||||
*/
|
||||
protected array $dtStringToArray = ['checkbox', 'selects', 'remoteSelects', 'city', 'images', 'files'];
|
||||
|
||||
protected array $noNeedPermission = ['logStart', 'getFileData', 'parseFieldData', 'generateCheck', 'uploadCompleted'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始生成
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function generate(): void
|
||||
{
|
||||
$type = $this->request->post('type', '');
|
||||
$table = $this->request->post('table', []);
|
||||
$fields = $this->request->post('fields', [], 'clean_xss,htmlspecialchars_decode_improve');
|
||||
|
||||
if (!$table || !$fields || !isset($table['name']) || !$table['name']) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
try {
|
||||
// 记录日志
|
||||
$crudLogId = Helper::recordCrudStatus([
|
||||
'table' => $table,
|
||||
'fields' => $fields,
|
||||
'status' => 'start',
|
||||
]);
|
||||
|
||||
// 表名称
|
||||
$tableName = TableManager::tableName($table['name'], false, $table['databaseConnection']);
|
||||
|
||||
if ($type == 'create' || $table['rebuild'] == 'Yes') {
|
||||
// 数据表存在则删除
|
||||
TableManager::phinxTable($tableName, [], true, $table['databaseConnection'])->drop()->save();
|
||||
}
|
||||
|
||||
// 处理表设计
|
||||
[$tablePk] = Helper::handleTableDesign($table, $fields);
|
||||
|
||||
// 表注释
|
||||
$tableComment = mb_substr($table['comment'], -1) == '表' ? mb_substr($table['comment'], 0, -1) . '管理' : $table['comment'];
|
||||
|
||||
// 生成文件信息解析
|
||||
$modelFile = Helper::parseNameData($table['isCommonModel'] ? 'common' : 'admin', $tableName, 'model', $table['modelFile']);
|
||||
$validateFile = Helper::parseNameData($table['isCommonModel'] ? 'common' : 'admin', $tableName, 'validate', $table['validateFile']);
|
||||
$controllerFile = Helper::parseNameData('admin', $tableName, 'controller', $table['controllerFile']);
|
||||
$webViewsDir = Helper::parseWebDirNameData($tableName, 'views', $table['webViewsDir']);
|
||||
$webLangDir = Helper::parseWebDirNameData($tableName, 'lang', $table['webViewsDir']);
|
||||
|
||||
// 语言翻译前缀
|
||||
$this->webTranslate = implode('.', $webLangDir['lang']) . '.';
|
||||
|
||||
// 快速搜索字段
|
||||
if (!in_array($tablePk, $table['quickSearchField'])) {
|
||||
$table['quickSearchField'][] = $tablePk;
|
||||
}
|
||||
$quickSearchFieldZhCnTitle = [];
|
||||
|
||||
// 模型数据
|
||||
$this->modelData['append'] = [];
|
||||
$this->modelData['methods'] = [];
|
||||
$this->modelData['fieldType'] = [];
|
||||
$this->modelData['createTime'] = '';
|
||||
$this->modelData['updateTime'] = '';
|
||||
$this->modelData['beforeInsertMixins'] = [];
|
||||
$this->modelData['beforeInsert'] = '';
|
||||
$this->modelData['afterInsert'] = '';
|
||||
$this->modelData['connection'] = $table['databaseConnection'];
|
||||
$this->modelData['name'] = $tableName;
|
||||
$this->modelData['className'] = $modelFile['lastName'];
|
||||
$this->modelData['namespace'] = $modelFile['namespace'];
|
||||
$this->modelData['relationMethodList'] = [];
|
||||
|
||||
// 控制器数据
|
||||
$this->controllerData['use'] = [];
|
||||
$this->controllerData['attr'] = [];
|
||||
$this->controllerData['methods'] = [];
|
||||
$this->controllerData['filterRule'] = '';
|
||||
$this->controllerData['className'] = $controllerFile['lastName'];
|
||||
$this->controllerData['namespace'] = $controllerFile['namespace'];
|
||||
$this->controllerData['tableComment'] = $tableComment;
|
||||
$this->controllerData['modelName'] = $modelFile['lastName'];
|
||||
$this->controllerData['modelNamespace'] = $modelFile['namespace'];
|
||||
|
||||
// index.vue数据
|
||||
$this->indexVueData['enableDragSort'] = false;
|
||||
$this->indexVueData['defaultItems'] = [];
|
||||
$this->indexVueData['tableColumn'] = [
|
||||
[
|
||||
'type' => 'selection',
|
||||
'align' => 'center',
|
||||
'operator' => 'false',
|
||||
],
|
||||
];
|
||||
$this->indexVueData['dblClickNotEditColumn'] = ['undefined'];
|
||||
$this->indexVueData['optButtons'] = ['edit', 'delete'];
|
||||
$this->indexVueData['defaultOrder'] = '';
|
||||
|
||||
// form.vue数据
|
||||
$this->formVueData['bigDialog'] = false;
|
||||
$this->formVueData['formFields'] = [];
|
||||
$this->formVueData['formValidatorRules'] = [];
|
||||
$this->formVueData['imports'] = [];
|
||||
|
||||
// 语言包数据
|
||||
$this->langTsData = [
|
||||
'en' => [],
|
||||
'zh-cn' => [],
|
||||
];
|
||||
|
||||
// 简化的字段数据
|
||||
$fieldsMap = [];
|
||||
|
||||
foreach ($fields as $key => $field) {
|
||||
|
||||
$fieldsMap[$field['name']] = $field['designType'];
|
||||
|
||||
// 分析字段
|
||||
Helper::analyseField($field);
|
||||
|
||||
Helper::getDictData($this->langTsData['en'], $field, 'en');
|
||||
Helper::getDictData($this->langTsData['zh-cn'], $field, 'zh-cn');
|
||||
|
||||
// 快速搜索字段
|
||||
if (in_array($field['name'], $table['quickSearchField'])) {
|
||||
$quickSearchFieldZhCnTitle[] = $this->langTsData['zh-cn'][$field['name']] ?? $field['name'];
|
||||
}
|
||||
|
||||
// 不允许双击编辑的字段
|
||||
if ($field['designType'] == 'switch') {
|
||||
$this->indexVueData['dblClickNotEditColumn'][] = $field['name'];
|
||||
}
|
||||
|
||||
// 列字典数据
|
||||
$columnDict = $this->getColumnDict($field);
|
||||
|
||||
// 表单项
|
||||
if (in_array($field['name'], $table['formFields'])) {
|
||||
$this->formVueData['formFields'][] = $this->getFormField($field, $columnDict, $table['databaseConnection']);
|
||||
}
|
||||
|
||||
// 表格列
|
||||
if (in_array($field['name'], $table['columnFields'])) {
|
||||
$this->indexVueData['tableColumn'][] = $this->getTableColumn($field, $columnDict);
|
||||
}
|
||||
|
||||
// 关联表数据解析
|
||||
if (in_array($field['designType'], ['remoteSelect', 'remoteSelects'])) {
|
||||
$this->parseJoinData($field, $table);
|
||||
}
|
||||
|
||||
// 模型方法
|
||||
$this->parseModelMethods($field, $this->modelData);
|
||||
|
||||
// 控制器/模型等文件的一些杂项属性解析
|
||||
$this->parseSundryData($field, $table);
|
||||
|
||||
if (!in_array($field['name'], $table['formFields'])) {
|
||||
$this->controllerData['attr']['preExcludeFields'][] = $field['name'];
|
||||
}
|
||||
}
|
||||
|
||||
// 快速搜索提示
|
||||
$this->langTsData['en']['quick Search Fields'] = implode(',', $table['quickSearchField']);
|
||||
$this->langTsData['zh-cn']['quick Search Fields'] = implode('、', $quickSearchFieldZhCnTitle);
|
||||
$this->controllerData['attr']['quickSearchField'] = $table['quickSearchField'];
|
||||
|
||||
// 开启字段排序
|
||||
$weighKey = array_search('weigh', $fieldsMap);
|
||||
if ($weighKey !== false) {
|
||||
$this->indexVueData['enableDragSort'] = true;
|
||||
$this->modelData['afterInsert'] = Helper::assembleStub('mixins/model/afterInsert', [
|
||||
'field' => $weighKey
|
||||
]);
|
||||
}
|
||||
|
||||
// 表格的操作列
|
||||
$this->indexVueData['tableColumn'][] = [
|
||||
'label' => "t('Operate')",
|
||||
'align' => 'center',
|
||||
'width' => $this->indexVueData['enableDragSort'] ? 140 : 100,
|
||||
'render' => 'buttons',
|
||||
'buttons' => 'optButtons',
|
||||
'operator' => 'false',
|
||||
];
|
||||
if ($this->indexVueData['enableDragSort']) {
|
||||
array_unshift($this->indexVueData['optButtons'], 'weigh-sort');
|
||||
}
|
||||
|
||||
// 写入语言包代码
|
||||
Helper::writeWebLangFile($this->langTsData, $webLangDir);
|
||||
|
||||
// 写入模型代码
|
||||
Helper::writeModelFile($tablePk, $fieldsMap, $this->modelData, $modelFile);
|
||||
|
||||
// 写入控制器代码
|
||||
Helper::writeControllerFile($this->controllerData, $controllerFile);
|
||||
|
||||
// 写入验证器代码
|
||||
$validateContent = Helper::assembleStub('mixins/validate/validate', [
|
||||
'namespace' => $validateFile['namespace'],
|
||||
'className' => $validateFile['lastName'],
|
||||
]);
|
||||
Helper::writeFile($validateFile['parseFile'], $validateContent);
|
||||
|
||||
// 写入index.vue代码
|
||||
$this->indexVueData['tablePk'] = $tablePk;
|
||||
$this->indexVueData['webTranslate'] = $this->webTranslate;
|
||||
Helper::writeIndexFile($this->indexVueData, $webViewsDir, $controllerFile);
|
||||
|
||||
// 写入form.vue代码
|
||||
Helper::writeFormFile($this->formVueData, $webViewsDir, $fields, $this->webTranslate);
|
||||
|
||||
// 生成菜单
|
||||
Helper::createMenu($webViewsDir, $tableComment);
|
||||
|
||||
Helper::recordCrudStatus([
|
||||
'id' => $crudLogId,
|
||||
'status' => 'success',
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
Helper::recordCrudStatus([
|
||||
'id' => $crudLogId ?? 0,
|
||||
'status' => 'error',
|
||||
]);
|
||||
$this->error($e->getMessage());
|
||||
} catch (Throwable $e) {
|
||||
Helper::recordCrudStatus([
|
||||
'id' => $crudLogId ?? 0,
|
||||
'status' => 'error',
|
||||
]);
|
||||
if (env('app_debug', false)) throw $e;
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'crudLog' => CrudLog::find($crudLogId),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从log开始
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function logStart(): void
|
||||
{
|
||||
$id = $this->request->post('id');
|
||||
$type = $this->request->post('type', '');
|
||||
|
||||
if ($type == 'Cloud history') {
|
||||
// 云端 历史记录
|
||||
$client = get_ba_client();
|
||||
$response = $client->request('GET', '/api/v6.Crud/info', [
|
||||
'query' => [
|
||||
'id' => $id,
|
||||
'server' => 1,
|
||||
'ba-user-token' => $this->request->post('token', ''),
|
||||
]
|
||||
]);
|
||||
$body = $response->getBody();
|
||||
$statusCode = $response->getStatusCode();
|
||||
$content = $body->getContents();
|
||||
if ($content == '' || stripos($content, '<title>系统发生错误</title>') !== false || $statusCode != 200) {
|
||||
$this->error(__('Failed to load cloud data'));
|
||||
}
|
||||
$json = json_decode($content, true);
|
||||
if (json_last_error() != JSON_ERROR_NONE) {
|
||||
$this->error(__('Failed to load cloud data'));
|
||||
}
|
||||
if (is_array($json)) {
|
||||
if ($json['code'] != 1) {
|
||||
$this->error($json['msg']);
|
||||
}
|
||||
|
||||
$info = $json['data']['info'];
|
||||
}
|
||||
} else {
|
||||
// 本地记录
|
||||
$info = CrudLog::find($id)->toArray();
|
||||
}
|
||||
|
||||
if (!isset($info) || !$info) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
// 数据表是否有数据
|
||||
$connection = TableManager::getConnection($info['table']['databaseConnection'] ?? '');
|
||||
$tableName = TableManager::tableName($info['table']['name'], false, $connection);
|
||||
$adapter = TableManager::phinxAdapter(true, $connection);
|
||||
if ($adapter->hasTable($tableName)) {
|
||||
$info['table']['empty'] = Db::connect($connection)
|
||||
->name($tableName)
|
||||
->limit(1)
|
||||
->select()
|
||||
->isEmpty();
|
||||
} else {
|
||||
$info['table']['empty'] = true;
|
||||
}
|
||||
|
||||
AdminLog::instance()->setTitle(__('Log start'));
|
||||
|
||||
$this->success('', [
|
||||
'table' => $info['table'],
|
||||
'fields' => $info['fields'],
|
||||
'sync' => $info['sync'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除CRUD记录和生成的文件
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function delete(): void
|
||||
{
|
||||
$id = $this->request->post('id');
|
||||
$info = CrudLog::find($id)->toArray();
|
||||
if (!$info) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
$webLangDir = Helper::parseWebDirNameData($info['table']['name'], 'lang', $info['table']['webViewsDir']);
|
||||
$files = [
|
||||
$webLangDir['en'] . '.ts',
|
||||
$webLangDir['zh-cn'] . '.ts',
|
||||
$info['table']['webViewsDir'] . '/' . 'index.vue',
|
||||
$info['table']['webViewsDir'] . '/' . 'popupForm.vue',
|
||||
$info['table']['controllerFile'],
|
||||
$info['table']['modelFile'],
|
||||
$info['table']['validateFile'],
|
||||
];
|
||||
try {
|
||||
foreach ($files as &$file) {
|
||||
$file = Filesystem::fsFit(root_path() . $file);
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
Filesystem::delEmptyDir(dirname($file));
|
||||
}
|
||||
|
||||
// 删除菜单
|
||||
Menu::delete(Helper::getMenuName($webLangDir), true);
|
||||
|
||||
Helper::recordCrudStatus([
|
||||
'id' => $id,
|
||||
'status' => 'delete',
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success(__('Deleted successfully'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件路径数据
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getFileData(): void
|
||||
{
|
||||
$table = $this->request->get('table');
|
||||
$commonModel = $this->request->get('commonModel/b');
|
||||
|
||||
if (!$table) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
try {
|
||||
$modelFile = Helper::parseNameData($commonModel ? 'common' : 'admin', $table, 'model');
|
||||
$validateFile = Helper::parseNameData($commonModel ? 'common' : 'admin', $table, 'validate');
|
||||
$controllerFile = Helper::parseNameData('admin', $table, 'controller');
|
||||
$webViewsDir = Helper::parseWebDirNameData($table, 'views');
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
// 模型和控制器文件和文件列表
|
||||
$adminModelFiles = Filesystem::getDirFiles(root_path() . 'app' . DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR . 'model' . DIRECTORY_SEPARATOR);
|
||||
$commonModelFiles = Filesystem::getDirFiles(root_path() . 'app' . DIRECTORY_SEPARATOR . 'common' . DIRECTORY_SEPARATOR . 'model' . DIRECTORY_SEPARATOR);
|
||||
$adminControllerFiles = get_controller_list();
|
||||
|
||||
$modelFileList = [];
|
||||
$controllerFiles = [];
|
||||
foreach ($adminModelFiles as $item) {
|
||||
$item = Filesystem::fsFit('app/admin/model/' . $item);
|
||||
$modelFileList[$item] = $item;
|
||||
}
|
||||
foreach ($commonModelFiles as $item) {
|
||||
$item = Filesystem::fsFit('app/common/model/' . $item);
|
||||
$modelFileList[$item] = $item;
|
||||
}
|
||||
|
||||
$outExcludeController = [
|
||||
'Addon.php',
|
||||
'Ajax.php',
|
||||
'Dashboard.php',
|
||||
'Index.php',
|
||||
'Module.php',
|
||||
'Terminal.php',
|
||||
'routine/AdminInfo.php',
|
||||
'routine/Config.php',
|
||||
];
|
||||
foreach ($adminControllerFiles as $item) {
|
||||
if (in_array($item, $outExcludeController)) {
|
||||
continue;
|
||||
}
|
||||
$item = Filesystem::fsFit('app/admin/controller/' . $item);
|
||||
$controllerFiles[$item] = $item;
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'modelFile' => $modelFile['rootFileName'],
|
||||
'controllerFile' => $controllerFile['rootFileName'],
|
||||
'validateFile' => $validateFile['rootFileName'],
|
||||
'controllerFileList' => $controllerFiles,
|
||||
'modelFileList' => $modelFileList,
|
||||
'webViewsDir' => $webViewsDir['views'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否已有CRUD记录
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function checkCrudLog(): void
|
||||
{
|
||||
$table = $this->request->get('table');
|
||||
$connection = $this->request->get('connection');
|
||||
$connection = $connection ?: config('database.default');
|
||||
|
||||
$crudLog = Db::name('crud_log')
|
||||
->where('table_name', $table)
|
||||
->where('connection', $connection)
|
||||
->order('create_time desc')
|
||||
->find();
|
||||
$this->success('', [
|
||||
'id' => ($crudLog && $crudLog['status'] == 'success') ? $crudLog['id'] : 0,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析字段数据
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function parseFieldData(): void
|
||||
{
|
||||
AdminLog::instance()->setTitle(__('Parse field data'));
|
||||
$type = $this->request->post('type');
|
||||
$table = $this->request->post('table');
|
||||
$connection = $this->request->post('connection');
|
||||
$connection = TableManager::getConnection($connection);
|
||||
|
||||
$table = TableManager::tableName($table, true, $connection);
|
||||
$connectionConfig = TableManager::getConnectionConfig($connection);
|
||||
|
||||
if ($type == 'db') {
|
||||
$sql = 'SELECT * FROM `information_schema`.`tables` '
|
||||
. 'WHERE TABLE_SCHEMA = ? AND table_name = ?';
|
||||
$tableInfo = Db::connect($connection)->query($sql, [$connectionConfig['database'], $table]);
|
||||
if (!$tableInfo) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
// 数据表是否有数据
|
||||
$adapter = TableManager::phinxAdapter(false, $connection);
|
||||
if ($adapter->hasTable($table)) {
|
||||
$empty = Db::connect($connection)
|
||||
->table($table)
|
||||
->limit(1)
|
||||
->select()
|
||||
->isEmpty();
|
||||
} else {
|
||||
$empty = true;
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'columns' => Helper::parseTableColumns($table, false, $connection),
|
||||
'comment' => $tableInfo[0]['TABLE_COMMENT'] ?? '',
|
||||
'empty' => $empty,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成前检查
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function generateCheck(): void
|
||||
{
|
||||
$table = $this->request->post('table');
|
||||
$connection = $this->request->post('connection');
|
||||
$webViewsDir = $this->request->post('webViewsDir', '');
|
||||
$controllerFile = $this->request->post('controllerFile', '');
|
||||
|
||||
if (!$table) {
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
AdminLog::instance()->setTitle(__('Generate check'));
|
||||
|
||||
try {
|
||||
$webViewsDir = Helper::parseWebDirNameData($table, 'views', $webViewsDir);
|
||||
$controllerFile = Helper::parseNameData('admin', $table, 'controller', $controllerFile)['rootFileName'];
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
// 数据表是否存在
|
||||
$tableList = TableManager::getTableList($connection);
|
||||
$tableExist = array_key_exists(TableManager::tableName($table, true, $connection), $tableList);
|
||||
|
||||
// 控制器是否存在
|
||||
$controllerExist = file_exists(root_path() . $controllerFile);
|
||||
|
||||
// 菜单规则是否存在
|
||||
$menuName = Helper::getMenuName($webViewsDir);
|
||||
$menuExist = AdminRule::where('name', $menuName)->value('id');
|
||||
|
||||
if ($controllerExist || $tableExist || $menuExist) {
|
||||
$this->error('', [
|
||||
'menu' => $menuExist,
|
||||
'table' => $tableExist,
|
||||
'controller' => $controllerExist,
|
||||
], -1);
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* CRUD 设计记录上传成功标记
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function uploadCompleted(): void
|
||||
{
|
||||
$syncIds = $this->request->post('syncIds/a', []);
|
||||
$cancelSync = $this->request->post('cancelSync/b', false);
|
||||
$crudLogModel = new CrudLog();
|
||||
|
||||
if ($cancelSync) {
|
||||
$logData = $crudLogModel->where('id', 'in', array_keys($syncIds))->select();
|
||||
foreach ($logData as $logDatum) {
|
||||
if ($logDatum->sync == $syncIds[$logDatum->id]) {
|
||||
$logDatum->sync = 0;
|
||||
$logDatum->save();
|
||||
}
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
$saveData = [];
|
||||
foreach ($syncIds as $key => $syncId) {
|
||||
$saveData[] = [
|
||||
'id' => $key,
|
||||
'sync' => $syncId,
|
||||
];
|
||||
}
|
||||
$crudLogModel->saveAll($saveData);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关联表数据解析
|
||||
* @param $field
|
||||
* @param $table
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function parseJoinData($field, $table): void
|
||||
{
|
||||
$dictEn = [];
|
||||
$dictZhCn = [];
|
||||
|
||||
if ($field['form']['relation-fields'] && $field['form']['remote-table']) {
|
||||
$columns = Helper::parseTableColumns($field['form']['remote-table'], true, $table['databaseConnection']);
|
||||
$relationFields = explode(',', $field['form']['relation-fields']);
|
||||
$tableName = TableManager::tableName($field['form']['remote-table'], false, $table['databaseConnection']);
|
||||
$rnPattern = '/(.*)(_ids|_id)$/';
|
||||
if (preg_match($rnPattern, $field['name'])) {
|
||||
$relationName = parse_name(preg_replace($rnPattern, '$1', $field['name']), 1, false);
|
||||
} else {
|
||||
$relationName = parse_name($field['name'] . '_table', 1, false);
|
||||
}
|
||||
|
||||
// 建立关联模型代码文件
|
||||
if (!$field['form']['remote-model'] || !file_exists(root_path() . $field['form']['remote-model'])) {
|
||||
$joinModelFile = Helper::parseNameData('admin', $tableName, 'model', $field['form']['remote-model']);
|
||||
if (!file_exists(root_path() . $joinModelFile['rootFileName'])) {
|
||||
$joinModelData['append'] = [];
|
||||
$joinModelData['methods'] = [];
|
||||
$joinModelData['fieldType'] = [];
|
||||
$joinModelData['createTime'] = '';
|
||||
$joinModelData['updateTime'] = '';
|
||||
$joinModelData['beforeInsertMixins'] = [];
|
||||
$joinModelData['beforeInsert'] = '';
|
||||
$joinModelData['afterInsert'] = '';
|
||||
$joinModelData['connection'] = $table['databaseConnection'];
|
||||
$joinModelData['name'] = $tableName;
|
||||
$joinModelData['className'] = $joinModelFile['lastName'];
|
||||
$joinModelData['namespace'] = $joinModelFile['namespace'];
|
||||
$joinTablePk = 'id';
|
||||
$joinFieldsMap = [];
|
||||
foreach ($columns as $column) {
|
||||
$joinFieldsMap[$column['name']] = $column['designType'];
|
||||
$this->parseModelMethods($column, $joinModelData);
|
||||
if ($column['primaryKey']) $joinTablePk = $column['name'];
|
||||
}
|
||||
$weighKey = array_search('weigh', $joinFieldsMap);
|
||||
if ($weighKey !== false) {
|
||||
$joinModelData['afterInsert'] = Helper::assembleStub('mixins/model/afterInsert', [
|
||||
'field' => $joinFieldsMap[$weighKey]
|
||||
]);
|
||||
}
|
||||
Helper::writeModelFile($joinTablePk, $joinFieldsMap, $joinModelData, $joinModelFile);
|
||||
}
|
||||
$field['form']['remote-model'] = $joinModelFile['rootFileName'];
|
||||
}
|
||||
|
||||
if ($field['designType'] == 'remoteSelect') {
|
||||
// 关联预载入方法
|
||||
$this->controllerData['attr']['withJoinTable'][$relationName] = $relationName;
|
||||
|
||||
// 模型方法代码
|
||||
$relationData = [
|
||||
'relationMethod' => $relationName,
|
||||
'relationMode' => 'belongsTo',
|
||||
'relationPrimaryKey' => $field['form']['remote-pk'] ?? 'id',
|
||||
'relationForeignKey' => $field['name'],
|
||||
'relationClassName' => str_replace(['.php', '/'], ['', '\\'], '\\' . $field['form']['remote-model']) . "::class",
|
||||
];
|
||||
$this->modelData['relationMethodList'][$relationName] = Helper::assembleStub('mixins/model/belongsTo', $relationData);
|
||||
|
||||
// 查询时显示的字段
|
||||
if ($relationFields) {
|
||||
$this->controllerData['relationVisibleFieldList'][$relationData['relationMethod']] = $relationFields;
|
||||
}
|
||||
} elseif ($field['designType'] == 'remoteSelects') {
|
||||
$this->modelData['append'][] = $relationName;
|
||||
$this->modelData['methods'][] = Helper::assembleStub('mixins/model/getters/remoteSelectLabels', [
|
||||
'field' => parse_name($relationName, 1),
|
||||
'className' => str_replace(['.php', '/'], ['', '\\'], '\\' . $field['form']['remote-model']),
|
||||
'primaryKey' => $field['form']['remote-pk'] ?? 'id',
|
||||
'foreignKey' => $field['name'],
|
||||
'labelFieldName' => $field['form']['remote-field'] ?? 'name',
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($relationFields as $relationField) {
|
||||
if (!array_key_exists($relationField, $columns)) continue;
|
||||
$relationFieldPrefix = $relationName . '.';
|
||||
$relationFieldLangPrefix = strtolower($relationName) . '__';
|
||||
Helper::getDictData($dictEn, $columns[$relationField], 'en', $relationFieldLangPrefix);
|
||||
Helper::getDictData($dictZhCn, $columns[$relationField], 'zh-cn', $relationFieldLangPrefix);
|
||||
|
||||
// 不允许双击编辑的字段
|
||||
if ($columns[$relationField]['designType'] == 'switch') {
|
||||
$this->indexVueData['dblClickNotEditColumn'][] = $field['name'];
|
||||
}
|
||||
|
||||
// 列字典数据
|
||||
$columnDict = $this->getColumnDict($columns[$relationField], $relationFieldLangPrefix);
|
||||
|
||||
// 表格列
|
||||
$columns[$relationField]['designType'] = $field['designType'];
|
||||
$columns[$relationField]['table']['render'] = 'tags';
|
||||
if ($field['designType'] == 'remoteSelects') {
|
||||
$columns[$relationField]['table']['operator'] = 'false';
|
||||
$this->indexVueData['tableColumn'][] = $this->getTableColumn($columns[$relationField], $columnDict, $relationFieldPrefix, $relationFieldLangPrefix);
|
||||
|
||||
// 额外生成一个公共搜索,渲染为远程下拉的列
|
||||
unset($columns[$relationField]['table']['render']);
|
||||
$columns[$relationField]['table']['label'] = "t('" . $this->webTranslate . $relationFieldLangPrefix . $columns[$relationField]['name'] . "')";
|
||||
$columns[$relationField]['name'] = $field['name'];
|
||||
$columns[$relationField]['table']['show'] = 'false';
|
||||
$columns[$relationField]['table']['operator'] = 'FIND_IN_SET';
|
||||
$columns[$relationField]['table']['comSearchRender'] = 'remoteSelect';
|
||||
|
||||
$columns[$relationField]['table']['remote'] = [
|
||||
'pk' => $this->getRemoteSelectPk($field),
|
||||
'field' => $field['form']['remote-field'] ?? 'name',
|
||||
'remoteUrl' => $this->getRemoteSelectUrl($field),
|
||||
'multiple' => 'true',
|
||||
];
|
||||
$this->indexVueData['tableColumn'][] = $this->getTableColumn($columns[$relationField], $columnDict, '', $relationFieldLangPrefix);
|
||||
} else {
|
||||
$columns[$relationField]['table']['operator'] = 'LIKE';
|
||||
$this->indexVueData['tableColumn'][] = $this->getTableColumn($columns[$relationField], $columnDict, $relationFieldPrefix, $relationFieldLangPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->langTsData['en'] = array_merge($this->langTsData['en'], $dictEn);
|
||||
$this->langTsData['zh-cn'] = array_merge($this->langTsData['zh-cn'], $dictZhCn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析模型方法(设置器、获取器等)
|
||||
*/
|
||||
private function parseModelMethods($field, &$modelData): void
|
||||
{
|
||||
// fieldType
|
||||
if ($field['designType'] == 'array') {
|
||||
$modelData['fieldType'][$field['name']] = 'json';
|
||||
} elseif (!in_array($field['name'], ['create_time', 'update_time', 'updatetime', 'createtime']) && $field['designType'] == 'datetime' && (in_array($field['type'], ['int', 'bigint']))) {
|
||||
$modelData['fieldType'][$field['name']] = 'timestamp:Y-m-d H:i:s';
|
||||
}
|
||||
|
||||
// beforeInsertMixins
|
||||
if ($field['designType'] == 'spk') {
|
||||
$modelData['beforeInsertMixins']['snowflake'] = Helper::assembleStub('mixins/model/mixins/beforeInsertWithSnowflake', []);
|
||||
}
|
||||
|
||||
// methods
|
||||
$fieldName = parse_name($field['name'], 1);
|
||||
if (in_array($field['designType'], $this->dtStringToArray)) {
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/getters/stringToArray', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/setters/arrayToString', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
} elseif ($field['designType'] == 'array') {
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/getters/jsonDecode', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
} elseif ($field['designType'] == 'time') {
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/setters/time', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
} elseif ($field['designType'] == 'editor') {
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/getters/htmlDecode', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
} elseif ($field['designType'] == 'spk') {
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/getters/string', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
} elseif (in_array($field['type'], ['float', 'decimal', 'double'])) {
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/getters/float', [
|
||||
'field' => $fieldName
|
||||
]);
|
||||
}
|
||||
|
||||
if ($field['designType'] == 'city') {
|
||||
$modelData['append'][] = $field['name'] . '_text';
|
||||
$modelData['methods'][] = Helper::assembleStub('mixins/model/getters/cityNames', [
|
||||
'field' => $fieldName . 'Text',
|
||||
'originalFieldName' => $field['name'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制器/模型等文件的一些杂项属性解析
|
||||
*/
|
||||
private function parseSundryData($field, $table): void
|
||||
{
|
||||
if ($field['designType'] == 'editor') {
|
||||
$this->formVueData['bigDialog'] = true; // 加宽 dialog
|
||||
$this->controllerData['filterRule'] = "\n" . Helper::tab(2) . '$this->request->filter(\'clean_xss\');'; // 修改变量过滤规则
|
||||
}
|
||||
|
||||
// 默认排序字段
|
||||
if ($table['defaultSortField'] && $table['defaultSortType']) {
|
||||
$defaultSortField = "{$table['defaultSortField']},{$table['defaultSortType']}";
|
||||
if ($defaultSortField == 'id,desc') {
|
||||
$this->controllerData['attr']['defaultSortField'] = '';
|
||||
} else {
|
||||
$this->controllerData['attr']['defaultSortField'] = $defaultSortField;
|
||||
$this->indexVueData['defaultOrder'] = Helper::buildDefaultOrder($table['defaultSortField'], $table['defaultSortType']);
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义了权重字段名称
|
||||
if ($field['originalDesignType'] == 'weigh' && $field['name'] != 'weigh') {
|
||||
$this->controllerData['attr']['weighField'] = $field['name'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装前台表单的数据
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function getFormField($field, $columnDict, ?string $dbConnection = null): array
|
||||
{
|
||||
// 表单项属性
|
||||
$formField = [
|
||||
':label' => 't(\'' . $this->webTranslate . $field['name'] . '\')',
|
||||
'type' => $field['designType'],
|
||||
'v-model' => 'baTable.form.items!.' . $field['name'],
|
||||
'prop' => $field['name'],
|
||||
];
|
||||
|
||||
// 不同输入框的属性处理
|
||||
if ($columnDict || in_array($field['designType'], ['radio', 'checkbox', 'select', 'selects'])) {
|
||||
$formField[':input-attr']['content'] = $columnDict;
|
||||
} elseif ($field['designType'] == 'textarea') {
|
||||
$formField[':input-attr']['rows'] = (int)($field['form']['rows'] ?? 3);
|
||||
$formField['@keyup.enter.stop'] = '';
|
||||
$formField['@keyup.ctrl.enter'] = 'baTable.onSubmit(formRef)';
|
||||
} elseif ($field['designType'] == 'remoteSelect' || $field['designType'] == 'remoteSelects') {
|
||||
$formField[':input-attr']['pk'] = $this->getRemoteSelectPk($field);
|
||||
$formField[':input-attr']['field'] = $field['form']['remote-field'] ?? 'name';
|
||||
$formField[':input-attr']['remoteUrl'] = $this->getRemoteSelectUrl($field);
|
||||
} elseif ($field['designType'] == 'number') {
|
||||
$formField[':input-attr']['step'] = (int)($field['form']['step'] ?? 1);
|
||||
} elseif ($field['designType'] == 'icon') {
|
||||
$formField[':input-attr']['placement'] = 'top';
|
||||
} elseif ($field['designType'] == 'editor') {
|
||||
$formField['@keyup.enter.stop'] = '';
|
||||
$formField['@keyup.ctrl.enter'] = 'baTable.onSubmit(formRef)';
|
||||
}
|
||||
|
||||
// placeholder
|
||||
if (!in_array($field['designType'], ['image', 'images', 'file', 'files', 'switch'])) {
|
||||
if (in_array($field['designType'], ['radio', 'checkbox', 'datetime', 'year', 'date', 'time', 'select', 'selects', 'remoteSelect', 'remoteSelects', 'city', 'icon'])) {
|
||||
$formField[':placeholder'] = "t('Please select field', { field: t('" . $this->webTranslate . $field['name'] . "') })";
|
||||
} else {
|
||||
$formField[':placeholder'] = "t('Please input field', { field: t('" . $this->webTranslate . $field['name'] . "') })";
|
||||
}
|
||||
}
|
||||
|
||||
// 默认值
|
||||
if ($field['defaultType'] == 'INPUT') {
|
||||
$this->indexVueData['defaultItems'][$field['name']] = $field['default'];
|
||||
}
|
||||
|
||||
// 部分生成类型的默认值需要额外处理
|
||||
if ($field['designType'] == 'editor') {
|
||||
$this->indexVueData['defaultItems'][$field['name']] = ($field['defaultType'] == 'INPUT' && $field['default']) ? $field['default'] : '';
|
||||
} elseif ($field['designType'] == 'array') {
|
||||
$this->indexVueData['defaultItems'][$field['name']] = "[]";
|
||||
} elseif ($field['defaultType'] == 'INPUT' && in_array($field['designType'], $this->dtStringToArray) && str_contains($field['default'], ',')) {
|
||||
$this->indexVueData['defaultItems'][$field['name']] = Helper::buildSimpleArray(explode(',', $field['default']));
|
||||
} elseif ($field['defaultType'] == 'INPUT' && in_array($field['designType'], ['number', 'float'])) {
|
||||
$this->indexVueData['defaultItems'][$field['name']] = (float)$field['default'];
|
||||
}
|
||||
|
||||
// 无意义的默认值
|
||||
if (isset($field['default']) && in_array($field['designType'], ['switch', 'number', 'float', 'remoteSelect']) && $field['default'] == 0) {
|
||||
unset($this->indexVueData['defaultItems'][$field['name']]);
|
||||
}
|
||||
|
||||
return $formField;
|
||||
}
|
||||
|
||||
private function getRemoteSelectPk($field): string
|
||||
{
|
||||
$pk = $field['form']['remote-pk'] ?? 'id';
|
||||
if (!str_contains($pk, '.')) {
|
||||
if ($field['form']['remote-source-config-type'] == 'crud' && $field['form']['remote-model']) {
|
||||
$alias = parse_name(basename(str_replace('\\', '/', $field['form']['remote-model']), '.php'));
|
||||
} else {
|
||||
$alias = $field['form']['remote-primary-table-alias'] ?? '';
|
||||
}
|
||||
}
|
||||
return !empty($alias) ? "$alias.$pk" : $pk;
|
||||
}
|
||||
|
||||
private function getRemoteSelectUrl($field): string
|
||||
{
|
||||
if ($field['form']['remote-source-config-type'] == 'crud' && $field['form']['remote-controller']) {
|
||||
$pathArr = [];
|
||||
$controller = explode(DIRECTORY_SEPARATOR, $field['form']['remote-controller']);
|
||||
$controller = str_replace('.php', '', $controller);
|
||||
$redundantDir = [
|
||||
'app' => 0,
|
||||
'admin' => 1,
|
||||
'controller' => 2,
|
||||
];
|
||||
foreach ($controller as $key => $item) {
|
||||
if (!array_key_exists($item, $redundantDir) || $key !== $redundantDir[$item]) {
|
||||
$pathArr[] = $item;
|
||||
}
|
||||
}
|
||||
$url = count($pathArr) > 1 ? implode('.', $pathArr) : $pathArr[0];
|
||||
return '/admin/' . $url . '/index';
|
||||
}
|
||||
return $field['form']['remote-url'];
|
||||
}
|
||||
|
||||
private function getTableColumn($field, $columnDict, $fieldNamePrefix = '', $translationPrefix = ''): array
|
||||
{
|
||||
$column = [
|
||||
'label' => "t('" . $this->webTranslate . $translationPrefix . $field['name'] . "')",
|
||||
'prop' => $fieldNamePrefix . $field['name'] . ($field['designType'] == 'city' ? '_text' : ''),
|
||||
'align' => 'center',
|
||||
];
|
||||
|
||||
// 模糊搜索增加一个placeholder
|
||||
if (isset($field['table']['operator']) && $field['table']['operator'] == 'LIKE') {
|
||||
$column['operatorPlaceholder'] = "t('Fuzzy query')";
|
||||
}
|
||||
|
||||
// 合并前端预设的字段表格属性
|
||||
if (isset($field['table']) && $field['table']) {
|
||||
$column = array_merge($column, $field['table']);
|
||||
}
|
||||
|
||||
// 需要值替换的渲染类型
|
||||
$columnReplaceValue = ['tag', 'tags', 'switch'];
|
||||
if (!in_array($field['designType'], ['remoteSelect', 'remoteSelects']) && ($columnDict || (isset($field['table']['render']) && in_array($field['table']['render'], $columnReplaceValue)))) {
|
||||
$column['replaceValue'] = $columnDict;
|
||||
}
|
||||
|
||||
if (isset($column['render']) && $column['render'] == 'none') {
|
||||
unset($column['render']);
|
||||
}
|
||||
return $column;
|
||||
}
|
||||
|
||||
private function getColumnDict($column, $translationPrefix = ''): array
|
||||
{
|
||||
$dict = [];
|
||||
// 确保字典中无翻译也可以识别到该值
|
||||
if (in_array($column['type'], ['enum', 'set'])) {
|
||||
$dataType = str_replace(' ', '', $column['dataType']);
|
||||
$columnData = substr($dataType, stripos($dataType, '(') + 1, -1);
|
||||
$columnData = explode(',', str_replace(["'", '"'], '', $columnData));
|
||||
foreach ($columnData as $columnDatum) {
|
||||
$dict[$columnDatum] = $column['name'] . ' ' . $columnDatum;
|
||||
}
|
||||
}
|
||||
$dictData = [];
|
||||
Helper::getDictData($dictData, $column, 'zh-cn', $translationPrefix);
|
||||
if ($dictData) {
|
||||
unset($dictData[$translationPrefix . $column['name']]);
|
||||
foreach ($dictData as $key => $item) {
|
||||
$keyName = str_replace($translationPrefix . $column['name'] . ' ', '', $key);
|
||||
$dict[$keyName] = "t('" . $this->webTranslate . $key . "')";
|
||||
}
|
||||
}
|
||||
return $dict;
|
||||
}
|
||||
}
|
||||
37
app/czg/crud/controller/LogController.php
Normal file
37
app/czg/crud/controller/LogController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\crud\controller;
|
||||
|
||||
use app\admin\model\CrudLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
/**
|
||||
* crud记录
|
||||
*
|
||||
*/
|
||||
class LogController extends Backend
|
||||
{
|
||||
/**
|
||||
* Log模型对象
|
||||
* @var object
|
||||
* @phpstan-var CrudLog
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected string|array $preExcludeFields = ['id', 'create_time'];
|
||||
|
||||
protected string|array $quickSearchField = ['id', 'table_name', 'comment'];
|
||||
|
||||
protected array $noNeedPermission = ['index'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new CrudLog();
|
||||
|
||||
if (!$this->auth->check('crud/crud/index')) {
|
||||
$this->error(__('You have no permission'), [], 401);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
90
app/czg/routine/controller/AdminInfoController.php
Normal file
90
app/czg/routine/controller/AdminInfoController.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\routine\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\Admin;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class AdminInfoController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var Admin
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected string|array $preExcludeFields = ['username', 'last_login_time', 'password', 'salt', 'status'];
|
||||
|
||||
protected array $authAllowFields = ['id', 'username', 'nickname', 'avatar', 'email', 'mobile', 'motto', 'last_login_time'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->auth->setAllowFields($this->authAllowFields);
|
||||
$this->model = $this->auth->getAdmin();
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$info = $this->auth->getInfo();
|
||||
$this->success('', [
|
||||
'info' => $info
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
if (!empty($data['avatar'])) {
|
||||
$row->avatar = $data['avatar'];
|
||||
if ($row->save()) {
|
||||
$this->success(__('Avatar modified successfully!'));
|
||||
}
|
||||
}
|
||||
|
||||
// 数据验证
|
||||
if ($this->modelValidate) {
|
||||
try {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = new $validate();
|
||||
$validate->scene('info')->check($data);
|
||||
} catch (Throwable $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['password'])) {
|
||||
$this->model->resetPassword($this->auth->id, $data['password']);
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
app/czg/routine/controller/AttachmentController.php
Normal file
59
app/czg/routine/controller/AttachmentController.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\routine\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\model\Attachment as AttachmentModel;
|
||||
|
||||
class AttachmentController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var AttachmentModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected string|array $quickSearchField = 'name';
|
||||
|
||||
protected array $withJoinTable = ['admin', 'user'];
|
||||
|
||||
protected string|array $defaultSortField = 'last_upload_time,desc';
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new AttachmentModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function del(): void
|
||||
{
|
||||
$where = [];
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds) {
|
||||
$where[] = [$this->dataLimitField, 'in', $dataLimitAdminIds];
|
||||
}
|
||||
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
$where[] = [$this->model->getPk(), 'in', $ids];
|
||||
$data = $this->model->where($where)->select();
|
||||
|
||||
$count = 0;
|
||||
try {
|
||||
foreach ($data as $v) {
|
||||
$count += $v->delete();
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->error(__('%d records and files have been deleted', [$count]) . $e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success(__('%d records and files have been deleted', [$count]));
|
||||
} else {
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
}
|
||||
}
|
||||
246
app/czg/routine/controller/ConfigController.php
Normal file
246
app/czg/routine/controller/ConfigController.php
Normal file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\routine\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\Filesystem;
|
||||
use app\common\library\Email;
|
||||
use PHPMailer\PHPMailer\PHPMailer;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\Config as ConfigModel;
|
||||
use PHPMailer\PHPMailer\Exception as PHPMailerException;
|
||||
|
||||
class ConfigController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var ConfigModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected array $filePath = [
|
||||
'appConfig' => 'config/app.php',
|
||||
'webAdminBase' => 'web/src/router/static/adminBase.ts',
|
||||
'backendEntranceStub' => 'app/admin/library/stubs/backendEntrance.stub',
|
||||
];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new ConfigModel();
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$configGroup = get_sys_config('config_group');
|
||||
$config = $this->model->order('weigh desc')->select()->toArray();
|
||||
|
||||
$list = [];
|
||||
$newConfigGroup = [];
|
||||
foreach ($configGroup as $item) {
|
||||
$list[$item['key']]['name'] = $item['key'];
|
||||
$list[$item['key']]['title'] = __($item['value']);
|
||||
$newConfigGroup[$item['key']] = $list[$item['key']]['title'];
|
||||
}
|
||||
foreach ($config as $item) {
|
||||
if (array_key_exists($item['group'], $newConfigGroup)) {
|
||||
$item['title'] = __($item['title']);
|
||||
$list[$item['group']]['list'][] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $list,
|
||||
'remark' => get_route_remark(),
|
||||
'configGroup' => $newConfigGroup ?? [],
|
||||
'quickEntrance' => get_sys_config('config_quick_entrance'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$all = $this->model->select();
|
||||
foreach ($all as $item) {
|
||||
if ($item['type'] == 'editor') {
|
||||
$this->request->filter('clean_xss');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$this->modelValidate = false;
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
|
||||
$configValue = [];
|
||||
foreach ($all as $item) {
|
||||
if (array_key_exists($item->name, $data)) {
|
||||
$configValue[] = [
|
||||
'id' => $item->id,
|
||||
'type' => $item->getData('type'),
|
||||
'value' => $data[$item->name]
|
||||
];
|
||||
|
||||
// 自定义后台入口
|
||||
if ($item->name == 'backend_entrance') {
|
||||
$backendEntrance = get_sys_config('backend_entrance');
|
||||
if ($backendEntrance == $data[$item->name]) continue;
|
||||
|
||||
if (!preg_match("/^\/[a-zA-Z0-9]+$/", $data[$item->name])) {
|
||||
$this->error(__('Backend entrance rule'));
|
||||
}
|
||||
|
||||
// 修改 adminBaseRoutePath
|
||||
$adminBaseFilePath = Filesystem::fsFit(root_path() . $this->filePath['webAdminBase']);
|
||||
$adminBaseContent = @file_get_contents($adminBaseFilePath);
|
||||
if (!$adminBaseContent) $this->error(__('Configuration write failed: %s', [$this->filePath['webAdminBase']]));
|
||||
|
||||
$adminBaseContent = str_replace("export const adminBaseRoutePath = '$backendEntrance'", "export const adminBaseRoutePath = '{$data[$item->name]}'", $adminBaseContent);
|
||||
$result = @file_put_contents($adminBaseFilePath, $adminBaseContent);
|
||||
if (!$result) $this->error(__('Configuration write failed: %s', [$this->filePath['webAdminBase']]));
|
||||
|
||||
// 去除后台入口开头的斜杠
|
||||
$oldBackendEntrance = ltrim($backendEntrance, '/');
|
||||
$newBackendEntrance = ltrim($data[$item->name], '/');
|
||||
|
||||
// 设置应用别名映射
|
||||
$appMap = config('app.app_map');
|
||||
$adminMapKey = array_search('admin', $appMap);
|
||||
if ($adminMapKey !== false) {
|
||||
unset($appMap[$adminMapKey]);
|
||||
}
|
||||
if ($newBackendEntrance != 'admin') {
|
||||
$appMap[$newBackendEntrance] = 'admin';
|
||||
}
|
||||
$appConfigFilePath = Filesystem::fsFit(root_path() . $this->filePath['appConfig']);
|
||||
$appConfigContent = @file_get_contents($appConfigFilePath);
|
||||
if (!$appConfigContent) $this->error(__('Configuration write failed: %s', [$this->filePath['appConfig']]));
|
||||
|
||||
$appMapStr = '';
|
||||
foreach ($appMap as $newAppName => $oldAppName) {
|
||||
$appMapStr .= "'$newAppName' => '$oldAppName', ";
|
||||
}
|
||||
$appMapStr = rtrim($appMapStr, ', ');
|
||||
$appMapStr = "[$appMapStr]";
|
||||
|
||||
$appConfigContent = preg_replace("/'app_map'(\s+)=>(\s+)(.*)\/\/ 域名/s", "'app_map'\$1=>\$2$appMapStr,\n // 域名", $appConfigContent);
|
||||
$result = @file_put_contents($appConfigFilePath, $appConfigContent);
|
||||
if (!$result) $this->error(__('Configuration write failed: %s', [$this->filePath['appConfig']]));
|
||||
|
||||
// 建立API入口文件
|
||||
$oldBackendEntranceFile = Filesystem::fsFit(public_path() . $oldBackendEntrance . '.php');
|
||||
$newBackendEntranceFile = Filesystem::fsFit(public_path() . $newBackendEntrance . '.php');
|
||||
if (file_exists($oldBackendEntranceFile)) @unlink($oldBackendEntranceFile);
|
||||
|
||||
if ($newBackendEntrance != 'admin') {
|
||||
$backendEntranceStub = @file_get_contents(Filesystem::fsFit(root_path() . $this->filePath['backendEntranceStub']));
|
||||
if (!$backendEntranceStub) $this->error(__('Configuration write failed: %s', [$this->filePath['backendEntranceStub']]));
|
||||
|
||||
$result = @file_put_contents($newBackendEntranceFile, $backendEntranceStub);
|
||||
if (!$result) $this->error(__('Configuration write failed: %s', [$newBackendEntranceFile]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('edit');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->saveAll($configValue);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('The current page configuration item was updated successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件测试
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function sendTestMail(): void
|
||||
{
|
||||
$data = $this->request->post();
|
||||
$mail = new Email();
|
||||
try {
|
||||
$mail->Host = $data['smtp_server'];
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = $data['smtp_user'];
|
||||
$mail->Password = $data['smtp_pass'];
|
||||
$mail->SMTPSecure = $data['smtp_verification'] == 'SSL' ? PHPMailer::ENCRYPTION_SMTPS : PHPMailer::ENCRYPTION_STARTTLS;
|
||||
$mail->Port = $data['smtp_port'];
|
||||
|
||||
$mail->setFrom($data['smtp_sender_mail'], $data['smtp_user']);
|
||||
|
||||
$mail->isSMTP();
|
||||
$mail->addAddress($data['testMail']);
|
||||
$mail->isHTML();
|
||||
$mail->setSubject(__('This is a test email') . '-' . get_sys_config('site_name'));
|
||||
$mail->Body = __('Congratulations, receiving this email means that your email service has been configured correctly');
|
||||
$mail->send();
|
||||
} catch (PHPMailerException) {
|
||||
$this->error($mail->ErrorInfo);
|
||||
}
|
||||
$this->success(__('Test mail sent successfully~'));
|
||||
}
|
||||
}
|
||||
150
app/czg/security/controller/DataRecycleController.php
Normal file
150
app/czg/security/controller/DataRecycleController.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\security\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\DataRecycle as DataRecycleModel;
|
||||
|
||||
class DataRecycleController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var DataRecycleModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['update_time', 'create_time'];
|
||||
|
||||
protected string|array $quickSearchField = 'name';
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new DataRecycleModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data['controller_as'] = str_ireplace('.php', '', $data['controller'] ?? '');
|
||||
$data['controller_as'] = strtolower(str_ireplace(['\\', '.'], '/', $data['controller_as']));
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
// 放在add方法内,就不需要额外添加权限节点了
|
||||
$this->success('', [
|
||||
'controllers' => $this->getControllerList(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data['controller_as'] = str_ireplace('.php', '', $data['controller'] ?? '');
|
||||
$data['controller_as'] = strtolower(str_ireplace(['\\', '.'], '/', $data['controller_as']));
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('edit');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getControllerList(): array
|
||||
{
|
||||
$outExcludeController = [
|
||||
'Addon.php',
|
||||
'Ajax.php',
|
||||
'Module.php',
|
||||
'Terminal.php',
|
||||
'Dashboard.php',
|
||||
'Index.php',
|
||||
'routine/AdminInfo.php',
|
||||
'user/MoneyLog.php',
|
||||
'user/ScoreLog.php',
|
||||
];
|
||||
$outControllers = [];
|
||||
$controllers = get_controller_list();
|
||||
foreach ($controllers as $key => $controller) {
|
||||
if (!in_array($controller, $outExcludeController)) {
|
||||
$outControllers[$key] = $controller;
|
||||
}
|
||||
}
|
||||
return $outControllers;
|
||||
}
|
||||
}
|
||||
106
app/czg/security/controller/DataRecycleLogController.php
Normal file
106
app/czg/security/controller/DataRecycleLogController.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\security\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\TableManager;
|
||||
use think\facade\Db;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\DataRecycleLog as DataRecycleLogModel;
|
||||
|
||||
class DataRecycleLogController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var DataRecycleLogModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = [];
|
||||
|
||||
protected string|array $quickSearchField = 'recycle.name';
|
||||
|
||||
protected array $withJoinTable = ['recycle', 'admin'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new DataRecycleLogModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function restore(): void
|
||||
{
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
$data = $this->model->where('id', 'in', $ids)->select();
|
||||
if (!$data) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
foreach ($data as $row) {
|
||||
$recycleData = json_decode($row['data'], true);
|
||||
if (is_array($recycleData) && Db::connect(TableManager::getConnection($row->connection))->name($row->data_table)->insert($recycleData)) {
|
||||
$row->delete();
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
if ($count) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were restore'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function info(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->where('data_recycle_log.id', $id)
|
||||
->find();
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
$data = $this->jsonToArray($row['data']);
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $key => $item) {
|
||||
$data[$key] = $this->jsonToArray($item);
|
||||
}
|
||||
}
|
||||
$row['data'] = $data;
|
||||
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
protected function jsonToArray($value = '')
|
||||
{
|
||||
if (!is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
$data = json_decode($value, true);
|
||||
if (($data && is_object($data)) || (is_array($data) && !empty($data))) {
|
||||
return $data;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
204
app/czg/security/controller/SensitiveDataController.php
Normal file
204
app/czg/security/controller/SensitiveDataController.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\security\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SensitiveData as SensitiveDataModel;
|
||||
|
||||
class SensitiveDataController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var SensitiveDataModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['update_time', 'create_time'];
|
||||
|
||||
protected string|array $quickSearchField = 'controller';
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new SensitiveDataModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($res->items() as $item) {
|
||||
if ($item->data_fields) {
|
||||
$fields = [];
|
||||
foreach ($item->data_fields as $key => $field) {
|
||||
$fields[] = $field ?: $key;
|
||||
}
|
||||
$item->data_fields = $fields;
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加重写
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data['controller_as'] = str_ireplace('.php', '', $data['controller'] ?? '');
|
||||
$data['controller_as'] = strtolower(str_ireplace(['\\', '.'], '/', $data['controller_as']));
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($data['fields'])) {
|
||||
$data['data_fields'] = [];
|
||||
foreach ($data['fields'] as $field) {
|
||||
$data['data_fields'][$field['name']] = $field['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
// 放在add方法内,就不需要额外添加权限节点了
|
||||
$this->success('', [
|
||||
'controllers' => $this->getControllerList(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑重写
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data['controller_as'] = str_ireplace('.php', '', $data['controller'] ?? '');
|
||||
$data['controller_as'] = strtolower(str_ireplace(['\\', '.'], '/', $data['controller_as']));
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('edit');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($data['fields'])) {
|
||||
$data['data_fields'] = [];
|
||||
foreach ($data['fields'] as $field) {
|
||||
$data['data_fields'][$field['name']] = $field['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'row' => $row,
|
||||
'controllers' => $this->getControllerList(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getControllerList(): array
|
||||
{
|
||||
$outExcludeController = [
|
||||
'Addon.php',
|
||||
'Ajax.php',
|
||||
'Dashboard.php',
|
||||
'Index.php',
|
||||
'Module.php',
|
||||
'Terminal.php',
|
||||
'auth/AdminLog.php',
|
||||
'routine/AdminInfo.php',
|
||||
'routine/Config.php',
|
||||
'user/MoneyLog.php',
|
||||
'user/ScoreLog.php',
|
||||
];
|
||||
$outControllers = [];
|
||||
$controllers = get_controller_list();
|
||||
foreach ($controllers as $key => $controller) {
|
||||
if (!in_array($controller, $outExcludeController)) {
|
||||
$outControllers[$key] = $controller;
|
||||
}
|
||||
}
|
||||
return $outControllers;
|
||||
}
|
||||
}
|
||||
117
app/czg/security/controller/SensitiveDataLogController.php
Normal file
117
app/czg/security/controller/SensitiveDataLogController.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\security\controller;
|
||||
|
||||
use Throwable;
|
||||
use ba\TableManager;
|
||||
use think\facade\Db;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SensitiveDataLog as SensitiveDataLogModel;
|
||||
|
||||
class SensitiveDataLogController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var SensitiveDataLogModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = [];
|
||||
|
||||
protected string|array $quickSearchField = 'sensitive.name';
|
||||
|
||||
protected array $withJoinTable = ['sensitive', 'admin'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new SensitiveDataLogModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($res->items() as $item) {
|
||||
$item->id_value = $item['primary_key'] . '=' . $item->id_value;
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function info(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->where('sensitive_data_log.id', $id)
|
||||
->find();
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function rollback(): void
|
||||
{
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
$data = $this->model->where('id', 'in', $ids)->select();
|
||||
if (!$data) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
foreach ($data as $row) {
|
||||
if (Db::connect(TableManager::getConnection($row->connection))->name($row->data_table)->where($row->primary_key, $row->id_value)->update([
|
||||
$row->data_field => $row->before
|
||||
])) {
|
||||
$row->delete();
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
if ($count) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were rollback'));
|
||||
}
|
||||
}
|
||||
}
|
||||
29
app/czg/sys/controller/ConfigController.php
Normal file
29
app/czg/sys/controller/ConfigController.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\sys\controller;
|
||||
|
||||
use app\admin\model\SysMenu;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class ConfigController extends Backend
|
||||
{
|
||||
|
||||
protected array $noNeedLogin = ['list'];
|
||||
public function list()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$db = Db::connect(get_slave_connect_name());
|
||||
$count = $db->name('sys_config')->count();
|
||||
$config_list= $db->name('sys_config')->where(['status' => 1])->limit(page($get['page'], $get['limit']), $get['limit'])->select()->toArray();
|
||||
$this->n_success(['page' => [
|
||||
'totalCount' => $count,
|
||||
'pageSize' => $get['limit'],
|
||||
'totalPage' => ceil($count / $get['limit']),
|
||||
'currPage' => $get['page'],
|
||||
'list' => $config_list,
|
||||
]]);
|
||||
}
|
||||
|
||||
}
|
||||
24
app/czg/sys/controller/LogController.php
Normal file
24
app/czg/sys/controller/LogController.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\sys\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class LogController extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
// 用户信息
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$this->result('成功', DatabaseRoute::paginateDb('sys_log', function ($query) {
|
||||
return $query->order('id', 'desc');
|
||||
}, $params['page'], $params['limit']), 0, null, [], [], 'page');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
127
app/czg/sys/controller/MenuController.php
Normal file
127
app/czg/sys/controller/MenuController.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\sys\controller;
|
||||
|
||||
use app\admin\model\SysMenu;
|
||||
use app\common\controller\Backend;
|
||||
use think\facade\Db;
|
||||
|
||||
class MenuController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['*'];
|
||||
// 菜单列表
|
||||
public function nav()
|
||||
{
|
||||
$admin = $this->auth->getAdmin();
|
||||
$return = SysMenu::getMenuList($this->auth->getUserMenus($admin['user_id']));
|
||||
|
||||
$this->n_success([
|
||||
'menuList' => convertToCamelCase($return['menuList']),
|
||||
'permissions' => $return['permissions'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function list()
|
||||
{
|
||||
$menuList = Db::name('sys_menu')->order('order_num', 'asc')->select()->toArray();
|
||||
|
||||
// 收集所有 parent_id
|
||||
$parentIds = array_column($menuList, 'parent_id');
|
||||
$parentIds = array_unique(array_filter($parentIds));
|
||||
|
||||
// 批量查询父级菜单
|
||||
$parentMap = [];
|
||||
if (!empty($parentIds)) {
|
||||
$parents = Db::name('sys_menu')->whereIn('menu_id', $parentIds)->column('name', 'menu_id');
|
||||
$parentMap = $parents;
|
||||
}
|
||||
|
||||
// 设置 parentName
|
||||
foreach ($menuList as &$menu) {
|
||||
$menu['menu_id'] = (string) $menu['menu_id'];
|
||||
$menu['parent_id'] = (string) $menu['parent_id'];
|
||||
|
||||
$menu['parent_name'] = $parentMap[$menu['parent_id']] ?? '';
|
||||
}
|
||||
unset($menu);
|
||||
|
||||
return $this->ApiDataReturn(convertToCamelCase($menuList));
|
||||
}
|
||||
|
||||
public function info()
|
||||
{
|
||||
$data = Db::name('sys_menu')->where([
|
||||
'menu_id' => $this->request->route->param('id')
|
||||
])->find();
|
||||
$data['menu_id'] = (string) $data['menu_id'];
|
||||
$data['parent_id'] = (string) $data['parent_id'];
|
||||
$data = convertToCamelCase($data);
|
||||
$this->n_success(['menu' => $data]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function save()
|
||||
{
|
||||
$menu = $this->request->post();
|
||||
SysMenu::verifyForm($menu);
|
||||
$menu = convertKeysCamelToSnakeRecursive($menu);
|
||||
Db::connect(get_master_connect_name())->name('sys_menu')->insert($menu);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function selectInfo()
|
||||
{
|
||||
$list = Db::name('sys_menu')->where([
|
||||
'type' => ['!=', 2]
|
||||
])->order('order_num')->select()->toArray();
|
||||
|
||||
$list[] = [
|
||||
'menu_id' => 0,
|
||||
'name' => '一级菜单',
|
||||
'parent_id' => -1,
|
||||
'open' => true,
|
||||
];
|
||||
$list = convertToCamelCase($list);
|
||||
$this->n_success(['menuList' => $list]);
|
||||
// $this->successWithData([
|
||||
// 'menuList' => $list
|
||||
// ]);
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
Db::name('sys_menu')->where([
|
||||
'menu_id' => $params['menu_id']
|
||||
])->update($params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
if(empty($post['menuId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
$menuId = $post['menuId'];
|
||||
if($menuId <= 31) {
|
||||
$this->error('系统菜单,不能删除');
|
||||
}
|
||||
|
||||
// 判断是否有子菜单或按钮
|
||||
$menuList = Db::connect(get_slave_connect_name())->name('sys_menu')->where(['parent_id' => $menuId])->order('order_num', 'asc')->select()->toArray();
|
||||
if($menuList) {
|
||||
$this->error('请先删除子菜单或按钮');
|
||||
}
|
||||
|
||||
if(Db::name('sys_menu')->where(['menu_id' => $menuId])->delete()) {
|
||||
$this->success('删除成功');
|
||||
}
|
||||
$this->error('操作失败');
|
||||
}
|
||||
|
||||
}
|
||||
43
app/czg/sys/controller/OssController.php
Normal file
43
app/czg/sys/controller/OssController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\sys\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class OssController extends Backend
|
||||
{
|
||||
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$data = DatabaseRoute::paginateDb('sys_oss', function ($query) {
|
||||
return $query->order('id', 'desc');
|
||||
}, $params['page'], $params['limit']);
|
||||
$this->n_success(['page' => $data]);
|
||||
}
|
||||
|
||||
public function config()
|
||||
{
|
||||
$data = Db::connect(get_slave_connect_name())->name('sys_config')->where(['param_key' => 'CLOUD_STORAGE_CONFIG_KEY'])->column('param_value')[0];
|
||||
$data = json_decode($data, true);
|
||||
$this->n_success(['config' => $data]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function saveConfig()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
if(is_array($post)) {
|
||||
$post = json_encode($post);
|
||||
}else {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
Db::name('sys_config')->where(['param_key' => 'CLOUD_STORAGE_CONFIG_KEY'])->update(['param_value' => $post]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
108
app/czg/sys/controller/RoleController.php
Normal file
108
app/czg/sys/controller/RoleController.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\sys\controller;
|
||||
|
||||
use app\admin\model\SysMenu;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class RoleController extends Backend
|
||||
{
|
||||
|
||||
public function list()
|
||||
{
|
||||
$prams = $this->request->get();
|
||||
$data = DatabaseRoute::paginateDb('sys_role', function ($query) {
|
||||
return $query;
|
||||
}, $prams['page'], $prams['limit']);
|
||||
$this->n_success(['page' => $data]);
|
||||
}
|
||||
|
||||
private function saveRoleMenu($roleId, $params)
|
||||
{
|
||||
if (!empty($params['menu_id_list'])) {
|
||||
Db::name('sys_role_menu')->where([
|
||||
'role_id' => $roleId
|
||||
])->delete();
|
||||
|
||||
foreach ($params['menu_id_list'] as $menuId) {
|
||||
Db::name('sys_role_menu')->insert([
|
||||
'role_id' => $roleId,
|
||||
'menu_id' => $menuId
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
|
||||
$id = Db::name('sys_role')->insertGetId([
|
||||
'role_name' => $params['role_name'],
|
||||
'create_time' => getNormalDate(),
|
||||
'remark' => $params['remark'] ?? ''
|
||||
]);
|
||||
$this->saveRoleMenu($id, $params);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
Db::name('sys_role')->where([
|
||||
'role_id' => $params['role_id']
|
||||
])->update([
|
||||
'role_name' => $params['role_name'],
|
||||
'remark' => $params['remark'] ?? ''
|
||||
]);
|
||||
|
||||
$this->saveRoleMenu($params['role_id'], $params);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
Db::name('sys_role')->where([
|
||||
['role_id', 'in', $params]
|
||||
])->delete();
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function selects()
|
||||
{
|
||||
|
||||
$this->n_success(['list' => convertToCamelCase(array_map(function ($item) {
|
||||
$item['role_id'] = (string)$item['role_id'];
|
||||
return $item;
|
||||
}, Db::connect(get_slave_connect_name())->name('sys_role')->select()->toArray()))]);
|
||||
}
|
||||
|
||||
|
||||
// 角色信息
|
||||
public function info()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['roleId'])) {
|
||||
$this->error('roleId 不能为空');
|
||||
}
|
||||
$db = Db::connect(get_slave_connect_name());
|
||||
|
||||
$role = $db->name('sys_role')->where(['role_id' => $get['roleId']])->find();
|
||||
if (!$role) {
|
||||
$this->error('角色不存在');
|
||||
}
|
||||
$role = apiconvertToCamelCase($role);
|
||||
$menuIdList = $db->name('sys_role_menu')->where(['role_id' => $get['roleId']])->column('menu_id');
|
||||
|
||||
$role['menuIdList'] = $menuIdList;
|
||||
$this->n_success(['role' => $role]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
232
app/czg/sys/controller/UserController.php
Normal file
232
app/czg/sys/controller/UserController.php
Normal file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\sys\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\InvitationCodeUtil;
|
||||
use extend\ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class UserController extends Backend
|
||||
{
|
||||
protected array $noNeedPermission = ['*'];
|
||||
|
||||
// 用户信息
|
||||
public function info()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if (empty($get['userId'])) {
|
||||
$info = $this->auth->getAdmin();
|
||||
} else {
|
||||
$info = DatabaseRoute::getDb('sys_user', $get['userId'])->find();
|
||||
}
|
||||
$info = convertToCamelCase($info);
|
||||
$info['password'] = null;
|
||||
// $info['salt'] = null;
|
||||
$roleIdList = array_column(Db::name('sys_user_role')->where([
|
||||
'user_id' => $info['userId']
|
||||
])->select()->toArray(), 'role_id');
|
||||
foreach ($roleIdList as $k => &$v) {
|
||||
$v = (string) $v;
|
||||
}
|
||||
$info['roleIdList'] = $roleIdList;
|
||||
$this->n_success(['user' => $info]);
|
||||
}
|
||||
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$data = DatabaseRoute::paginateAllDb('sys_user', function ($query) use ($params) {
|
||||
if (!empty($params['username'])) {
|
||||
$query->whereLike('username', '%' . $params['username'] . '%');
|
||||
}
|
||||
|
||||
if (!empty($params['isChannel'])) {
|
||||
$query->where('is_channel', $params['isChannel']);
|
||||
}
|
||||
return $query;
|
||||
}, $params['page'], $params['limit']);
|
||||
$data['list'] = convertToCamelCase($data['list']);
|
||||
$this->n_success(['page' => $data]);
|
||||
|
||||
}
|
||||
|
||||
public function detail()
|
||||
{
|
||||
$id = $this->request->route->param('id');
|
||||
$sysInfo = DatabaseRoute::getDb('sys_user', $id)->find();
|
||||
if (!$sysInfo) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
$userRoleList = Db::name('sys_user_role')->where([
|
||||
'user_id' => $sysInfo['user_id']
|
||||
])->select()->toArray();
|
||||
$sysInfo = convertToCamelCase($sysInfo);
|
||||
$sysInfo['roleIdList'] =array_map('strval', array_column($userRoleList, 'role_id'));
|
||||
$this->successWithData([
|
||||
'user' => $sysInfo
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function updateRoleInfo($params)
|
||||
{
|
||||
if (!empty($params['role_id_list'])) {
|
||||
Db::name('sys_user_role')->where([
|
||||
'user_id' => $params['user_id']
|
||||
])->delete();
|
||||
|
||||
foreach ($params['role_id_list'] as $roleId) {
|
||||
Db::name('sys_user_role')->insert([
|
||||
'user_id' => $params['user_id'],
|
||||
'role_id' => $roleId
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
if (empty($params['userId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
if (isset($params['password']) && $params['password'] == '') {
|
||||
unset($params['password']);
|
||||
} else if (!empty($params['password'])) {
|
||||
$params['password'] = shiro_simple_hash_hex_salt('sha256', $params['password'], $params['salt']);
|
||||
}
|
||||
$this->updateRoleInfo($params);
|
||||
unset($params['role_id_list']);
|
||||
|
||||
DatabaseRoute::getDb('sys_user', $params['user_id'], true, true)->where([
|
||||
'user_id' => $params['user_id']
|
||||
])->update($params);
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
$params['create_time'] = getNormalDate();
|
||||
$params['salt'] = Random::generateRandomPrefixedId(20);
|
||||
$params['password'] = shiro_simple_hash_hex_salt('sha256', $params['password'], $params['salt']);
|
||||
$params['user_id'] = Random::generateRandomPrefixedId();
|
||||
|
||||
$this->updateRoleInfo($params);
|
||||
|
||||
unset($params['role_id_list']);
|
||||
unset($params['money']);
|
||||
DatabaseRoute::getDb('sys_user', $params['user_id'], true)->insert($params);
|
||||
if (!empty($params['is_channel']) && $params['is_channel'] == 1 && empty($params['qd_code'])) {
|
||||
$params['qd_code'] = InvitationCodeUtil::toRegisteredCode($params['user_id']);
|
||||
DatabaseRoute::getDb('sys_user', $params['user_id'], true, true)->update($params);
|
||||
}
|
||||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
if (empty($params)) {
|
||||
$this->error('参数有误');
|
||||
}
|
||||
|
||||
foreach ($params as $id) {
|
||||
DatabaseRoute::getDb('sys_user', $id, true, true)->delete();
|
||||
}
|
||||
|
||||
$this->success();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function selectInviteUserList()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$params = convertKeysCamelToSnakeRecursive($params);
|
||||
|
||||
// 1. 分页查询被邀请人分组:按 inviter_code 聚合
|
||||
$inviteListPageInfo = DatabaseRoute::paginateAllDb('tb_user', function ($query) use ($params) {
|
||||
if (!empty($params['user_name'])) {
|
||||
$query->where('user_name', 'like', '%' . $params['user_name'] . '%');
|
||||
}
|
||||
|
||||
if (!empty($params['phone'])) {
|
||||
$query->where('phone', 'like', '%' . $params['phone'] . '%');
|
||||
}
|
||||
|
||||
return $query->fieldRaw('ANY_VALUE(inviter_code) AS inviter_code, COUNT(*) AS counts')
|
||||
->group('inviter_code')
|
||||
->order('counts', 'desc');
|
||||
}, $params['page'], $params['limit'], 'counts', null, true);
|
||||
|
||||
$records = $inviteListPageInfo['records'];
|
||||
if (empty($records)) {
|
||||
$this->successWithData($inviteListPageInfo); // 无数据
|
||||
}
|
||||
|
||||
$inviteCodeList = array_column($records, 'inviter_code');
|
||||
$countMap = array_column($records, 'counts', 'inviter_code');
|
||||
|
||||
// 2. 查询邀请人信息(部分 code 可能查不到 => 被删)
|
||||
$userInfoList = DatabaseRoute::getAllDbData('tb_user', function ($query) use ($inviteCodeList) {
|
||||
return $query->whereIn('invitation_code', $inviteCodeList);
|
||||
})->select()->toArray();
|
||||
|
||||
// 3. 查询金额信息(注意先判断 user_id 是否存在)
|
||||
$userIdList = array_column($userInfoList, 'user_id');
|
||||
$userMoneyList = [];
|
||||
if (!empty($userIdList)) {
|
||||
$userMoneyList = DatabaseRoute::getAllDbData('user_money', function ($query) use ($userIdList) {
|
||||
return $query->whereIn('user_id', $userIdList);
|
||||
})->select()->toArray();
|
||||
}
|
||||
|
||||
$userMoneyMap = [];
|
||||
foreach ($userMoneyList as $money) {
|
||||
$userMoneyMap[$money['user_id']] = $money;
|
||||
}
|
||||
|
||||
// 4. 构建 inviter_code => user 映射
|
||||
$inviterMap = [];
|
||||
foreach ($userInfoList as $user) {
|
||||
$code = $user['invitation_code'];
|
||||
$uid = $user['user_id'];
|
||||
|
||||
$user['money'] = $userMoneyMap[$uid]['invite_income_money'] ?? 0;
|
||||
$user['counts'] = $countMap[$code] ?? 0;
|
||||
|
||||
$inviterMap[$code] = $user;
|
||||
}
|
||||
|
||||
// 5. 最终组装记录:保留所有 inviter_code,即使用户不存在
|
||||
$finalRecords = [];
|
||||
foreach ($inviteCodeList as $code) {
|
||||
if (isset($inviterMap[$code])) {
|
||||
$finalRecords[] = $inviterMap[$code];
|
||||
} else {
|
||||
// 🛠️ 如果邀请人被删,构造一条匿名信息
|
||||
$finalRecords[] = [
|
||||
'user_id' => null,
|
||||
'user_name' => '已删除',
|
||||
'phone' => '-',
|
||||
'money' => 0,
|
||||
'counts' => $countMap[$code],
|
||||
'invitation_code' => $code,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$inviteListPageInfo['records'] = $finalRecords;
|
||||
$this->successWithData($inviteListPageInfo);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
163
app/czg/user/controller/GroupController.php
Normal file
163
app/czg/user/controller/GroupController.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\user\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\UserRule;
|
||||
use app\admin\model\UserGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class GroupController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var UserGroup
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['update_time', 'create_time'];
|
||||
|
||||
protected string|array $quickSearchField = 'name';
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
// parent::initialize();
|
||||
$this->model = new UserGroup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data = $this->handleRules($data);
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
$validate->scene('add')->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$data = $this->handleRules($data);
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
$validate->scene('edit')->check($data);
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
}
|
||||
|
||||
// 读取所有pid,全部从节点数组移除,父级选择状态由子级决定
|
||||
$pidArr = UserRule::field('pid')
|
||||
->distinct(true)
|
||||
->where('id', 'in', $row->rules)
|
||||
->select()
|
||||
->toArray();
|
||||
$rules = $row->rules ? explode(',', $row->rules) : [];
|
||||
foreach ($pidArr as $item) {
|
||||
$ruKey = array_search($item['pid'], $rules);
|
||||
if ($ruKey !== false) {
|
||||
unset($rules[$ruKey]);
|
||||
}
|
||||
}
|
||||
$row->rules = array_values($rules);
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限规则入库前处理
|
||||
* @param array $data 接受到的数据
|
||||
* @return array
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function handleRules(array &$data): array
|
||||
{
|
||||
if (is_array($data['rules']) && $data['rules']) {
|
||||
$rules = UserRule::select();
|
||||
$super = true;
|
||||
foreach ($rules as $rule) {
|
||||
if (!in_array($rule['id'], $data['rules'])) {
|
||||
$super = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($super) {
|
||||
$data['rules'] = '*';
|
||||
} else {
|
||||
$data['rules'] = implode(',', $data['rules']);
|
||||
}
|
||||
} else {
|
||||
unset($data['rules']);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
50
app/czg/user/controller/MoneyLogController.php
Normal file
50
app/czg/user/controller/MoneyLogController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\user\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\User;
|
||||
use app\admin\model\UserMoneyLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class MoneyLogController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var UserMoneyLog
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected array $withJoinTable = ['user'];
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['create_time'];
|
||||
|
||||
protected string|array $quickSearchField = ['user.username', 'user.nickname'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
// parent::initialize();
|
||||
$this->model = new UserMoneyLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @param int $userId
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(int $userId = 0): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
parent::add();
|
||||
}
|
||||
|
||||
$user = User::where('id', $userId)->find();
|
||||
if (!$user) {
|
||||
$this->error(__("The user can't find it"));
|
||||
}
|
||||
$this->success('', [
|
||||
'user' => $user
|
||||
]);
|
||||
}
|
||||
}
|
||||
260
app/czg/user/controller/RuleController.php
Normal file
260
app/czg/user/controller/RuleController.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\user\controller;
|
||||
|
||||
use ba\Tree;
|
||||
use Throwable;
|
||||
use app\admin\model\UserRule;
|
||||
use app\admin\model\UserGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class RuleController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var UserRule
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
/**
|
||||
* @var Tree
|
||||
*/
|
||||
protected Tree $tree;
|
||||
|
||||
protected string|array $preExcludeFields = ['create_time', 'update_time'];
|
||||
|
||||
protected string|array $defaultSortField = ['weigh' => 'desc'];
|
||||
|
||||
protected string|array $quickSearchField = 'title';
|
||||
|
||||
/**
|
||||
* 远程select初始化传值
|
||||
* @var array
|
||||
*/
|
||||
protected array $initValue;
|
||||
|
||||
/**
|
||||
* 是否组装Tree
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $assembleTree;
|
||||
|
||||
/**
|
||||
* 搜索关键词
|
||||
* @var string
|
||||
*/
|
||||
protected string $keyword;
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
// parent::initialize();
|
||||
|
||||
// 防止 URL 中的特殊符号被默认的 filter 函数转义
|
||||
$this->request->filter('clean_xss');
|
||||
|
||||
$this->model = new UserRule();
|
||||
$this->tree = Tree::instance();
|
||||
$isTree = $this->request->param('isTree', true);
|
||||
$this->initValue = $this->request->get("initValue/a", []);
|
||||
$this->initValue = array_filter($this->initValue);
|
||||
$this->keyword = $this->request->request('quickSearch', '');
|
||||
$this->assembleTree = $isTree && !$this->initValue; // 有初始化值时不组装树状(初始化出来的值更好看)
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $this->getRules(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
|
||||
$data[$this->dataLimitField] = $this->auth->id;
|
||||
}
|
||||
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
|
||||
if (!empty($data['pid'])) {
|
||||
$groups = UserGroup::where('rules', '<>', '*')->select();
|
||||
foreach ($groups as $group) {
|
||||
$rules = explode(',', $group->rules);
|
||||
if (in_array($data['pid'], $rules) && !in_array($this->model->id, $rules)) {
|
||||
$rules[] = $this->model->id;
|
||||
$group->rules = implode(',', $rules);
|
||||
$group->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$id = $this->request->param($this->model->getPk());
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
$dataLimitAdminIds = $this->getDataLimitAdminIds();
|
||||
if ($dataLimitAdminIds && !in_array($row[$this->dataLimitField], $dataLimitAdminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$data = $this->excludeFields($data);
|
||||
$result = false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('edit');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
if (isset($data['pid']) && $data['pid'] > 0) {
|
||||
// 满足意图并消除副作用
|
||||
$parent = $this->model->where('id', $data['pid'])->find();
|
||||
if ($parent['pid'] == $row['id']) {
|
||||
$parent->pid = 0;
|
||||
$parent->save();
|
||||
}
|
||||
}
|
||||
$result = $row->save($data);
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Update successful'));
|
||||
} else {
|
||||
$this->error(__('No rows updated'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function del(): void
|
||||
{
|
||||
$ids = $this->request->param('ids/a', []);
|
||||
|
||||
// 子级元素检查
|
||||
$subData = $this->model->where('pid', 'in', $ids)->column('pid', 'id');
|
||||
foreach ($subData as $key => $subDatum) {
|
||||
if (!in_array($key, $ids)) {
|
||||
$this->error(__('Please delete the child element first, or use batch deletion'));
|
||||
}
|
||||
}
|
||||
|
||||
parent::del();
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程下拉
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function select(): void
|
||||
{
|
||||
$data = $this->getRules([['status', '=', 1]]);
|
||||
|
||||
if ($this->assembleTree) {
|
||||
$data = $this->tree->assembleTree($this->tree->getTreeArray($data, 'title'));
|
||||
}
|
||||
$this->success('', [
|
||||
'options' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单规则
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function getRules(array $where = []): array
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$initKey = $this->request->get("initKey/s", $pk);
|
||||
|
||||
if ($this->keyword) {
|
||||
$keyword = explode(' ', $this->keyword);
|
||||
foreach ($keyword as $item) {
|
||||
$where[] = [$this->quickSearchField, 'like', '%' . $item . '%'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->initValue) {
|
||||
$where[] = [$initKey, 'in', $this->initValue];
|
||||
}
|
||||
|
||||
$data = $this->model
|
||||
->where($where)
|
||||
->order($this->queryOrderBuilder())
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return $this->assembleTree ? $this->tree->assembleChild($data) : $data;
|
||||
}
|
||||
|
||||
}
|
||||
50
app/czg/user/controller/ScoreLogController.php
Normal file
50
app/czg/user/controller/ScoreLogController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\user\controller;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\User;
|
||||
use app\admin\model\UserScoreLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class ScoreLogController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var UserScoreLog
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected array $withJoinTable = ['user'];
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['create_time'];
|
||||
|
||||
protected string|array $quickSearchField = ['user.username', 'user.nickname'];
|
||||
|
||||
public function initialize(): void
|
||||
{
|
||||
// parent::initialize();
|
||||
$this->model = new UserScoreLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @param int $userId
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(int $userId = 0): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
parent::add();
|
||||
}
|
||||
|
||||
$user = User::where('id', $userId)->find();
|
||||
if (!$user) {
|
||||
$this->error(__("The user can't find it"));
|
||||
}
|
||||
$this->success('', [
|
||||
'user' => $user
|
||||
]);
|
||||
}
|
||||
}
|
||||
541
app/czg/user/controller/UserController.php
Normal file
541
app/czg/user/controller/UserController.php
Normal file
@@ -0,0 +1,541 @@
|
||||
<?php
|
||||
|
||||
namespace app\czg\user\controller;
|
||||
|
||||
use app\api\model\TbUser;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\User as UserModel;
|
||||
|
||||
class UserController extends Backend
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @phpstan-var UserModel
|
||||
*/
|
||||
protected object $model;
|
||||
|
||||
protected array $withJoinTable = ['userGroup'];
|
||||
|
||||
// 排除字段
|
||||
protected string|array $preExcludeFields = ['last_login_time', 'login_failure', 'password', 'salt'];
|
||||
|
||||
protected string|array $quickSearchField = ['username', 'nickname', 'id'];
|
||||
|
||||
protected array $noNeedPermission = [
|
||||
'courseMessage',
|
||||
'userMessage',
|
||||
'selectUserOnLineCount',
|
||||
'homeMessage',
|
||||
'selectUserCountStatisticsByTime',
|
||||
'selectUserList',
|
||||
'updateUserStatusByUserId',
|
||||
'inviteAmount',
|
||||
'selectUserByInvitationCode',
|
||||
'getuserinfo',
|
||||
'deleteUserByUserId',
|
||||
];
|
||||
protected array $noNeedLogin = ['userListExcel'];
|
||||
public function initialize(): void
|
||||
{
|
||||
// $this->model = new UserModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function index(): void
|
||||
{
|
||||
if ($this->request->param('select')) {
|
||||
$this->select();
|
||||
}
|
||||
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function add(): void
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$data = $this->request->post();
|
||||
if (!$data) {
|
||||
$this->error(__('Parameter %s can not be empty', ['']));
|
||||
}
|
||||
|
||||
$result = false;
|
||||
$passwd = $data['password']; // 密码将被排除不直接入库
|
||||
$data = $this->excludeFields($data);
|
||||
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
// 模型验证
|
||||
if ($this->modelValidate) {
|
||||
$validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
if (class_exists($validate)) {
|
||||
$validate = new $validate();
|
||||
if ($this->modelSceneValidate) $validate->scene('add');
|
||||
$validate->check($data);
|
||||
}
|
||||
}
|
||||
$result = $this->model->save($data);
|
||||
$this->model->commit();
|
||||
|
||||
if (!empty($passwd)) {
|
||||
$this->model->resetPassword($this->model->id, $passwd);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success(__('Added successfully'));
|
||||
} else {
|
||||
$this->error(__('No rows were added'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->error(__('Parameter error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function edit(): void
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
$id = $this->request->param($pk);
|
||||
$row = $this->model->find($id);
|
||||
if (!$row) {
|
||||
$this->error(__('Record not found'));
|
||||
}
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$password = $this->request->post('password', '');
|
||||
if ($password) {
|
||||
$this->model->resetPassword($id, $password);
|
||||
}
|
||||
parent::edit();
|
||||
}
|
||||
|
||||
unset($row->salt);
|
||||
$row->password = '';
|
||||
$this->success('', [
|
||||
'row' => $row
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写select
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function select(): void
|
||||
{
|
||||
list($where, $alias, $limit, $order) = $this->queryBuilder();
|
||||
$res = $this->model
|
||||
->withoutField('password,salt')
|
||||
->withJoin($this->withJoinTable, $this->withJoinType)
|
||||
->alias($alias)
|
||||
->where($where)
|
||||
->order($order)
|
||||
->paginate($limit);
|
||||
|
||||
foreach ($res as $re) {
|
||||
$re->nickname_text = $re->username . '(ID:' . $re->id . ')';
|
||||
}
|
||||
|
||||
$this->success('', [
|
||||
'list' => $res->items(),
|
||||
'total' => $res->total(),
|
||||
'remark' => get_route_remark(),
|
||||
]);
|
||||
}
|
||||
|
||||
// 短剧分析
|
||||
public function courseMessage()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$admin = $this->auth->getAdmin();
|
||||
$pageUtils = \app\admin\model\User::queryCourseOrder($get['page'], $get['limit'], $get['type'], completeStartTime($get['date']), $admin['user_id']);
|
||||
$this->n_success(['data' => $pageUtils]);
|
||||
}
|
||||
|
||||
// 用户分析
|
||||
public function userMessage()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$admin = $this->auth->getAdmin();
|
||||
// 补全开始时间(调用之前实现的函数)
|
||||
$date = completeStartTime($get['date']); // 假设已实现该函数
|
||||
$qdCode = $admin['qd_code'];
|
||||
$sumUserCount = \app\admin\model\User::queryUserCount($get['type'], $date, null, $qdCode);
|
||||
$h5Count = \app\admin\model\User::queryUserCount($get['type'], $date, "h5", $qdCode);
|
||||
$appCount = \app\admin\model\User::queryUserCount($get['type'], $date, "app", $qdCode);
|
||||
$wxCount = \app\admin\model\User::queryUserCount($get['type'], $date, "小程序", $qdCode);
|
||||
$dyCount = \app\admin\model\User::queryUserCount($get['type'], $date, "抖音", $qdCode);
|
||||
$giveMemberCount = \app\admin\model\User::userMessage($date, $get['type'], $qdCode, 1);
|
||||
$moneyMemberCount = \app\admin\model\User::userMessage($date, $get['type'], $qdCode, 2);
|
||||
$memberCount = \app\admin\model\User::userMessage($date, $get['type'], $qdCode, null);
|
||||
$userCount = $sumUserCount - $memberCount;
|
||||
$this->n_success(['data' => [
|
||||
'sumUserCount' => $sumUserCount,
|
||||
'h5Count' => $h5Count,
|
||||
'appCount' => $appCount,
|
||||
'wxCount' => $wxCount,
|
||||
'dyCount' => $dyCount,
|
||||
'memberCount' => $memberCount,
|
||||
'giveMemberCount' => $giveMemberCount,
|
||||
'moneyMemberCount' => $moneyMemberCount,
|
||||
'userCount' => $userCount,
|
||||
]]);
|
||||
}
|
||||
|
||||
// 当前在线人数统计
|
||||
public function selectUserOnLineCount()
|
||||
{
|
||||
$admin = $this->auth->getAdmin();
|
||||
$qdCode = $admin['qd_code'];
|
||||
$selectUserOnLineCount = DatabaseRoute::getAllDbData('tb_user', function($query)use($qdCode) {
|
||||
if($query) {
|
||||
$query->where(['qd_code' => $qdCode]);
|
||||
}
|
||||
return $query->where('on_line_time', '>=', Db::raw('DATE_SUB(NOW(), INTERVAL 10 MINUTE)'));
|
||||
})->count();
|
||||
$this->n_success(['data' => $selectUserOnLineCount]);
|
||||
}
|
||||
|
||||
// 用户统计
|
||||
public function homeMessage()
|
||||
{
|
||||
$admin = $this->auth->getAdmin();
|
||||
$qdCode = $admin['qd_code'];
|
||||
$data = [];
|
||||
$data['totalUsers'] = \app\admin\model\User::queryUserCount(0, null, null, $qdCode);
|
||||
$data['newToday'] = \app\admin\model\User::queryUserCount(1, null, null, $qdCode);
|
||||
$data['newMonth'] = \app\admin\model\User::queryUserCount(2, null, null, $qdCode);
|
||||
$data['newYear'] = \app\admin\model\User::queryUserCount(3, null, null, $qdCode);
|
||||
$data['totalRevenue'] = \app\admin\model\User::queryPayMoney(0, $qdCode);
|
||||
$data['todayRevenue'] = \app\admin\model\User::queryPayMoney(1, $qdCode);
|
||||
$data['monthRevenue'] = \app\admin\model\User::queryPayMoney(2, $qdCode);
|
||||
$data['yearRevenue'] = \app\admin\model\User::queryPayMoney(3, $qdCode);
|
||||
$map = \app\admin\model\User::queryPayAndExtractInfo();
|
||||
$data['todayPayAmount'] = isset($map['payAmount'])
|
||||
? round((float)$map['payAmount'], 2, PHP_ROUND_HALF_UP)
|
||||
: 0.00;
|
||||
$data['todayPayCount'] = isset($map['payCount'])
|
||||
? (int)$map['payCount']
|
||||
: 0;
|
||||
$data['todayExtractAmount'] = isset($map['extractAmount'])
|
||||
? round((float)$map['extractAmount'], 2, PHP_ROUND_HALF_UP)
|
||||
: 0.00;
|
||||
|
||||
$data['todayExtractCount'] = isset($map['extractCount'])
|
||||
? (int)$map['extractCount']
|
||||
: 0;
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
// 用户增长折线图
|
||||
public function selectUserCountStatisticsByTime()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$startTime = $get['startTime'];
|
||||
$endTime = $get['endTime'];
|
||||
|
||||
// 初始化结果数组
|
||||
$userCountList = [];
|
||||
$dateList = [];
|
||||
|
||||
// 日期处理
|
||||
$currentDate = strtotime($startTime);
|
||||
$endDate = strtotime($endTime);
|
||||
|
||||
// 循环遍历日期范围
|
||||
while ($currentDate <= $endDate) {
|
||||
$date = date('Y-m-d', $currentDate);
|
||||
|
||||
// 查询当日用户注册数量
|
||||
$userCount = \app\admin\model\User::queryUserCount(1, $date, null, null);
|
||||
|
||||
// 记录数据
|
||||
$userCountList[] = $userCount;
|
||||
$dateList[] = $date;
|
||||
|
||||
// 日期加1天
|
||||
$currentDate = strtotime('+1 day', $currentDate);
|
||||
}
|
||||
|
||||
// 构建结果数据
|
||||
$result = [
|
||||
'userCountList' => $userCountList,
|
||||
'year' => $dateList // 注:原Java代码中使用year变量,但实际存储的是日期列表
|
||||
];
|
||||
|
||||
$this->n_success(['data' => $result]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 查询所有用户列表
|
||||
public function selectUserList()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$vipType = $params['vipType'] ?? null;
|
||||
$member = $params['member'] ?? null;
|
||||
$status = $params['status'] ?? null;
|
||||
$page = $params['page'] ?? null;
|
||||
$limit = $params['limit'] ?? null;
|
||||
$phone = $params['phone'] ?? null;
|
||||
$sysUserName = $params['sysUserName'] ?? null;
|
||||
$userName = $params['userName'] ?? null;
|
||||
$sex = $params['sex'] ?? null;
|
||||
$platform = $params['platform'] ?? null;
|
||||
$sysPhone = $params['sysPhone'] ?? null;
|
||||
$inviterCode = $params['inviterCode'] ?? null;
|
||||
$invitationCode = $params['invitationCode'] ?? null;
|
||||
$qdCode = $params['qdCode'] ?? null;
|
||||
$startTime = $params['startTime'] ?? null;
|
||||
$endTime = $params['endTime'] ?? null;
|
||||
$delegate = $params['delegate'] ?? null;
|
||||
$this->n_success(['data' => \app\admin\model\User::selectUserPage(
|
||||
$page, $limit, $phone, $sex, $platform, $sysPhone, $status, $member,
|
||||
$inviterCode, $userName, $invitationCode, $startTime, $endTime, $qdCode, $sysUserName, $vipType, $delegate
|
||||
)]);
|
||||
}
|
||||
|
||||
// 修改用户状态
|
||||
public function updateUserStatusByUserId()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId'])) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
if(empty($get['status']) && $get['status'] == null) {
|
||||
$this->error('status 不能为空');
|
||||
}
|
||||
$status = $get['status'];
|
||||
$userId = $get['userId'];
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId], true));
|
||||
// 查询用户是否存在
|
||||
$user = $db->name('tb_user')->where(['user_id' => $userId])->find();
|
||||
if (is_null($user)) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
|
||||
// 根据状态执行不同操作
|
||||
switch ($status) {
|
||||
case 1:
|
||||
// 状态1:设置状态为1,并调用upUserBlack方法(拉黑)
|
||||
\app\admin\model\User::upUserBlack($user, 1, $db);
|
||||
break;
|
||||
case 2:
|
||||
// 状态2:直接更新状态为2
|
||||
$db->name('tb_user')->where('user_id', $userId)
|
||||
->update(['status' => 2]);
|
||||
break;
|
||||
case 0:
|
||||
// 状态0:调用upUserBlack方法(解封)
|
||||
\app\admin\model\User::upUserBlack($user, 0, $db);
|
||||
break;
|
||||
default:
|
||||
// 无效状态
|
||||
$this->error('状态不正确');
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
// 更新用户邀请奖励金额
|
||||
public function inviteAmount()
|
||||
{
|
||||
$userInviteDTO = $this->request->post();
|
||||
// 验证用户ID不能为空
|
||||
if (empty($userInviteDTO['userId'])) {
|
||||
$this->error('用户id不能为空');
|
||||
}
|
||||
|
||||
// 验证邀请奖励金额必须大于0
|
||||
$inviteAmount = $userInviteDTO['inviteAmount'] ?? null;
|
||||
if (is_null($inviteAmount) || bccomp($inviteAmount, 0) <= 0) {
|
||||
$this->error('邀请奖励金额必须大于0');
|
||||
}
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userInviteDTO['userId']], true))->name('tb_user');
|
||||
// 查询用户是否存在
|
||||
$userEntity = $db->where(['user_id' => $userInviteDTO['userId']])->find($userInviteDTO['userId']);
|
||||
if (is_null($userEntity)) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
// 更新用户邀请奖励金额
|
||||
$db->where(['user_id' => $userInviteDTO['userId']])->update(['invite_amount' => $inviteAmount]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
public function updatePwd()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['userId']) || empty($get['pwd'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
$userId = $get['userId'];
|
||||
$pwd = $get['pwd'];
|
||||
$db = Db::connect(DatabaseRoute::getConnection('sys_user', ['user_id' => $userId]));
|
||||
$user = $db->name('sys_user')->where(['user_id' => $userId])->find();
|
||||
if(!$user) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
$db = Db::connect(DatabaseRoute::getConnection('sys_user', ['user_id' => $userId], true));
|
||||
$user = $db->name('sys_user')->where(['user_id' => $userId])->update(['password' => shiro_simple_hash_hex_salt('sha256', $pwd, $user['salt'])]);
|
||||
if($user) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error();
|
||||
}
|
||||
|
||||
public function deleteUserByUserId()
|
||||
{
|
||||
$post = $this->request->post();
|
||||
if(empty($post['userId'])) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
$userId = $post['userId'];
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId], true));
|
||||
$user = $db->name('tb_user')->where(['user_id' => $userId])->delete();
|
||||
if($user) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error('操作失败');
|
||||
}
|
||||
|
||||
|
||||
public function getuserinfo()
|
||||
{
|
||||
$userId = $this->request->get('userId');
|
||||
if(empty($userId)) {
|
||||
$this->error('userId 不能为空');
|
||||
}
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId]));
|
||||
$user = $db->name('tb_user')->where(['user_id' => $userId])->find();
|
||||
if(!$user) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
|
||||
$inviteMoney = \app\admin\model\User::selectInviteMoneyByUserId($userId, $db);
|
||||
if(empty($inviteMoney)) {
|
||||
$inviteMoney = [
|
||||
'user_id' => $userId,
|
||||
'money_sum' => 0.00,
|
||||
'money' => 0.00,
|
||||
'cash_out' => 0.00,
|
||||
];
|
||||
Db::connect(DatabaseRoute::getConnection('invite_money', ['user_id' => $userId], true), true)->name('invite_money')->insert($inviteMoney);
|
||||
}
|
||||
$money = $inviteMoney['money'];
|
||||
|
||||
// 获取当前日期(格式:YYYY-MM-DD HH:mm:ss)
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
// 查询本月充值(复用之前的instantselectSumPay方法)
|
||||
$consume = \app\admin\model\User::instantselectSumPay(date('Y-m'), $userId, $db);
|
||||
|
||||
// 查询本月提现(假设monthIncome方法已实现)
|
||||
$income = \app\admin\model\User::monthIncome(date('Y-m'), $userId, $db);
|
||||
|
||||
// 查询邀请人数(复用之前的countUsersByInviterCode方法)
|
||||
$count = \app\admin\model\User::queryInviterCount($user['invitation_code']);
|
||||
|
||||
// 查询VIP信息
|
||||
$userVip = \app\admin\model\User::selectUserVipByUserId($userId);
|
||||
if ($userVip) {
|
||||
$user['member'] = $userVip['is_vip'];
|
||||
$user['end_time'] = $userVip['end_time'];
|
||||
$user['vip_type'] = $userVip['vip_type'];
|
||||
}
|
||||
|
||||
// 组装结果数据
|
||||
$resultData = [
|
||||
'userEntity' => $user,
|
||||
'money' => $money,
|
||||
'consume' => $consume,
|
||||
'income' => $income,
|
||||
'count' => $count
|
||||
];
|
||||
$this->n_success(['data' => $resultData]);
|
||||
|
||||
}
|
||||
|
||||
public function userListExcel()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$startTime = $get['startTime'] ?? null;
|
||||
$endTime = $get['endTime'] ?? null;
|
||||
$this->n_success(\app\admin\model\User::userListExcel($startTime, $endTime));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取用户详细信息
|
||||
public function selectUserByInvitationCode()
|
||||
{
|
||||
$get = $this->request->get();
|
||||
if(empty($get['invitationCode'])) {
|
||||
$this->error('参数不完整');
|
||||
}
|
||||
$invitationCode = $get['invitationCode'];
|
||||
$userEntity = TbUser::GetByusername($invitationCode, 'invitation_code');
|
||||
if(empty($userEntity)) {
|
||||
$this->error('用户信息不存在');
|
||||
}
|
||||
$userId = $userEntity['user_id'];
|
||||
|
||||
$db = Db::connect(DatabaseRoute::getConnection('invite_money', ['user_id' => $userId]));
|
||||
// 查询用户钱包
|
||||
$inviteMoney = \app\admin\model\User::selectInviteMoneyByUserId($userId, $db);
|
||||
$money = $inviteMoney['money'];
|
||||
// 获取当前时间(格式:Y-m-d H:i:s)
|
||||
$currentDate = date('Y-m-d H:i:s');
|
||||
// 查询本月充值总额
|
||||
$consume = \app\admin\model\User::instantselectSumPay($currentDate, $userId, $db);
|
||||
$income = \app\admin\model\User::monthIncome($currentDate, $userId, $db);
|
||||
//查询邀请人数
|
||||
$count = \app\admin\model\User::queryInviterCount($userEntity['invitation_code']);
|
||||
$userVip = \app\admin\model\User::selectUserVipByUserId($userId);
|
||||
if ($userVip) {
|
||||
$userEntity['member'] = $userVip['is_vip'];
|
||||
$userEntity['end_time'] = $userVip['end_time'];
|
||||
$userEntity['vip_type'] = $userVip['vip_type'];
|
||||
}
|
||||
$data = [
|
||||
'userEntity' => $userEntity,
|
||||
'money' => $money,
|
||||
'consume' => $consume,
|
||||
'income' => $income,
|
||||
'count' => $count
|
||||
];
|
||||
$this->n_success(['data' => $data]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1430,3 +1430,16 @@ function convertUserIdToString(array $data): array {
|
||||
|
||||
return $result;
|
||||
}
|
||||
function convertKeysCamelToSnakeRecursive(array $array): array
|
||||
{
|
||||
$converted = [];
|
||||
foreach ($array as $key => $value) {
|
||||
$newKey = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $key));
|
||||
if (is_array($value)) {
|
||||
$converted[$newKey] = convertKeysCamelToSnakeRecursive($value);
|
||||
} else {
|
||||
$converted[$newKey] = $value;
|
||||
}
|
||||
}
|
||||
return $converted;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user