add
This commit is contained in:
parent
30abda5ba7
commit
281248fd04
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
use ba\Filesystem;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
if (!function_exists('get_controller_list')) {
|
||||
function get_controller_list($app = 'admin'): array
|
||||
{
|
||||
$controllerDir = root_path() . 'app' . DIRECTORY_SEPARATOR . $app . DIRECTORY_SEPARATOR . 'controller' . DIRECTORY_SEPARATOR;
|
||||
return Filesystem::getDirFiles($controllerDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('get_ba_client')) {
|
||||
/**
|
||||
* 获取一个请求 BuildAdmin 开源社区的 Client
|
||||
* @throws Throwable
|
||||
*/
|
||||
function get_ba_client(): Client
|
||||
{
|
||||
return new Client([
|
||||
'base_uri' => config('buildadmin.api_url'),
|
||||
'timeout' => 30,
|
||||
'connect_timeout' => 30,
|
||||
'verify' => false,
|
||||
'http_errors' => false,
|
||||
'headers' => [
|
||||
'X-REQUESTED-WITH' => 'XMLHttpRequest',
|
||||
'Referer' => dirname(request()->root(true)),
|
||||
'User-Agent' => 'BuildAdminClient',
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 Ajax 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 Alioss 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Announcement extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Appinfo 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Banner extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
|
||||
public function selectBannerPage()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 Cash extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
protected array $noNeedPermission = ['statisticsIncomeMoney', 'statisticsCashMoney'];
|
||||
public function selectUserRechargeByUserId()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$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('提现成功,将在三个工作日内到账,请耐心等待!');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\facade\Token;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\utils\WuYouPayUtils;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
use think\Collection;
|
||||
|
||||
class CashOutAudit 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Common 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 CompletAward 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class Course 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseClassification 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseCollect 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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class CourseDetails 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class Dashboard extends Backend
|
||||
{
|
||||
public function initialize(): void
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
public function index(): void
|
||||
{
|
||||
$this->success('', [
|
||||
'remark' => get_route_remark()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class DiscSpinning 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Db;
|
||||
|
||||
class DiscSpinningAmount 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\api\model\CommonInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class ExtSys 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SysCaptcha;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class HelpWord 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,
|
||||
]]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SysCaptcha;
|
||||
class Indetcode extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function getCode()
|
||||
{
|
||||
$data = $this->request->get();
|
||||
if(empty($data['uuid']))$this->error('参数不完整');
|
||||
$this->success('ok', SysCaptcha::getCode($data['uuid']));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\admin\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 Index 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Exception;
|
||||
use think\facade\Db;
|
||||
|
||||
class Integral 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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Invite 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'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class InviteAward 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 Login extends Frontend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
// 发送验证码
|
||||
public function sendMsg($phone, $event)
|
||||
{
|
||||
$get = $this->request->get();
|
||||
return $this->ApiDataReturn(Msg::sendMsg($get['phone'], $get['event']));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\MessageInfo;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Message 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->param();
|
||||
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)]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 Module 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
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 MoneyDetails 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'])]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,498 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\api\model\TbUser;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use ba\Exception;
|
||||
|
||||
class Order 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->param();
|
||||
$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]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class PayClassify 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\UserIntegral;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Sdk 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,
|
||||
]]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\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 Sys 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']));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class TaskCenter 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class TaskCenterReward 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use think\facade\Db;
|
||||
|
||||
class UrlAddress 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class UserInfo extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
public function list()
|
||||
{
|
||||
$params = $this->request->param();
|
||||
$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 = $this->request->put();
|
||||
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->delete();
|
||||
if (empty($params['userId'])) {
|
||||
$this->error('参数错误');
|
||||
}
|
||||
DatabaseRoute::getDb('user_info', $params['userId'], true, true)->delete();
|
||||
$this->success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class UserPrizeExchange 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();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SysCaptcha;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class VipDetails 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('成功');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\auth;
|
||||
|
||||
use Throwable;
|
||||
use think\facade\Db;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\Admin as AdminModel;
|
||||
|
||||
class Admin 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!'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\auth;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\AdminLog as AdminLogModel;
|
||||
|
||||
class AdminLog 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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,379 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\auth;
|
||||
|
||||
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 Group 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~'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\auth;
|
||||
|
||||
use ba\Tree;
|
||||
use Throwable;
|
||||
use app\admin\model\AdminRule;
|
||||
use app\admin\model\AdminGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class Rule 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,992 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\crud;
|
||||
|
||||
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 Crud 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\crud;
|
||||
|
||||
use app\admin\model\CrudLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
/**
|
||||
* crud记录
|
||||
*
|
||||
*/
|
||||
class Log 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\routine;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\Admin;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class AdminInfo 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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\routine;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\model\Attachment as AttachmentModel;
|
||||
|
||||
class Attachment 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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\routine;
|
||||
|
||||
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 Config 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~'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\security;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\DataRecycle as DataRecycleModel;
|
||||
|
||||
class DataRecycle 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\security;
|
||||
|
||||
use Throwable;
|
||||
use ba\TableManager;
|
||||
use think\facade\Db;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\DataRecycleLog as DataRecycleLogModel;
|
||||
|
||||
class DataRecycleLog 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\security;
|
||||
|
||||
use Throwable;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SensitiveData as SensitiveDataModel;
|
||||
|
||||
class SensitiveData 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\security;
|
||||
|
||||
use Throwable;
|
||||
use ba\TableManager;
|
||||
use think\facade\Db;
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\SensitiveDataLog as SensitiveDataLogModel;
|
||||
|
||||
class SensitiveDataLog 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'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\sys;
|
||||
|
||||
use app\admin\model\SysMenu;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Config extends Backend
|
||||
{
|
||||
|
||||
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,
|
||||
]]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\sys;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Log 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');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\sys;
|
||||
|
||||
use app\admin\model\SysMenu;
|
||||
use app\common\controller\Backend;
|
||||
use think\facade\Db;
|
||||
|
||||
class Menu extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
// 菜单列表
|
||||
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->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('操作失败');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\sys;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Oss 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\sys;
|
||||
|
||||
use app\admin\model\SysMenu;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use think\facade\Db;
|
||||
|
||||
class Role extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
public function list()
|
||||
{
|
||||
$prams = $this->request->param();
|
||||
$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')->insert([
|
||||
'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]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\sys;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\InvitationCodeUtil;
|
||||
use ba\Random;
|
||||
use think\facade\Db;
|
||||
|
||||
class User extends Backend
|
||||
{
|
||||
protected array $noNeedLogin = ['*'];
|
||||
|
||||
// 用户信息
|
||||
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->param();
|
||||
$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->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->param();
|
||||
$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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\UserRule;
|
||||
use app\admin\model\UserGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class Group 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\User;
|
||||
use app\admin\model\UserMoneyLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class MoneyLog 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
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use ba\Tree;
|
||||
use Throwable;
|
||||
use app\admin\model\UserRule;
|
||||
use app\admin\model\UserGroup;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class Rule 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
use Throwable;
|
||||
use app\admin\model\User;
|
||||
use app\admin\model\UserScoreLog;
|
||||
use app\common\controller\Backend;
|
||||
|
||||
class ScoreLog 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
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,542 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\controller\user;
|
||||
|
||||
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 User 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
|
||||
{
|
||||
parent::initialize();
|
||||
// $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]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
// 事件定义文件
|
||||
return [
|
||||
'bind' => [
|
||||
],
|
||||
'listen' => [
|
||||
'AppInit' => [],
|
||||
'HttpRun' => [],
|
||||
'HttpEnd' => [],
|
||||
'LogLevel' => [],
|
||||
'LogWrite' => [],
|
||||
'backendInit' => [app\common\event\Security::class],
|
||||
],
|
||||
'subscribe' => [
|
||||
],
|
||||
];
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
return [
|
||||
'Please login first' => 'Please login first',
|
||||
'You have no permission' => 'You have no permission to operate',
|
||||
'Username' => 'Username',
|
||||
'Password' => 'Password',
|
||||
'Nickname' => 'Nickname',
|
||||
'Email' => 'Email',
|
||||
'Mobile' => 'Mobile Number',
|
||||
'Captcha' => 'Captcha',
|
||||
'CaptchaId' => 'Captcha Id',
|
||||
'Please enter the correct verification code' => 'Please enter the correct Captcha!',
|
||||
'Captcha error' => 'Captcha error!',
|
||||
'Parameter %s can not be empty' => 'Parameter %s can not be empty',
|
||||
'Record not found' => 'Record not found',
|
||||
'No rows were added' => 'No rows were added',
|
||||
'No rows were deleted' => 'No rows were deleted',
|
||||
'No rows updated' => 'No rows updated',
|
||||
'Update successful' => 'Update successful!',
|
||||
'Added successfully' => 'Added successfully!',
|
||||
'Deleted successfully' => 'Deleted successfully!',
|
||||
'Parameter error' => 'Parameter error!',
|
||||
'File uploaded successfully' => 'File uploaded successfully',
|
||||
'No files were uploaded' => 'No files were uploaded',
|
||||
'The uploaded file format is not allowed' => 'The uploaded file format is no allowance.',
|
||||
'The uploaded image file is not a valid image' => 'The uploaded image file is not a valid image',
|
||||
'The uploaded file is too large (%sMiB), Maximum file size:%sMiB' => 'The uploaded file is too large (%sMiB), maximum file size:%sMiB',
|
||||
'No files have been uploaded or the file size exceeds the upload limit of the server' => 'No files have been uploaded or the file size exceeds the server upload limit.',
|
||||
'Unknown' => 'Unknown',
|
||||
'Account not exist' => 'Account does not exist',
|
||||
'Account disabled' => 'Account is disabled',
|
||||
'Token login failed' => 'Token login failed',
|
||||
'Username is incorrect' => 'Incorrect username',
|
||||
'Please try again after 1 day' => 'The number of login failures exceeds the limit, please try again after 24 hours',
|
||||
'Password is incorrect' => 'Wrong password',
|
||||
'You are not logged in' => 'You are not logged in',
|
||||
'Cache cleaned~' => 'The cache has been cleaned up, please refresh the page.',
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
return [
|
||||
'Failed to switch package manager. Please modify the configuration file manually:%s' => 'Failed to switch package manager, please modify the configuration file manually:%s',
|
||||
'Failed to modify the terminal configuration. Please modify the configuration file manually:%s' => 'Failed to modify the terminal configuration, please modify the configuration file manually:%s',
|
||||
'upload' => 'Upload files',
|
||||
'Change terminal config' => 'Modify terminal configuration',
|
||||
'Clear cache' => 'Clear cache',
|
||||
'Data table does not exist' => 'Data table does not exist',
|
||||
];
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
return [
|
||||
'Group Name Arr' => 'Administrator Grouping ',
|
||||
'Please use another administrator account to disable the current account!' => 'Disable the current account, please use another administrator account!',
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'Super administrator' => 'Super administrator',
|
||||
'No permission' => 'No permission',
|
||||
'You cannot modify your own management group!' => 'You cannot modify your own management group!',
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'type' => 'Rule type',
|
||||
'title' => 'Rule title',
|
||||
'name' => 'Rule name',
|
||||
];
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
return [
|
||||
'change-field-name fail not exist' => 'Field %s failed to be renamed because the field does not exist in the data table',
|
||||
'del-field fail not exist' => 'Failed to delete field %s because the field does not exist in the data table',
|
||||
'change-field-attr fail not exist' => 'Description Failed to modify the properties of field %s because the field does not exist in the data table',
|
||||
'add-field fail exist' => 'Failed to add field %s because the field already exists in the data table',
|
||||
];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'Remark lang' => "Open source equals mutual assistance, and needs everyone's support. There are many ways to support it, such as using, recommending, writing tutorials, protecting the ecology, contributing code, answering questions, sharing experiences, donation, sponsorship and so on. Welcome to join us!",
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
return [
|
||||
'No background menu, please contact super administrator!' => 'No background menu, please contact the super administrator!',
|
||||
'You have already logged in. There is no need to log in again~' => 'You have already logged in, no need to log in again.',
|
||||
'Login succeeded!' => 'Login successful!',
|
||||
'Incorrect user name or password!' => 'Incorrect username or password!',
|
||||
'Login' => 'Login',
|
||||
'Logout' => 'Logout',
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'Please input correct username' => 'Please enter the correct username',
|
||||
'Please input correct password' => 'Please enter the correct password',
|
||||
'Avatar modified successfully!' => 'Profile picture modified successfully!',
|
||||
];
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
return [
|
||||
'%d records and files have been deleted' => '%d records and files have been deleted',
|
||||
'remark_text' => 'When the same file is uploaded multiple times, only one copy will be saved to the disk and an attachment record will be added; Deleting an attachment record will automatically delete the corresponding file!',
|
||||
];
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
return [
|
||||
'Basics' => 'Basic configuration',
|
||||
'Mail' => 'Mail configuration',
|
||||
'Config group' => 'Configure grouping',
|
||||
'Site Name' => 'Site name',
|
||||
'Config Quick entrance' => 'Quick configuration entrance',
|
||||
'Record number' => 'Record Number',
|
||||
'Version number' => 'Version Number',
|
||||
'time zone' => 'Time zone',
|
||||
'No access ip' => 'No access IP',
|
||||
'smtp server' => 'SMTP server',
|
||||
'smtp port' => 'SMTP port',
|
||||
'smtp user' => 'SMTP username',
|
||||
'smtp pass' => 'SMTP password',
|
||||
'smtp verification' => 'SMTP verification mode',
|
||||
'smtp sender mail' => 'SMTP sender mailbox',
|
||||
'Variable name' => 'variable name',
|
||||
'Test mail sent successfully~' => 'Test message sent successfully',
|
||||
'This is a test email' => 'This is a test email',
|
||||
'Congratulations, receiving this email means that your email service has been configured correctly' => "Congratulations, when you receive this email, it means that your mail service is configures correctly. This is the email subject, <b>you can use HtmlL!</b> in the main body.",
|
||||
'Backend entrance rule' => 'The background entry must start with / and contain only numbers and letters.',
|
||||
];
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
return [
|
||||
'Name' => 'Rule Name',
|
||||
'Controller' => 'Controller',
|
||||
'Data Table' => 'Corresponding data table',
|
||||
'Primary Key' => 'Data table primary key',
|
||||
];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'No rows were restore' => 'No records have been restored',
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
return [
|
||||
'Name' => 'Rule name',
|
||||
'Controller' => 'Controller',
|
||||
'Data Table' => 'Corresponding data table',
|
||||
'Primary Key' => 'Data table primary key',
|
||||
'Data Fields' => 'Sensitive data fields',
|
||||
];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'No rows were rollback' => 'No records have been roll-back',
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
return [
|
||||
'user_id' => 'User',
|
||||
'money' => 'Change amount',
|
||||
'memo' => 'Change Notes',
|
||||
"The user can't find it" => "User does not exist",
|
||||
'Change note cannot be blank' => 'Change Notes cannot be empty',
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
return [
|
||||
'user_id' => 'User',
|
||||
'score' => 'Change points',
|
||||
'memo' => 'Change Notes',
|
||||
"The user can't find it" => 'User does not exist',
|
||||
'Change note cannot be blank' => 'Change notes cannot be empty',
|
||||
];
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
return [
|
||||
'Please login first' => '请先登录!',
|
||||
'You have no permission' => '没有权限操作!',
|
||||
'Username' => '用户名',
|
||||
'Password' => '密码',
|
||||
'Nickname' => '昵称',
|
||||
'Email' => '邮箱',
|
||||
'Mobile' => '手机号',
|
||||
'Captcha' => '验证码',
|
||||
'CaptchaId' => '验证码ID',
|
||||
'Please enter the correct verification code' => '请输入正确的验证码!',
|
||||
'Captcha error' => '验证码错误!',
|
||||
'Parameter %s can not be empty' => '参数%s不能为空',
|
||||
'Record not found' => '记录未找到',
|
||||
'No rows were added' => '未添加任何行',
|
||||
'No rows were deleted' => '未删除任何行',
|
||||
'No rows updated' => '未更新任何行',
|
||||
'Update successful' => '更新成功!',
|
||||
'Added successfully' => '添加成功!',
|
||||
'Deleted successfully' => '删除成功!',
|
||||
'Parameter error' => '参数错误!',
|
||||
'Please use the %s field to sort before operating' => '请使用 %s 字段排序后再操作',
|
||||
'File uploaded successfully' => '文件上传成功!',
|
||||
'No files were uploaded' => '没有文件被上传',
|
||||
'The uploaded file format is not allowed' => '上传的文件格式未被允许',
|
||||
'The uploaded image file is not a valid image' => '上传的图片文件不是有效的图像',
|
||||
'The uploaded file is too large (%sMiB), Maximum file size:%sMiB' => '上传的文件太大(%sM),最大文件大小:%sM',
|
||||
'No files have been uploaded or the file size exceeds the upload limit of the server' => '没有文件被上传或文件大小超出服务器上传限制!',
|
||||
'Topic format error' => '上传存储子目录格式错误!',
|
||||
'Driver %s not supported' => '不支持的驱动:%s',
|
||||
'Unknown' => '未知',
|
||||
// 权限类语言包-s
|
||||
'Account not exist' => '帐户不存在',
|
||||
'Account disabled' => '帐户已禁用',
|
||||
'Token login failed' => '令牌登录失败',
|
||||
'Username is incorrect' => '用户名不正确',
|
||||
'Please try again after 1 day' => '登录失败次数超限,请在1天后再试',
|
||||
'Password is incorrect' => '密码不正确',
|
||||
'You are not logged in' => '你没有登录',
|
||||
// 权限类语言包-e
|
||||
// 时间格式化-s
|
||||
'%d second%s ago' => '%d秒前',
|
||||
'%d minute%s ago' => '%d分钟前',
|
||||
'%d hour%s ago' => '%d小时前',
|
||||
'%d day%s ago' => '%d天前',
|
||||
'%d week%s ago' => '%d周前',
|
||||
'%d month%s ago' => '%d月前',
|
||||
'%d year%s ago' => '%d年前',
|
||||
'%d second%s after' => '%d秒后',
|
||||
'%d minute%s after' => '%d分钟后',
|
||||
'%d hour%s after' => '%d小时后',
|
||||
'%d day%s after' => '%d天后',
|
||||
'%d week%s after' => '%d周后',
|
||||
'%d month%s after' => '%d月后',
|
||||
'%d year%s after' => '%d年后',
|
||||
// 时间格式化-e
|
||||
'Cache cleaned~' => '缓存已清理,请刷新后台~',
|
||||
'Please delete the child element first, or use batch deletion' => '请首先删除子元素,或使用批量删除!',
|
||||
'Configuration write failed: %s' => '配置写入失败:%s',
|
||||
'Token expiration' => '登录态过期,请重新登录!',
|
||||
];
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
return [
|
||||
'Start the database migration' => '开始进行数据库迁移',
|
||||
'Start formatting the web project code' => '开始格式化前端代码(失败无影响,代码编辑器内按需的手动格式化即可)',
|
||||
'Start installing the composer dependencies' => '开始安装服务端依赖',
|
||||
'Start executing the build command of the web project' => '开始执行 web 工程的 build 命令,成功后会自动将构建产物移动至 根目录/public 目录下',
|
||||
'Failed to modify the terminal configuration. Please modify the configuration file manually:%s' => '修改终端配置失败,请手动修改配置文件:%s',
|
||||
'upload' => '上传文件',
|
||||
'Change terminal config' => '修改终端配置',
|
||||
'Clear cache' => '清理缓存',
|
||||
'Data table does not exist' => '数据表不存在~',
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'Group Name Arr' => '管理员分组',
|
||||
'Please use another administrator account to disable the current account!' => '请使用另外的管理员账户禁用当前账户!',
|
||||
'You have no permission to add an administrator to this group!' => '您没有权限向此分组添加管理员!',
|
||||
];
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
return [
|
||||
'name' => '组别名称',
|
||||
'Please select rules' => '请选择权限',
|
||||
'Super administrator' => '超级管理员',
|
||||
'No permission' => '无权限',
|
||||
'You cannot modify your own management group!' => '不能修改自己所在的管理组!',
|
||||
'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~' => '您需要拥有该分组的所有权限且还有额外权限时,才可以操作该分组~',
|
||||
'Role group has all your rights, please contact the upper administrator to add or do not need to add!' => '角色组拥有您的全部权限,请联系上级管理员添加或无需添加!',
|
||||
'The group permission node exceeds the range that can be allocated' => '分组权限节点超出可分配范围,请刷新重试~',
|
||||
'Remark lang' => '为保障系统安全,角色组本身的上下级关系仅供参考,系统的实际上下级划分是根据`权限多寡`来确定的,两位管理员的权限节点:相同被认为是`同级`、包含且有额外权限才被认为是`上级`,同级不可管理同级,上级可为下级分配自己拥有的权限节点;若有特殊情况管理员需转`上级`,可建立一个虚拟权限节点',
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'type' => '规则类型',
|
||||
'title' => '规则标题',
|
||||
'name' => '规则名称',
|
||||
];
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
return [
|
||||
'Parse field data' => 'CRUD代码生成-解析字段数据',
|
||||
'Log start' => 'CRUD代码生成-从历史记录开始',
|
||||
'Generate check' => 'CRUD代码生成-生成前预检',
|
||||
'change-field-name fail not exist' => '字段 %s 改名失败,数据表内不存在该字段',
|
||||
'del-field fail not exist' => '字段 %s 删除失败,数据表内不存在该字段',
|
||||
'change-field-attr fail not exist' => '修改字段 %s 的属性失败,数据表内不存在该字段',
|
||||
'add-field fail exist' => '添加字段 %s 失败,数据表内已经存在该字段',
|
||||
'Failed to load cloud data' => '加载云端数据失败,请稍后重试!',
|
||||
];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'Remark lang' => '开源等于互助;开源需要大家一起来支持,支持的方式有很多种,比如使用、推荐、写教程、保护生态、贡献代码、回答问题、分享经验、打赏赞助等;欢迎您加入我们!',
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
return [
|
||||
'No background menu, please contact super administrator!' => '无后台菜单,请联系超级管理员!',
|
||||
'You have already logged in. There is no need to log in again~' => '您已经登录过了,无需重复登录~',
|
||||
'Login succeeded!' => '登录成功!',
|
||||
'Incorrect user name or password!' => '用户名或密码不正确!',
|
||||
'Login' => '登录',
|
||||
'Logout' => '注销登录',
|
||||
];
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
return [
|
||||
'Order not found' => '订单找不到啦!',
|
||||
'Module already exists' => '模块已存在!',
|
||||
'package download failed' => '包下载失败!',
|
||||
'package check failed' => '包检查失败!',
|
||||
'No permission to write temporary files' => '没有权限写入临时文件!',
|
||||
'Zip file not found' => '找不到压缩包文件',
|
||||
'Unable to open the zip file' => '无法打开压缩包文件',
|
||||
'Unable to extract ZIP file' => '无法提取ZIP文件',
|
||||
'Unable to package zip file' => '无法打包zip文件',
|
||||
'Basic configuration of the Module is incomplete' => '模块基础配置不完整',
|
||||
'Module package file does not exist' => '模块包文件不存在',
|
||||
'Module file conflicts' => '模块文件存在冲突,请手动处理!',
|
||||
'Configuration file has no write permission' => '配置文件无写入权限',
|
||||
'The current state of the module cannot be set to disabled' => '模块当前状态无法设定为禁用',
|
||||
'The current state of the module cannot be set to enabled' => '模块当前状态无法设定为启用',
|
||||
'Module file updated' => '模块文件有更新',
|
||||
'Please disable the module first' => '请先禁用模块',
|
||||
'Please disable the module before updating' => '更新前请先禁用模块',
|
||||
'The directory required by the module is occupied' => '模块所需目录已被占用',
|
||||
'Install module' => '安装模块',
|
||||
'Unload module' => '卸载模块',
|
||||
'Update module' => '更新模块',
|
||||
'Change module state' => '改变模块状态',
|
||||
'Upload install module' => '上传安装模块',
|
||||
'Please login to the official website account first' => '请先使用BuildAdmin官网账户登录到模块市场~',
|
||||
'composer config %s conflict' => 'composer 配置项 %s 存在冲突',
|
||||
];
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
return [
|
||||
'Please input correct username' => '请输入正确的用户名',
|
||||
'Please input correct password' => '请输入正确的密码',
|
||||
'Avatar modified successfully!' => '头像修改成功!',
|
||||
];
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
return [
|
||||
'Remark lang' => '同一文件被多次上传时,只会保存一份至磁盘和增加一条附件记录;删除附件记录,将自动删除对应文件!',
|
||||
'%d records and files have been deleted' => '删除了%d条记录和文件',
|
||||
];
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
return [
|
||||
'Basics' => '基础配置',
|
||||
'Mail' => '邮件配置',
|
||||
'Config group' => '配置分组',
|
||||
'Site Name' => '站点名称',
|
||||
'Backend entrance' => '自定义后台入口',
|
||||
'Config Quick entrance' => '快捷配置入口',
|
||||
'Record number' => '备案号',
|
||||
'Version number' => '版本号',
|
||||
'time zone' => '时区',
|
||||
'No access ip' => '禁止访问IP',
|
||||
'smtp server' => 'SMTP 服务器',
|
||||
'smtp port' => 'SMTP 端口',
|
||||
'smtp user' => 'SMTP 用户名',
|
||||
'smtp pass' => 'SMTP 密码',
|
||||
'smtp verification' => 'SMTP 验证方式',
|
||||
'smtp sender mail' => 'SMTP 发件人邮箱',
|
||||
'Variable name' => '变量名',
|
||||
'Test mail sent successfully~' => '测试邮件发送成功~',
|
||||
'This is a test email' => '这是一封测试邮件',
|
||||
'Congratulations, receiving this email means that your email service has been configured correctly' => '恭喜您,收到此邮件代表您的邮件服务已配置正确;这是邮件主体 <b>在主体中可以使用Html!</b>',
|
||||
'The current page configuration item was updated successfully' => '当前页配置项更新成功!',
|
||||
'Backend entrance rule' => '后台入口请以 / 开头,且只包含数字和字母。',
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
return [
|
||||
'Name' => '规则名称',
|
||||
'Controller' => '控制器',
|
||||
'Data Table' => '对应数据表',
|
||||
'Primary Key' => '数据表主键',
|
||||
'Remark lang' => '在此定义需要回收的数据,实现数据自动统一回收',
|
||||
];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'No rows were restore' => '没有记录被还原',
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
return [
|
||||
'Name' => '规则名称',
|
||||
'Controller' => '控制器',
|
||||
'Data Table' => '对应数据表',
|
||||
'Primary Key' => '数据表主键',
|
||||
'Data Fields' => '敏感数据字段',
|
||||
'Remark lang' => '在此定义需要保护的敏感字段,随后系统将自动监听该字段的修改操作,并提供了敏感字段的修改回滚功能',
|
||||
];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
return [
|
||||
'No rows were rollback' => '没有记录被回滚',
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
return [
|
||||
'user_id' => '用户',
|
||||
'money' => '变更金额',
|
||||
'memo' => '变更备注',
|
||||
"The user can't find it" => '用户找不到啦',
|
||||
'Change note cannot be blank' => '变更备注不能为空',
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
return [
|
||||
'user_id' => '用户',
|
||||
'score' => '变更积分',
|
||||
'memo' => '变更备注',
|
||||
"The user can't find it" => '用户找不到啦',
|
||||
'Change note cannot be blank' => '变更备注不能为空',
|
||||
];
|
||||
|
|
@ -0,0 +1,517 @@
|
|||
<?php
|
||||
|
||||
namespace app\admin\library;
|
||||
|
||||
|
||||
use app\common\library\DatabaseRoute;
|
||||
use app\common\model\SysUser;
|
||||
use app\utils\JwtUtils;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 管理员权限类
|
||||
* @property int $id 管理员ID
|
||||
* @property string $username 管理员用户名
|
||||
* @property string $nickname 管理员昵称
|
||||
* @property string $email 管理员邮箱
|
||||
* @property string $mobile 管理员手机号
|
||||
*/
|
||||
class Auth extends \ba\Auth
|
||||
{
|
||||
/**
|
||||
* 需要登录时/无需登录时的响应状态代码
|
||||
*/
|
||||
public const LOGIN_RESPONSE_CODE = 303;
|
||||
|
||||
/**
|
||||
* 需要登录标记 - 前台应清理 token、记录当前路由 path、跳转到登录页
|
||||
*/
|
||||
public const NEED_LOGIN = 'need login';
|
||||
|
||||
/**
|
||||
* 已经登录标记 - 前台应跳转到基础路由
|
||||
*/
|
||||
public const LOGGED_IN = 'logged in';
|
||||
|
||||
/**
|
||||
* token 入库 type
|
||||
*/
|
||||
public const TOKEN_TYPE = 'admin';
|
||||
|
||||
/**
|
||||
* 是否登录
|
||||
* @var bool
|
||||
*/
|
||||
protected bool $loginEd = false;
|
||||
|
||||
/**
|
||||
* 错误消息
|
||||
* @var string
|
||||
*/
|
||||
protected string $error = '';
|
||||
|
||||
/**
|
||||
* Model实例
|
||||
* @var ?Admin
|
||||
*/
|
||||
protected $model = null;
|
||||
|
||||
|
||||
protected $user_id_slave_connect_db;
|
||||
|
||||
/**
|
||||
* 令牌
|
||||
* @var string
|
||||
*/
|
||||
protected string $token = '';
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
* @var string
|
||||
*/
|
||||
protected string $refreshToken = '';
|
||||
|
||||
/**
|
||||
* 令牌默认有效期
|
||||
* 可在 config/buildadmin.php 内修改默认值
|
||||
* @var int
|
||||
*/
|
||||
protected int $keepTime = 86400;
|
||||
|
||||
/**
|
||||
* 刷新令牌有效期
|
||||
* @var int
|
||||
*/
|
||||
protected int $refreshTokenKeepTime = 2592000;
|
||||
|
||||
/**
|
||||
* 允许输出的字段
|
||||
* @var array
|
||||
*/
|
||||
protected array $allowFields = ['id', 'username', 'nickname', 'avatar', 'last_login_time'];
|
||||
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
parent::__construct($config);
|
||||
$this->setKeepTime((int)Config::get('buildadmin.admin_token_keep_time'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 魔术方法-管理员信息字段
|
||||
* @param $name
|
||||
* @return mixed 字段信息
|
||||
*/
|
||||
public function __get($name): mixed
|
||||
{
|
||||
return $this->model[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @access public
|
||||
* @param array $options 传递到 /ba/Auth 的配置信息
|
||||
* @return Auth
|
||||
*/
|
||||
public static function instance(array $options = []): Auth
|
||||
{
|
||||
$request = request();
|
||||
if (!isset($request->adminAuth)) {
|
||||
$request->adminAuth = new static($options);
|
||||
}
|
||||
return $request->adminAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Token初始化管理员登录态
|
||||
* @param string $token
|
||||
* @return bool
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function init(string $token): bool
|
||||
{
|
||||
// $tokenData = Token::get($token);
|
||||
$jwtUtil = (new JwtUtils());
|
||||
|
||||
$tokenData = $jwtUtil->getClaimByToken($token);
|
||||
|
||||
if ($tokenData) {
|
||||
/**
|
||||
* 过期检查,过期则抛出 @see TokenExpirationException
|
||||
*/
|
||||
// Token::tokenExpirationCheck($tokenData);
|
||||
|
||||
// $userId = intval($tokenData['user_id']);
|
||||
$userId = $tokenData->sub;
|
||||
if (!isset($tokenData->type) || ($tokenData->type == self::TOKEN_TYPE && $userId > 0)) {
|
||||
$this->user_id_slave_connect_db = Db::connect(DatabaseRoute::getConnection('sys_user', ['user_id' => $userId]));
|
||||
$this->model = $this->user_id_slave_connect_db->name('sys_user')->where('user_id', $userId)->find();
|
||||
if (!$this->model) {
|
||||
$this->setError('Account not exist');
|
||||
return false;
|
||||
}
|
||||
if ($this->model['status'] != '1') {
|
||||
$this->setError('Account disabled');
|
||||
return false;
|
||||
}
|
||||
$this->token = $token;
|
||||
$this->loginSuccessful();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$this->setError('Token login failed');
|
||||
$this->reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员登录
|
||||
* @param string $username 用户名
|
||||
* @param string $password 密码
|
||||
* @param bool $keep 是否保持登录
|
||||
* @return bool
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function login(string $username, string $password, bool $keep = false): bool
|
||||
{
|
||||
|
||||
$this->model = SysUser::GetByusername($username);
|
||||
if (!$this->model) {
|
||||
$this->setError('未注册, 请先注册');
|
||||
return false;
|
||||
}
|
||||
if ($this->model['status'] != 1) {
|
||||
$this->setError('账号已被禁用,请联系客服处理!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(empty($this->model['password'])) {
|
||||
$this->setError('当前账号未绑定密码,请前往忘记密码中进行重置!');
|
||||
return false;
|
||||
}
|
||||
$pwd = shiro_simple_hash_hex_salt('sha256', $password, $this->model['salt']);
|
||||
// 验证密码
|
||||
if($pwd == $this->model['password']) {
|
||||
$this->loginSuccessful();
|
||||
return true;
|
||||
}else {
|
||||
$this->setError('账号或密码不正确!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置刷新Token
|
||||
* @param int $keepTime
|
||||
*/
|
||||
public function setRefreshToken(int $keepTime = 0): void
|
||||
{
|
||||
$this->refreshToken = Random::uuid();
|
||||
Token::set($this->refreshToken, self::TOKEN_TYPE . '-refresh', $this->model->id, $keepTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员登录成功
|
||||
* @return bool
|
||||
*/
|
||||
public function loginSuccessful(): bool
|
||||
{
|
||||
if (!$this->model) return false;
|
||||
try {
|
||||
$this->loginEd = true;
|
||||
if (!$this->token) {
|
||||
// $this->token = Random::uuid();
|
||||
$this->token = (new JwtUtils())->generateToken($this->model['user_id'], 'admin');
|
||||
// Token::set($this->token, self::TOKEN_TYPE, $this->model['user_id'], $this->keepTime);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员登录失败
|
||||
* @return bool
|
||||
*/
|
||||
public function loginFailed(): bool
|
||||
{
|
||||
if (!$this->model) return false;
|
||||
$this->model->startTrans();
|
||||
try {
|
||||
$this->model->login_failure++;
|
||||
$this->model->last_login_time = time();
|
||||
$this->model->last_login_ip = request()->ip();
|
||||
$this->model->save();
|
||||
$this->model->commit();
|
||||
} catch (Throwable $e) {
|
||||
$this->model->rollback();
|
||||
$this->setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
return $this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* @return bool
|
||||
*/
|
||||
public function logout(): bool
|
||||
{
|
||||
if (!$this->loginEd) {
|
||||
$this->setError('You are not logged in');
|
||||
return false;
|
||||
}
|
||||
return $this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否登录
|
||||
* @return bool
|
||||
*/
|
||||
public function isLogin(): bool
|
||||
{
|
||||
return $this->loginEd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员模型
|
||||
* @return Admin
|
||||
*/
|
||||
public function getAdmin()
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员Token
|
||||
* @return string
|
||||
*/
|
||||
public function getToken(): string
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员刷新Token
|
||||
* @return string
|
||||
*/
|
||||
public function getRefreshToken(): string
|
||||
{
|
||||
return $this->refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员信息 - 只输出允许输出的字段
|
||||
* @return array
|
||||
*/
|
||||
public function getInfo(): array
|
||||
{
|
||||
if (!$this->model) return [];
|
||||
$info = $this->model->toArray();
|
||||
$info = array_intersect_key($info, array_flip($this->getAllowFields()));
|
||||
$info['token'] = $this->getToken();
|
||||
$info['refresh_token'] = $this->getRefreshToken();
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取允许输出字段
|
||||
* @return array
|
||||
*/
|
||||
public function getAllowFields(): array
|
||||
{
|
||||
return $this->allowFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置允许输出字段
|
||||
* @param $fields
|
||||
* @return void
|
||||
*/
|
||||
public function setAllowFields($fields): void
|
||||
{
|
||||
$this->allowFields = $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Token有效期
|
||||
* @param int $keepTime
|
||||
* @return void
|
||||
*/
|
||||
public function setKeepTime(int $keepTime = 0): void
|
||||
{
|
||||
$this->keepTime = $keepTime;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是超级管理员
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function isSuperAdmin(): bool
|
||||
{
|
||||
return in_array('*', $this->getRuleIds());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员所在分组的所有子级分组
|
||||
* @return array
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getAdminChildGroups(): array
|
||||
{
|
||||
$groupIds = Db::name('admin_group_access')
|
||||
->where('uid', $this->id)
|
||||
->select();
|
||||
$children = [];
|
||||
foreach ($groupIds as $group) {
|
||||
$this->getGroupChildGroups($group['group_id'], $children);
|
||||
}
|
||||
return array_unique($children);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个分组下的子分组
|
||||
* @param int $groupId 分组ID
|
||||
* @param array $children 存放子分组的变量
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getGroupChildGroups(int $groupId, array &$children): void
|
||||
{
|
||||
$childrenTemp = AdminGroup::where('pid', $groupId)
|
||||
->where('status', 1)
|
||||
->select();
|
||||
foreach ($childrenTemp as $item) {
|
||||
$children[] = $item['id'];
|
||||
$this->getGroupChildGroups($item['id'], $children);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分组内的管理员
|
||||
* @param array $groups
|
||||
* @return array 管理员数组
|
||||
*/
|
||||
public function getGroupAdmins(array $groups): array
|
||||
{
|
||||
return Db::name('admin_group_access')
|
||||
->where('group_id', 'in', $groups)
|
||||
->column('uid');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取拥有 `所有权限` 的分组
|
||||
* @param string $dataLimit 数据权限
|
||||
* @param array $groupQueryWhere 分组查询条件(默认查询启用的分组:[['status','=',1]])
|
||||
* @return array 分组数组
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function getAllAuthGroups(string $dataLimit, array $groupQueryWhere = [['status', '=', 1]]): array
|
||||
{
|
||||
// 当前管理员拥有的权限
|
||||
$rules = $this->getRuleIds();
|
||||
$allAuthGroups = [];
|
||||
$groups = AdminGroup::where($groupQueryWhere)->select();
|
||||
foreach ($groups as $group) {
|
||||
if ($group['rules'] == '*') {
|
||||
continue;
|
||||
}
|
||||
$groupRules = explode(',', $group['rules']);
|
||||
|
||||
// 及时break, array_diff 等没有 in_array 快
|
||||
$all = true;
|
||||
foreach ($groupRules as $groupRule) {
|
||||
if (!in_array($groupRule, $rules)) {
|
||||
$all = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($all) {
|
||||
if ($dataLimit == 'allAuth' || ($dataLimit == 'allAuthAndOthers' && array_diff($rules, $groupRules))) {
|
||||
$allAuthGroups[] = $group['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $allAuthGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置错误消息
|
||||
* @param $error
|
||||
* @return Auth
|
||||
*/
|
||||
public function setError($error): Auth
|
||||
{
|
||||
$this->error = $error;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误消息
|
||||
* @return string
|
||||
*/
|
||||
public function getError(): string
|
||||
{
|
||||
return $this->error ? __($this->error) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 属性重置(注销、登录失败、重新初始化等将单例数据销毁)
|
||||
*/
|
||||
protected function reset(bool $deleteToken = true): bool
|
||||
{
|
||||
if ($deleteToken && $this->token) {
|
||||
// Token::delete($this->token);
|
||||
}
|
||||
|
||||
$this->token = '';
|
||||
$this->loginEd = false;
|
||||
$this->model = null;
|
||||
$this->refreshToken = '';
|
||||
$this->setError('');
|
||||
$this->setKeepTime((int)Config::get('buildadmin.admin_token_keep_time'));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue