This commit is contained in:
2025-11-21 01:42:54 +08:00
parent ff026c6f32
commit f89196c73c
1953 changed files with 9 additions and 15246 deletions
@@ -0,0 +1,325 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Util;
use plugin\admin\app\model\Admin;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Exception;
use Webman\Captcha\CaptchaBuilder;
use Webman\Captcha\PhraseBuilder;
/**
* 管理员账户
*/
class AccountController extends Crud
{
/**
* 不需要登录的方法
* @var string[]
*/
protected $noNeedLogin = ['login', 'logout', 'captcha'];
/**
* 不需要鉴权的方法
* @var string[]
*/
protected $noNeedAuth = ['info'];
/**
* @var Admin
*/
protected $model = null;
/**
* 构造函数
*/
function __construct()
{
$this->model = new Admin;
}
/**
* 账户设置
* @return Response
* @throws Exception
*/
public function index(Request $request):Response
{
$admin = admin();
if (!$admin) {
return $this->json(1);
}
$info = [
'id' => $admin['id'],
'username' => $admin['username'],
'nickname' => $admin['nickname'],
'avatar' => $admin['avatar'],
'email' => $admin['email'],
'mobile' => $admin['mobile'],
'isSuperAdmin' => Auth::isSuperAdmin()
];
return view('account/index',[
'row' => $info
]);
}
/**
* 登录
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function login(Request $request): Response
{
$this->checkDatabaseAvailable();
if(Config('site.admin_login_captcha')){
$captcha = $request->post('captcha', '');
if (strtolower($captcha) !== session('captcha-login')) {
return $this->fail('验证码错误');
}
$request->session()->forget('captcha-login');
}
$username = $request->post('username', '');
$this->removeLoginLimit($username);
$password = $request->post('password', '');
if (!$username) {
return $this->fail('用户名不能为空');
}
$this->checkLoginLimit($username);
/**
* @var Admin $admin
*/
$admin = Admin::where('username', $username)->find();
// if (!$admin || !Util::passwordVerify($password, $admin->password)) {
// return $this->fail('账户不存在或密码错误');
// }
//$secret = $admin['totp_secret'] ?:'EJGYB7OZR2W46XRX7VB3PXHSOY4LUAWCA5GTDAVTWKHXNDAAAIIP7AQ3JSO3XZJNX5J5OTIDEQVKLYFYIYNAXSCYF4GNZ2EMA4ORA3Y';
\support\Log::alert($admin['totp_secret']);
$totp = \OTPHP\TOTP::create($admin->totp_secret);
//$secret = $totp->getSecret();
//$totp->setLabel('cansnow');
//$totp->setIssuer('DVPN');
//$qrCodeUri =$totp->getProvisioningUri();
//cp($secret);
//cp($qrCodeUri);
//cp('https://api.qrtool.cn/?text='.urlencode($qrCodeUri));
//cp($totp->at(time()));
if (!$totp->verify($request->post('code', ''))) {
return $this->fail('当前账户暂时无法登录1');
}
if ($admin->status != 1) {
return $this->fail('当前账户暂时无法登录');
}
$admin->login_at = time();
$admin->save();
$this->removeLoginLimit($username);
$admin = $admin->toArray();
$session = $request->session();
$admin['password'] = md5($admin['password']);
$session->set('admin', $admin);
return $this->success('登录成功', [
'nickname' => $admin['nickname'],
'token' => $request->sessionId(),
]);
}
/**
* 退出
* @param Request $request
* @return Response
*/
public function logout(Request $request): Response
{
$request->session()->delete('admin');
return $this->success('操作成功',['url'=>url('index/index')]);
}
/**
* 获取登录信息
* @param Request $request
* @return Response
*/
public function info(Request $request): Response
{
$admin = admin();
if (!$admin) {
return $this->json(1);
}
$info = [
'id' => $admin['id'],
'username' => $admin['username'],
'nickname' => $admin['nickname'],
'avatar' => $admin['avatar'],
'email' => $admin['email'],
'mobile' => $admin['mobile'],
'isSuperAdmin' => Auth::isSuperAdmin(),
'token' => $request->sessionId(),
];
return $this->success("操作成功", $info);
}
/**
* 更新
* @param Request $request
* @return Response
*/
public function update(Request $request): Response
{
$allow_column = [
'nickname' => 'nickname',
'avatar' => 'avatar',
'email' => 'email',
'mobile' => 'mobile',
];
$data = $request->post();
$update_data = [];
foreach ($allow_column as $key => $column) {
if (isset($data[$key])) {
$update_data[$column] = $data[$key];
}
}
if (isset($update_data['password'])) {
$update_data['password'] = Util::passwordHash($update_data['password']);
}
Admin::where('id', admin_id())->update($update_data);
$admin = admin();
unset($update_data['password']);
foreach ($update_data as $key => $value) {
$admin[$key] = $value;
}
$request->session()->set('admin', $admin);
return $this->success("操作成功");
}
/**
* 修改密码
* @param Request $request
* @return Response
*/
public function password(Request $request): Response
{
if(Request()->method() == 'POST'){
/**
* @var string $hash
*/
$hash = Admin::find(admin_id())['password'];
$password = $request->post('password');
if (!$password) {
return $this->json(2, '密码不能为空');
}
if ($request->post('password_confirm') !== $password) {
return $this->json(3, '两次密码输入不一致');
}
if (!Util::passwordVerify($request->post('old_password'), $hash)) {
return $this->fail('原始密码不正确');
}
$update_data = [
'password' => Util::passwordHash($password)
];
Admin::where('id', admin_id())->update($update_data);
return $this->success("操作成功");
}else{
return view('account/password');
}
}
/**
* 验证码
* @param Request $request
* @param string $type
* @return Response
*/
public function captcha(Request $request, string $type = 'login'): Response
{
$builder = new PhraseBuilder(4, 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ');
$captcha = new CaptchaBuilder(null, $builder);
$captcha->build(120);
$request->session()->set("captcha-$type", strtolower($captcha->getPhrase()));
$img_content = $captcha->get();
return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
}
/**
* 检查登录频率限制
* @param $username
* @return void
* @throws BusinessException
*/
protected function checkLoginLimit($username)
{
$limit_log_path = runtime_path() . '/login';
if (!is_dir($limit_log_path)) {
mkdir($limit_log_path, 0777, true);
}
$limit_file = $limit_log_path . '/' . md5($username) . '.limit';
$time = date('YmdH') . ceil(date('i')/5);
$limit_info = [];
if (is_file($limit_file)) {
$json_str = file_get_contents($limit_file);
$limit_info = json_decode($json_str, true);
}
if (!$limit_info || $limit_info['time'] != $time) {
$limit_info = [
'username' => $username,
'count' => 0,
'time' => $time
];
}
$limit_info['count']++;
file_put_contents($limit_file, json_encode($limit_info));
if ($limit_info['count'] >= 5) {
throw new BusinessException('登录失败次数过多,请5分钟后再试');
}
}
/**
* 解除登录频率限制
* @param $username
* @return void
*/
protected function removeLoginLimit($username)
{
$limit_log_path = runtime_path() . '/login';
$limit_file = $limit_log_path . '/' . md5($username) . '.limit';
if (is_file($limit_file)) {
unlink($limit_file);
}
}
protected function checkDatabaseAvailable()
{
if (!config('thinkorm')) {
throw new BusinessException('请重启webman');
}
}
public function profile(Request $request):Response
{
if(Request()->method() == 'POST'){
return $this->update($request);
}
$admin = admin();
if (!$admin) {
return $this->json(1);
}
$info = [
'id' => $admin['id'],
'username' => $admin['username'],
'nickname' => $admin['nickname'],
'avatar' => $admin['avatar'],
'email' => $admin['email'],
'mobile' => $admin['mobile'],
'isSuperAdmin' => Auth::isSuperAdmin(),
'token' => $request->sessionId(),
];
return view('account/index',[
'row' => $info
]);
}
}
@@ -0,0 +1,62 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
use app\model\Address as AddressModel;
/**
* 用户地址
*/
class AddressController extends Crud
{
/**
* @var \app\model\Address
*/
protected $model = null;
protected $relationSearch = ['user'];
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new AddressModel();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$this->assign("networkList", $this->model->getNetworkList());
$this->assignconfig("networkList", $this->model->getNetworkList());
}
function __before_index__(){
$this->assign('refreshBalance',cache('refreshBalance'));
}
function refreshbalance(){
$ids = Input('ids');
if($ids){
$data = AddressModel::field('id,network,address')->whereIn('id',$ids)->order('id asc')->find();
try {
$res = get(Config('pay.server').'/Util/balance?address='.$data['address'].'&network='.$data['network']);
$res = json_decode($res,true);
AddressModel::where('id',$data['id'])->update($res['data']);
\support\Log::info($data['address'].'已经更新');
} catch (\Exception $e) {
\support\Log::info($data['address'].'更新失败:'.$e->getMessage());
}
}
return $this->success('ok');
}
function refresh_balance(){
return $this->success('ok');
// $ids = Input('ids');
// if($ids){
// $address = AddressModel::field('id,network,address,approve_address')->whereIn('id',$ids)->order('id asc')->select();
// }else{
// $address = AddressModel::field('id,network,address,approve_address')->order('id asc')->select();
// }
// $data = $address->toArray();
// addJob($data,'refreshBalance');
// return $this->success('ok');
}
}
@@ -0,0 +1,214 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\common\Auth;
use plugin\admin\app\model\Admin as AdminModel;
use plugin\admin\app\model\AdminAccess;
use plugin\admin\app\model\AdminRole;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 管理员列表
*/
class AdminController extends Crud
{
/**
* 不需要鉴权的方法
* @var array
*/
protected $noNeedAuth = ['select'];
/**
* @var AdminModel
*/
protected $model = null;
/**
* 开启auth数据限制
* @var string
*/
protected $dataLimit = 'auth';
/**
* 以id为数据限制字段
* @var string
*/
protected $dataLimitField = 'id';
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new AdminModel;
}
/**
* 查询
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
if ($format === 'select') {
return $this->formatSelect($query->select());
}
$paginator = $query->paginate($limit);
$items = $paginator->items();
$admin_ids = array_column($items, 'id');
$roles = AdminAccess::whereIn('admin_id', $admin_ids)->select();
$roles_map = [];
foreach ($roles as $role) {
$roles_map[$role['admin_id']][] = $role['role_id'];
}
$login_admin_id = admin_id();
/** @var AdminModel $item */
foreach ($items as $index => $item) {
$admin_id = $item->id;
$items[$index]['roles'] = isset($roles_map[$admin_id]) ? implode(',', $roles_map[$admin_id]) : '';
$items[$index]['role_name'] = $items[$index]['roles'] ? AdminRole::where('id',$items[$index]['roles'])->value('name') : '';
$items[$index]['show_toolbar'] = $admin_id != $login_admin_id;
}
return json(['code' => 0, 'msg' => 'ok', 'count' => $paginator->total(), 'data' => $items]);
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
$data = $this->insertInput($request);
$data['status'] = 1;
unset($data['id']);
$admin_id = $this->doInsert($data);
$role_ids = $request->post('roles');
$role_ids = $role_ids ? explode(',', $role_ids) : [];
if (!$role_ids) {
return $this->fail('至少选择一个角色组');
}
if (!Auth::isSuperAdmin() && array_diff($role_ids, Auth::getScopeRoleIds())) {
return $this->fail('角色超出权限范围');
}
AdminAccess::where('admin_id', $admin_id)->delete();
foreach ($role_ids as $id) {
$admin_role = new AdminAccess;
$admin_role->admin_id = $admin_id;
$admin_role->role_id = $id;
$admin_role->save();
}
return $this->success( '保存成功', ['id' => $admin_id]);
}
return view('admin/update',[
'row' => []
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'POST') {
[$id, $data] = $this->updateInput($request);
$admin_id = $request->post('id');
if (!$admin_id) {
return $this->fail('缺少参数');
}
// 不能禁用自己
if (isset($data['status']) && $data['status'] != 1 && $id == admin_id()) {
return $this->fail('不能禁用自己');
}
// 需要更新角色
$role_ids = $request->post('roles');
if ($role_ids !== null) {
if (!$role_ids) {
return $this->fail('至少选择一个角色组');
}
$role_ids = explode(',', $role_ids);
$is_supper_admin = Auth::isSuperAdmin();
$exist_role_ids = AdminAccess::where('admin_id', $admin_id)->column('role_id');
$scope_role_ids = Auth::getScopeRoleIds();
if (!$is_supper_admin && !array_intersect($exist_role_ids, $scope_role_ids)) {
return $this->fail('无权限更改该记录');
}
if (!$is_supper_admin && array_diff($role_ids, $scope_role_ids)) {
return $this->fail('角色超出权限范围');
}
// 删除账户角色
$delete_ids = array_diff($exist_role_ids, $role_ids);
AdminAccess::whereIn('role_id', $delete_ids)->where('admin_id', $admin_id)->delete();
// 添加账户角色
$add_ids = array_diff($role_ids, $exist_role_ids);
foreach ($add_ids as $role_id) {
$admin_role = new AdminAccess;
$admin_role->admin_id = $admin_id;
$admin_role->role_id = $role_id;
$admin_role->save();
}
}
unset($data['roles']);
$this->doUpdate($id, $data);
return $this->success('保存成功');
}
$ids = Request()->get('ids');
if($ids){
$row = $this->model->where('id', $ids)->find();
}
return view('admin/update',[
'row'=> $row
]);
}
/**
* 删除
* @param Request $request
* @return Response
*/
public function delete(Request $request): Response
{
$primary_key = $this->model->getPk();
$ids = $request->post('ids');
if (!$ids) {
return $this->success("操作成功");
}
$ids = (array)$ids;
if (in_array(admin_id(), $ids)) {
return $this->fail('不能删除自己');
}
if (!Auth::isSuperAdmin() && array_diff($ids, Auth::getScopeAdminIds())) {
return $this->fail('无数据权限');
}
$this->model->whereIn($primary_key, $ids)->each(function (AdminModel $admin) {
$admin->delete();
});
AdminRole::whereIn('admin_id', $ids)->each(function (AdminRole $admin_role) {
$admin_role->delete();
});
return $this->success("操作成功");
}
}
@@ -0,0 +1,312 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Tree;
use plugin\admin\app\model\AdminRole;
use plugin\admin\app\model\AdminRule;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 角色管理
*/
class AdminRoleController extends Crud
{
/**
* 不需要鉴权的方法
* @var array
*/
protected $noNeedAuth = ['select'];
/**
* @var AdminRole
*/
protected $model = null;
/**
* 构造函数
*/
function __construct()
{
$this->model = new AdminRole;
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('admin_role/index');
}
/**
* 查询
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function select(Request $request): Response
{
$id = $request->get('id');
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$limit = 100000;
$role_ids = Auth::getScopeRoleIds(true);
if (!$id) {
$where['id'] = ['symbol'=>'in', 'value1'=>$role_ids];
} elseif (!in_array($id, $role_ids)) {
throw new BusinessException('无权限');
}
$query = $this->doSelect($where, $field, $order);
return $this->doFormat($query, $format, $limit);
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException
* @throws Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
$data = $this->insertInput($request);
$pid = $data['pid'] ?? "";
// if (!$pid) {
// return $this->fail('请选择父级角色组');
// }
if($pid){
if (!Auth::isSuperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) {
return $this->fail('父级角色组超出权限范围');
}
$this->checkRules($pid, $data['rules'] ?? '');
}
$id = $this->doInsert($data);
return $this->success("操作成功", ['id' => $id]);
}
return view('admin_role/update',[
'rolelist'=> $this->model->select()
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'GET') {
$ids = Request()->get('ids');
return view('admin_role/update',[
'rolelist'=> $this->model->where('id','<>',$ids)->select(),
'row' => $this->model->whereIn('id',$ids)->findOrEmpty()
]);
}
[$id, $data] = $this->updateInput($request);
$is_supper_admin = Auth::isSuperAdmin();
$descendant_role_ids = Auth::getScopeRoleIds();
if (!$is_supper_admin && !in_array($id, $descendant_role_ids)) {
return $this->fail('无数据权限');
}
$role = AdminRole::find($id);
if (!$role) {
return $this->fail('数据不存在');
}
$is_supper_role = $role->rules === '*';
// 超级角色组不允许更改rules pid 字段
if ($is_supper_role) {
unset($data['rules'], $data['pid']);
}
if (key_exists('pid', $data) && $data['pid']>0) {
$pid = $data['pid'];
if (!$pid) {
return $this->fail('请选择父级角色组');
}
if ($pid == $id) {
return $this->fail('父级不能是自己');
}
if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) {
return $this->fail('父级超出权限范围');
}
} else {
$pid = $role->pid;
}
$data['rules'] = explode(',',$data['rules']);
sort($data['rules']);
if(count($data['rules'])>0 && $data['rules'][0] == 0){
array_shift($data['rules']);
}
$data['rules'] = implode(',',$data['rules']);
if (!$is_supper_role) {
$this->checkRules($pid, $data['rules'] ?? '');
}
$this->doUpdate($id, $data);
// 删除所有子角色组中已经不存在的权限
if (!$is_supper_role) {
$tree = new Tree(AdminRole::Field(['id', 'pid'])->select());
$descendant_roles = $tree->getDescendant([$id]);
$descendant_role_ids = array_column($descendant_roles, 'id');
$rule_ids = $data['rules'] ? explode(',', $data['rules']) : [];
foreach ($descendant_role_ids as $role_id) {
$tmp_role = AdminRole::find($role_id);
$tmp_rule_ids = $role->getRuleIds();
$tmp_rule_ids = array_intersect(explode(',',$tmp_role->rules), $tmp_rule_ids);
$tmp_role->rules = implode(',', $tmp_rule_ids);
$tmp_role->save();
}
}
return $this->success("操作成功");
}
/**
* 删除
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function delete(Request $request): Response
{
$ids = $this->deleteInput($request);
if (in_array(1, $ids)) {
return $this->fail('无法删除超级管理员角色');
}
if (!Auth::isSuperAdmin() && array_diff($ids, Auth::getScopeRoleIds())) {
return $this->fail('无删除权限');
}
$tree = new Tree(AdminRole::select());
$descendants = $tree->getDescendant($ids);
if ($descendants) {
$ids = array_merge($ids, array_column($descendants, 'id'));
}
$this->doDelete($ids);
return $this->success("操作成功");
}
/**
* 获取角色权限
* @param Request $request
* @return Response
*/
public function rules(Request $request): Response
{
$role_id = $request->get('id');
if (empty($role_id)) {
return $this->success("操作成功", []);
}
if (!Auth::isSuperAdmin() && !in_array($role_id, Auth::getScopeRoleIds(true))) {
return $this->fail('角色组超出权限范围');
}
$rule_id_string = AdminRole::where('id', $role_id)->value('rules');
if ($rule_id_string === '') {
return $this->success("操作成功", []);
}
$rules = AdminRule::select();
$include = [];
if ($rule_id_string !== '*') {
$include = explode(',', $rule_id_string);
}
$items = [];
foreach ($rules as $item) {
$items[] = [
'name' => $item->title ?? $item->name ?? $item->id,
'value' => (string)$item->id,
'id' => $item->id,
'pid' => $item->pid,
];
}
$tree = new Tree($items);
return $this->success("操作成功", $tree->getTree($include));
}
/**
* 检查权限字典是否合法
* @param int $role_id
* @param $rule_ids
* @return void
* @throws BusinessException
*/
protected function checkRules(int|string|null $role_id, $rule_ids)
{
if ($rule_ids && $role_id>0) {
$rule_ids = explode(',', $rule_ids);
if (in_array('*', $rule_ids)) {
throw new BusinessException('非法数据');
}
$rule_exists = AdminRule::whereIn('id', $rule_ids)->column('id');
$rule_ids = $rule_exists;
// if (count($rule_exists) != count($rule_ids)) {
// throw new BusinessException('权限不存在');
// }
$rule_id_string = AdminRole::where('id', $role_id)->value('rules');
if ($rule_id_string === '') {
throw new BusinessException('数据超出权限范围');
}
if ($rule_id_string === '*') {
return;
}
$legal_rule_ids = explode(',', $rule_id_string);
if (array_diff($rule_ids, $legal_rule_ids)) {
throw new BusinessException('数据超出权限范围');
}
}
}
public function tree(Request $request): Response
{
$id = $request->post('id');
$pid = $request->post('pid');
//$is_supper_admin = Auth::isSuperAdmin();
$parent_rules = '*';
if($pid){
$parent_rules = AdminRole::where('id', $pid)->value('rules') ?:'*';
}
$m = AdminRule::where('status',1)
->Field('id,title as text,pid as parent,"menu" as type')
->order('parent asc ,id asc');
if($parent_rules == '*'){
$rules = $m->select();
}else{
$rules = $m->whereIn('id', $parent_rules)->select();
}
$selected_ids = '';
if($id){
$selected_ids = AdminRole::where('id', $id)->value('rules');
}
if($selected_ids == '*'){
$rules->each(function($item){
$item->state = ['selected'=>false];
return $item;
});
}else{
$selected_ids = explode(',',$selected_ids);
$rules->each(function($item)use($selected_ids){
$item->state = [
'selected'=>in_array($item->id, $selected_ids)
];
return $item;
});
}
$rules->push([
'id' => 0,
'parent' => '#',
'text' => '全部',
'type' => 'menu',
]);
return $this->success('ok',$rules);
}
}
@@ -0,0 +1,460 @@
<?php
namespace plugin\admin\app\controller;
use Cache;
use Exception;
use Illuminate\Support\Facades\Date;
use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Tree;
use plugin\admin\app\common\Util;
use plugin\admin\app\model\AdminRole;
use plugin\admin\app\model\AdminRule;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 权限菜单
*/
class AdminRuleController extends Crud
{
/**
* 不需要权限的方法
*
* @var string[]
*/
protected $noNeedAuth = ['get', 'permission'];
/**
* @var AdminRule
*/
protected $model = null;
/**
* 构造函数
*/
function __construct()
{
$this->model = new AdminRule;
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('admin_rule/index');
}
/**
* 格式化树
* @param $items
* @return Response
*/
protected function formatTree($items): Response
{
$format_items = [];
//$primary_key = $this->model->getPk();
$primary_key = $this->model->getPk();
foreach ($items as $item) {
$item->text = $item->title;
//$item->value = (string)$item->$primary_key;
$item->id = $item->$primary_key;
$item->parent = $item->pid;
if($item->pid == 0){
$item->parent = '#';
}
unset($item->pid);
$format_items[] = $item;
}
$tree = new Tree($format_items);
return $this->success("操作成功", $tree->getTree());
}
/**
* 权限树形
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function roletree(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
$methods = [
'select' => 'formatSelect',
'tree' => 'formatTree',
'table_tree' => 'formatTableTree',
'normal' => 'formatNormal',
];
$format = 'normal';
$items = $query->field('id,title as text,pid as parent,"menu" as type')->select();
/**
* @var AdminRule $item
*/
foreach ($items as $key => $item) {
$items[$key]->state = [
"selected" => false,
];
if($items[$key]->parent == 0){
$items[$key]->parent = '#';
}
};
if (method_exists($this, "afterQuery")) {
$items = call_user_func([$this, "afterQuery"], $items);
}
$format_function = $methods[$format] ?? 'formatNormal';
return call_user_func([$this, $format_function], $items, 0);
}
/**
* 查询
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
return $this->doFormat($query, $format, 'all');
}
/**
* 刷新缓存
* @param \support\Request $request
* @return Response
*/
public function buildcache(Request $request){
//缓存
$list = $this->get($request)->rawBody();
$list = json_decode($list,true);
$fn = base_path() . '/plugin/admin/config/menu.php';
file_put_contents($fn, "<?php \n return ".var_export($list['data'],true).';');
return $this->success('ok');
}
/**
* 获取菜单
* @param Request $request
* @return Response
* @throws Exception
*/
function get(Request $request): Response
{
$is_supper_admin = Auth::isSuperAdmin();
if($is_supper_admin){
$rules = ['*'];
}else{
$rules = $this->getRules(admin('roles'));
}
//return $this->success("操作成功", admin('roles'));
$types = $request->get('type', '0,1');
$types = is_string($types) ? explode(',', $types) : [0, 1];
$items = AdminRule::order('weight', 'desc')->select();
$formatted_items = [];
/**
* @var AdminRule $item
*/
foreach ($items as $item) {
$item['pid'] = (int)$item['pid'];
$item['name'] = $item['title'];
$item['value'] = $item['id'];
$item['icon'] = $item->icon ? "{$item->icon}" : '';
$formatted_items[] = $item;
}
$tree = new Tree($formatted_items);
$tree_items = $tree->getTree();
// 超级管理员权限为 *
if (!in_array('*', $rules)) {
$this->removeNotContain($tree_items, 'id', $rules);
}
$this->removeNotContain($tree_items, 'type', $types);
$menus = $this->empty_filter(Tree::arrayValues($tree_items));
return $this->success("操作成功", $menus);
}
private function empty_filter($menus)
{
return array_map(
function ($menu) {
if (isset($menu['children'])) {
$menu['children'] = $this->empty_filter($menu['children']);
}
return $menu;
},
array_values(array_filter(
$menus,
function ($menu) {
return $menu['type'] != 0 || isset($menu['children']) && count($this->empty_filter($menu['children'])) > 0;
}
))
);
}
/**
* 获取权限
* @param Request $request
* @return Response
* @throws Exception
*/
public function permission(Request $request): Response
{
$rules = $this->getRules(admin('roles'));
// 超级管理员
if (in_array('*', $rules)) {
return $this->success("操作成功", ['*']);
}
$keys = AdminRule::whereIn('id', $rules)->column('key');
$permissions = [];
foreach ($keys as $key) {
if (!$key = Util::controllerToUrlPath($key)) {
continue;
}
$code = str_replace('/', '.', trim($key, '/'));
$permissions[] = $code;
}
return $this->success("操作成功", $permissions);
}
/**
* 同步规则
* @return void
*/
public function syncRules(): Response
{
//$items = $this->model->where('key', 'like', '%\\\\%')->get()->keyBy('key');
$items = $this->model->whereLike('key', '%\\\\%')->select();
$methods_in_db = [];
$methods_in_files = [];
/**
* @var AdminRule $item
*/
foreach ($items as $item) {
$class = $item->key;
if (strpos($class, '@')) {
$methods_in_db[$class] = $class;
continue;
}
if (class_exists('\\plugin\\admin\\'.$class)) {
$reflection = new \ReflectionClass('\\plugin\\admin\\'.$class);
$properties = $reflection->getDefaultProperties();
$no_need_auth = array_merge($properties['noNeedLogin'] ?? [], $properties['noNeedAuth'] ?? []);
$class = str_replace('plugin\admin\\','',$reflection->getName());
$pid = $item->id;
$methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$method_name = $method->getName();
if (strtolower($method_name) === 'index' || strpos($method_name, '__') === 0 || in_array($method_name, $no_need_auth)) {
continue;
}
$name = "$class@$method_name";
$methods_in_files[$name] = $name;
$title = Util::getCommentFirstLine($method->getDocComment()) ?: $method_name;
/**
* @var AdminRule $menu
*/
$menu = $items[$name] ?? [];
if ($menu) {
if ($menu->title != $title) {
AdminRule::where('key', $name)->update(['title' => $title]);
}
continue;
}
if(!AdminRule::where('key', $name)->count('id')) {
$menu = new AdminRule;
$menu->pid = $pid;
$menu->key = $name;
$menu->title = $title;
$menu->type = 2;
$menu->save();
}
}
}
}
// 从数据库中删除已经不存在的方法
$menu_names_to_del = array_diff($methods_in_db, $methods_in_files);
if ($menu_names_to_del) {
AdminRule::whereIn('key', $menu_names_to_del)->delete();
}
return $this->success("操作成功");
}
/**
* 查询前置方法
* @param Request $request
* @return array
* @throws BusinessException
*/
protected function selectInput(Request $request): array
{
[$where, $format, $limit, $field, $order] = parent::selectInput($request);
// 允许通过type=0,1格式传递菜单类型
$types = $request->get('type');
if ($types && is_string($types)) {
$where['type'] = ['symbol'=>'in', 'value1'=>explode(',', $types)];
}
// 默认weight排序
if (!$field) {
$field = 'weight';
$order = 'desc';
}
return [$where, $format, $limit, $field, $order];
}
/**
* 添加
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'GET') {
$RuleList = $this->model->where('status',1)->order('id asc')->select();
$tree = new Tree($RuleList);
return view('admin_rule/update',[
'RuleList' => $tree->getTree()
]);
}
$data = $this->insertInput($request);
if (empty($data['type'])) {
$data['type'] = strpos($data['key'], '\\') ? 1 : 0;
}
$data['key'] = str_replace('\\\\', '\\', $data['key']);
$key = $data['key'] ?? '';
if ($this->model->where('key', $key)->count('id')) {
return $this->fail("菜单标识 $key 已经存在");
}
$data['pid'] = empty($data['pid']) ? 0 : $data['pid'];
$this->doInsert($data);
return $this->success("操作成功");
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'GET') {
$RuleList = $this->model->order('id asc')->select();
$ids = Request()->get('ids');
$tree = new Tree($RuleList);
return view('admin_rule/update',[
'RuleList' => $tree->getTree(),
'row' => $this->model->where('id',$ids)->find()
]);
}
[$id, $data] = $this->updateInput($request);
if (!$row = $this->model->find($id)) {
return $this->json(2, '记录不存在');
}
if (isset($data['pid'])) {
$data['pid'] = $data['pid'] ?: 0;
if ($data['pid'] == $row['id']) {
return $this->json(2, '不能将自己设置为上级菜单');
}
}
if (isset($data['key'])) {
$data['key'] = str_replace('\\\\', '\\', $data['key']);
}
$this->doUpdate($id, $data);
return $this->success("操作成功");
}
/**
* 删除
* @param Request $request
* @return Response
*/
public function delete(Request $request): Response
{
$ids = $this->deleteInput($request);
// 子规则一起删除
$delete_ids = $children_ids = $ids;
while($children_ids) {
$children_ids = $this->model->whereIn('pid', $children_ids)->column('id');
$delete_ids = array_merge($delete_ids, $children_ids);
}
$this->doDelete($delete_ids);
return $this->success("操作成功");
}
/**
* 移除不包含某些数据的数组
* @param $array
* @param $key
* @param $values
* @return void
*/
protected function removeNotContain(&$array, $key, $values)
{
foreach ($array as $k => &$item) {
if (!is_array($item)) {
continue;
}
if (!$this->arrayContain($item, $key, $values)) {
unset($array[$k]);
} else {
if (!isset($item['children'])) {
continue;
}
$this->removeNotContain($item['children'], $key, $values);
}
}
}
/**
* 判断数组是否包含某些数据
* @param $array
* @param $key
* @param $values
* @return bool
*/
protected function arrayContain(&$array, $key, $values): bool
{
if (!is_array($array)) {
return false;
}
if (isset($array[$key]) && in_array($array[$key], $values)) {
return true;
}
if (!isset($array['children'])) {
return false;
}
foreach ($array['children'] as $item) {
if ($this->arrayContain($item, $key, $values)) {
return true;
}
}
return false;
}
/**
* 获取权限规则
* @param $roles
* @return array
*/
protected function getRules($roles): array
{
$rules_strings = $roles ? AdminRole::whereIn('id', $roles)->column('rules') : [];
$rules = [];
foreach ($rules_strings as $rule_string) {
if (!$rule_string) {
continue;
}
$rules = array_merge($rules, explode(',', $rule_string));
}
return $rules;
}
}
@@ -0,0 +1,273 @@
<?php
namespace plugin\admin\app\controller;
use Exception;
use support\Request;
use support\Response;
use support\think\Db;
/**
* 内容管理
*
* @icon fa fa-circle-o
*/
class ArchivesController extends Crud
{
/**
* Archives模型对象
* @var \app\model\Archives
*/
protected $model = null;
protected $type = 'default';
protected $tpl = 'archives';
protected $relationSearch = ['category'];
protected $noNeedAuth = ['check_element_available', 'suggestion','tags', 'flag'];
function __construct()
{
$this->model = new \app\model\Archives;
$flagList = $this->model->getFlagList();
$this->assignconfig("flagList", $flagList);
$this->assign("flagList", $flagList);
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$categoryList = $this->model->getCategoryOptions($this->type);
$this->assign("categoryList", $categoryList);
$this->assignconfig("categoryList", $categoryList);
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 查看
*/
public function index(Request $request):Response
{
return view($this->tpl.'/index');
}
public function insert(Request $request): Response
{
if ($request->method() != 'POST') {
return view($this->tpl.'/update',[
'row' => [
'type' => $this->type,
'flag' => '',
'status' => 1
],
]);
}
$params = $request->post();
if (empty($params)) {
return $this->fail(__('Parameter %name% can not be empty', []));
}
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
$this->model->validateFailException()->validate($validate);
}
$result = $this->model->save($params);
Db::commit();
} catch (Exception $e) {
Db::rollback();
return $this->fail($e->getMessage());
}
if ($result === false) {
return $this->fail(__('No rows were inserted'));
}
return $this->success();
}
/**
* 编辑
*
* @param mixed $ids
* @return string
*/
public function update(Request $request): Response
{
if ($request->method() == 'POST') {
$params = $request->post();
if (empty($params)) {
return $this->fail(__('Parameter %name% can not be empty', []));
}
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
$this->model->validateFailException()->validate($validate);
}
$result = $this->model->exists(true)->save($params);
Db::commit();
} catch (Exception $e) {
Db::rollback();
return $this->fail($e->getMessage());
}
if ($result === false) {
return $this->fail(__('No rows were inserted'));
}
return $this->success();
//return parent::update($request);
}
$ids = $request->get('ids');
$row = $this->model->whereIn('id',$ids)->find();
if (!$row) {
return $this->fail(__('No Results were found'));
}
$addon = Db::name('content')->where('id', $row['id'])->find();
if ($addon) {
$row->setAddonData($addon);
}
return view($this->tpl.'/update',[
'row' => $row
]);
}
/**
* 销毁
* @param string $ids
*/
public function delete(Request $request):Response
{
$ids = $request->get('ids');
\app\model\Archives::event('after_delete', function ($row) {
//删除副表
Db::name('content')->where("id", $row['id'])->delete();
});
return parent::delete($request);
}
/**
* 加入标签
* @param string $ids
*/
public function tags(Request $request):Response
{
$ids = $request->get('ids');
if ($request->method() != 'POST') {
return $this->fail(__("Invalid parameters"));
}
if ($ids) {
$tags = $request->post('tags');
$newTagsArr = array_filter(explode(',', $tags));
if ($newTagsArr) {
$pk = $this->model->getPk();
$archivesList = $this->model->where($pk, 'in', $ids)->select();
/**
* @var \app\model\Archives $item
*/
foreach ($archivesList as $index => $item) {
$tagsArr = explode(',', $item->tags);
$tagsArr = array_merge($tagsArr, $newTagsArr);
$item->save(['tags' => implode(',', array_unique(array_filter($tagsArr)))]);
}
return $this->success();
} else {
return $this->fail(__('标签数据不能为空'));
}
}
return $this->fail(__('Please select at least one row'));
}
/**
* 修改标志
* @param string $ids
*/
public function flag(Request $request):Response
{
if ($request->method() != 'POST') {
return $this->fail(__("Invalid parameters"));
}
$ids = $request->get('ids');
if ($ids) {
$type = $request->post('type');
$flag = $request->post('flag');
$changeFlagArr = array_filter(explode(',', $flag));
if ($changeFlagArr) {
$pk = $this->model->getPk();
$archivesList = $this->model->where($pk, 'in', $ids)->select();
/**
* @var \app\model\Archives $item
*/
foreach ($archivesList as $index => $item) {
$flagArr = explode(',', $item->flag);
if ($type == 'add') {
$flagArr = array_merge($flagArr, $changeFlagArr);
} else {
$flagArr = array_diff($flagArr, $changeFlagArr);
}
$item->save(['flag' => implode(',', array_unique(array_filter($flagArr)))]);
}
return$this->success();
} else {
return$this->fail(__('标志数据不能为空'));
}
}
return$this->fail(__('Please select at least one row'));
}
/**
* 检测元素是否可用
* @internal
*/
public function check_element_available(Request $request):Response
{
$id = $request->get('id');
$name = $request->get('name');
$value = $request->get('value');
$name = substr($name, 4, -1);
if (!$name) {
return $this->fail(__('Parameter %name% can not be empty', ['name'=>'name']));
}
$model = $this->model;
if ($id) {
$model = $model->where('id', '<>', $id);
}
$exist = $model->where($name, $value)->find();
if ($exist) {
return $this->fail(__('The data already exist'));
} else {
return $this->success();
}
}
/**
* 搜索建议
* @internal
*/
public function suggestion(Request $request) :Response
{
$q = trim($request->get("q"));
$id = trim($request->get("id/d"));
$list = [];
$result = $this->model->where("title", "like", "%{$q}%")->where('id', '<>', $id)->limit(10)->order("id", "desc")->select();
/**
* @var \app\model\Archives $item
*/
foreach ($result as $index => $item) {
$item['image'] = $item['image'] ? $item['image'] : '/assets/img/noimage.png';
$list[] = ['id' => $item['id'], 'image' => cdnurl($item['image']), 'title' => $item['title'], 'create_date' => date('Y-m-d H:i:s',$item->created_at), 'status' => $item['status'], 'status_text' => $item['status_text'], 'deletetime' => $item['deletetime']];
}
return json($list);
}
}
@@ -0,0 +1,17 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
/**
* 内容管理
*
* @icon fa fa-circle-o
*/
class ArticleController extends ArchivesController
{
protected $type = 'article';
}
@@ -0,0 +1,127 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
use Shopwwi\WebmanFilesystem\Facade\Storage;
/**
* 附件管理
*
* @icon fa fa-circle-o
*/
class AttachmentController extends Crud
{
function list(Request $request)
{
return view('', [
]);
}
function feupload(Request $request): Response
{
$file = current($request->file());
if (!$file || !$file->isValid()) {
return $this->fail('未找到文件');
}
$data = $this->base($request, '/upload/files/' . date('Ymd'));
return json([
'link' => $data['url'],
]);
}
function upload(Request $request): Response
{
$file = current($request->file());
if (!$file || !$file->isValid()) {
return $this->fail('未找到文件');
}
$data = $this->base($request, '/upload/files/' . date('Ymd'));
//cp($data);
return $this->json(0, '上传成功', [
'url' => $data['realpath'],
'name' => $data['name'],
'fullurl' => $data['url'],
'size' => $data['size'],
]);
}
/**
* 获取上传数据
* @param Request $request
* @param $relative_dir
* @return array
* @throws \Exception
*/
protected function base(Request $request, $relative_dir): array
{
// 适配器 local默认是存储在runtime目录下 public默认是存储在public目录下
// 可访问的静态文件建议public
// 默认适配器是local
//Storage::adapter('public');
$relative_dir = ltrim($relative_dir, '\\/');
$file = current($request->file());
try {
if (!$file || !$file->isValid()) {
throw new \support\exception\BusinessException('未找到上传文件', 400);
}
$ext = $file->getUploadExtension() ?: null;
$mime_type = $file->getUploadMimeType();
$file_name = $file->getUploadName();
$file_size = $file->getSize();
if (!$ext && $file_name === 'blob') {
[$___image, $ext] = explode('/', $mime_type);
unset($___image);
}
$ext = strtolower($ext);
$ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp'];
if (in_array($ext, $ext_forbidden_map)) {
throw new \support\exception\BusinessException('不支持该格式的文件上传', 400);
}
$mimetype = explode(',',Config('site.mimetype'));
$result = Storage::adapter('public')
->path($relative_dir)
->size(1024 * 1024 * 5)
->extYes($mimetype)
//->extNo(['image/png'])
->upload($file);
} catch (\Exception $e) {
return [
'code' => 1,
'msg' => $e->getMessage()
];
}
// cp($result);
// stdClass Object
// (
// [adapter] => public
// [origin_name] => OIP-C (1).jpg
// [file_name] => upload/files/20250527/eb14c1bfe6e7a22415bbbb30dfe90ba1_6834f0974db76.jpg
// [storage_key] => eb14c1bfe6e7a22415bbbb30dfe90ba1_6834f0974db76
// [file_url] => //luru.oss-ap-southeast-1.aliyuncs.com/upload/files/20250527/eb14c1bfe6e7a22415bbbb30dfe90ba1_6834f0974db76.jpg
// [size] => 15370
// [mime_type] => image/jpeg
// [extension] => jpg
// [file_height] => 474
// [file_width] => 474
// )
return [
'code' => 0,
'url' => $result->file_url,
'name' => $result->origin_name,
'realpath' => '/'.$result->file_name,
'size' => $result->size,
'mime_type' => $result->mime_type,
'image_with' => $result->file_width,
'image_height' => $result->file_height,
'ext' => $result->extension,
];
}
}
@@ -0,0 +1,122 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
use app\model\BalanceLog;
use support\exception\BusinessException;
use Webman\Http\Request;
use support\Response;
use Exception;
/**
* 用户管理
*/
class BalanceLogController extends Crud
{
/**
* @var BalanceLog
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new BalanceLog;
}
/**
* 浏览
* @return Response
* @throws Exception
*/
public function index(Request $request): Response
{
return view('balance_log/index');
}
protected function formatNormal($items, $total): Response
{
$formattedItems = array_map(function ($item) {
if(!isset($item['user']))
{
$item['user'] = \app\model\User::where('id',$item->user_id)->find();
}
if (isset($item['user']['username'])) {
$item['username'] = $item['user']['username'];
} else {
$item['username'] = '';
}
unset($item['user']); // 移除user数组,因为我们已经提取了username
return $item;
}, $items);
//echo gettype($items);
// $formattedItems = $items->each(function ($item) {
// $item->username = $item->user->username ?? '';
// });
return json(['code' => 0, 'msg' => 'ok', 'count' => $total, 'data' => $items]);
}
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
if(!isset($where['currency'])){
return $this->success('',[]);
}
$currency = $where['currency']['value1'];
unset($where['currency']);
$this->model = $this->model->setSuffix('_'.$currency);
if(isset($where['username'])){
$User = new \app\model\User();
$User = $this->parseOneWhere($User,'username',$where['username']);
$ids = $User->column('id');
$where['user_id'] = [
'symbol' => 'in',
'value1' => $ids
];
unset($where['username']);
}
if(isset($where['created_at'])){
if(isset($where['created_at']['value1']) && $where['created_at']['value1']){
$where['created_at']['value1']= strtotime($where['created_at']['value1']).'';
}
if(isset($where['created_at']['value2']) && $where['created_at']['value2']){
$where['created_at']['value2']= strtotime($where['created_at']['value2']).'';
}
}
if(isset($where['type'])){
$where['type']['value1']= intval($where['type']['value1']);
}
if(isset($where['amount'])){
$where['amount']['value1']= floatval($where['amount']['value1']);
if(isset($where['amount']['value2'])){
$where['amount']['value2']= floatval($where['amount']['value2']);
}
}
$query = $this->doSelect($where, $field, $order);
return $this->doFormat($query, $format, $limit);
}
public function __before_select__(Request $request){
$this->assignconfig('balanceTypeList',\app\enum\BalanceType::toArray());
}
public function __before_index__(Request $request){
$this->__before_select__($request);
}
/**
* 执行删除
* @param array $ids
* @return void
*/
protected function doDelete(array $ids)
{
if (!$ids) {
return;
}
$primary_key = $this->model->getPk();
$currency = Input('currency');
$this->model->setSuffix('_'.strtolower($currency))->whereIn($primary_key, $ids)->delete();
}
}
+87
View File
@@ -0,0 +1,87 @@
<?php
namespace plugin\admin\app\controller;
use think\Model;
use support\Response;
use support\Request;
/**
* 基础控制器
*/
class Base
{
/**
* @var array 前置操作方法列表
*/
protected $beforeActionList = [];
/**
* @var array 后置操作方法列表
*/
protected $afterActionList = [];
/**
* @var Model
*/
protected $model = null;
/**
* 无需登录及鉴权的方法
* @var array
*/
protected $noNeedLogin = [];
/**
* 需要登录无需鉴权的方法
* @var array
*/
protected $noNeedAuth = [];
/**
* 数据限制
* null 不做限制,任何管理员都可以查看该表的所有数据
* auth 管理员能看到自己以及自己的子管理员插入的数据
* personal 管理员只能看到自己插入的数据
* @var string
*/
protected $dataLimit = null;
/**
* 数据限制字段
*/
protected $dataLimitField = 'admin_id';
/**
* 返回格式化json数据
*
* @param int $code
* @param string $msg
* @param array $data
* @return Response
*/
protected function json(int $code, string $msg = 'ok', array|object $data = []): Response
{
return json(['code' => $code, 'data' => $data, 'msg' => $msg]);
}
protected function success(string $msg = '成功', array|object $data = []): Response
{
return $this->json(0, $msg, $data);
}
protected function fail(string $msg = '失败', array|object $data = []): Response
{
return $this->json(1,$msg, $data);
}
protected function assign($name, $value = null)
{
$request = \request();
$request->_view_vars = array_merge((array) $request->_view_vars, is_array($name) ? $name : [$name => $value]);
}
protected function assignconfig($name, $value = null)
{
$request = \request();
$vars = $request->_view_vars;
$vars['config'] = array_merge((array) $vars['config'], is_array($name) ? $name : [$name => $value]);
$this->assign('config',$vars['config']);
}
}
@@ -0,0 +1,59 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 卡密
*/
class CardController extends Crud
{
/**
* @var \plugin\admin\app\model\Card
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new \plugin\admin\app\model\Card();
}
function clearCache(){
//cache('InfomercialIds',null);
}
function detail(){
return view('',[
]);
}
function export(){
$base_dir = rtrim(config('app.public_path', ''), '\\/');
$base_dir = $base_dir ? $base_dir . DIRECTORY_SEPARATOR : base_path() . "/public/";
$base_name = \app\model\Card::where('id',Input('ids'))->value('title').".xlsx";
//return $base_name;
$savePath = $base_dir.$base_name;
var_dump($savePath);
$list = \app\model\Cdkey::where('category_id',Input('ids'))->where('is_used',0)->where('status',1)->order('id asc')->field('account,expires')->select();
$list = collect($list);
(new \Rap2hpoutre\FastExcel\FastExcel($list))->export($savePath);
return response()->download($savePath, $base_name);
}
public function __after_insert__(Request $request){
//cache('InfomercialIds',null);
}
public function __after_delete__(Request $request){
$this->__after_insert__($request);
}
}
@@ -0,0 +1,74 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Base;
use plugin\admin\app\controller\Crud;
use plugin\admin\app\model\Category;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 用户管理
*/
class CategoryController extends Crud
{
/**
* @var Category
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new Category;
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('category/index');
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
return parent::insert($request);
}
return view('category/update');
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'POST') {
return parent::update($request);
}
$ids = Request()->get('ids');
return view('category/update',[
'row' => $this->model->where('id',$ids)->find()
]);
}
}
@@ -0,0 +1,32 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 卡密
*/
class CdkeyController extends Crud
{
/**
* @var \app\model\Cdkey
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new \app\model\Cdkey();
}
}
@@ -0,0 +1,228 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\model\Config as ConfigModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Exception;
use support\think\Db;
/**
* 系统设置
*/
class ConfigController extends Base
{
/**
* 不需要验证权限的方法
* @var string[]
*/
protected $noNeedAuth = ['get','check','testmail'];
/**
* 账户设置
* @return Response
* @throws Exception
*/
public function index(): Response
{
$_list = ConfigModel::order('id asc')->select();
$_list = $_list->toArray();
$list = [];
foreach($_list as $k=>$v){
if(!isset($list[$v['group']])){
$list[$v['group']] = [];
}
// if(in_array($v['type'] ,['radio','checkbox','select','selects'] ) && $v['content']){
// $firstLetter = substr($v['content'],0,1);
// if($firstLetter == '[' || $firstLetter == '{'){
// $arr = json_decode($v['content'],true);
// }else{
// $_content = explode("\n",$v['content']);
// $arr = [];
// foreach($_content as $k1=>$v1){
// $_v1 = explode('|',$v1);
// $arr[$_v1[0]]=$_v1[1];
// }
// }
// $v['content'] = $arr;
// }
$list[$v['group']][$v['name']] = $v;
}
//echo json_encode($list,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return view('config/index',[
'configlist' => $list,
'typeList' => [
'string' => '字符串',
'password' => __('密码'),
'text' => __('文本'),
'editor' => __('编辑器'),
'number' => __('数字'),
'date' => __('日期'),
'time' => __('时间'),
'datetime' => __('日期时间'),
'datetimerange' => __('日期时间区间'),
'select' => __('下拉列表'),
'selects' => __('多选下拉列表'),
'image' => __('图片'),
'images' => __('图片(多)'),
'file' => __('文件'),
'files' => __('文件(多)'),
'switch' => __('开关'),
'checkbox' => __('复选'),
'radio' => __('单选'),
'city' => __('城市地区'),
'selectpage' => __('关联表'),
'selectpages' => __('关联表(多选)'),
'array' => __('数组'),
'custom' => __('自定义'),
],
'ruleList' => [
'required' => '必选',
'digits' => '数字',
'letters' => '字母',
'date' => '日期',
'time' => '时间',
'email' => '邮箱',
'url' => '网址',
'qq' => 'QQ号',
'IDcard' => '身份证',
'tel' => '座机电话',
'mobile' => '手机号',
'zipcode' => '邮编',
'chinese' => '中文',
'username' => '用户名',
'password' => '密码'
]
]);
}
/**
* 更改
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function update(Request $request): Response
{
$list = ConfigModel::where(1,1)->select();
$post = $request->post();
$saveData = [];
/**
* @var ConfigModel $v
*/
foreach ($list as $k => $v) {
if(isset($post[$v['name']]) ){
$value = $post[$v['name']];
// if($v['type'] == 'selects'){
// $value = implode(',',$value);
// }
$saveData[] = [
"id"=>$v['id'],
"type"=>$v['type'],
"name"=>$v['name'],
'value'=> $value
];
}
}
$Config = new ConfigModel;
$Config->saveAll($saveData);
$this->buildcache();
return $this->success('保存成功');
}
/**
* 更改
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function insert(Request $request): Response
{
$post = $request->post('row');
Db::startTrans();
try {
if($post['type'] == 'selects'){
$post['value'] = implode(',',$post['value']);
}
$user = ConfigModel::create($post);
Db::commit();
$this->buildcache();
return $this->success('保存成功');
} catch (Exception $e) {
Db::rollback();
return $this->fail($e->getMessage());
}
}
protected function buildcache(){
//缓存
$_list = ConfigModel::Field('name,value,type')->order('id asc')->select();
$_list = $_list->toArray();
$list = [];
foreach($_list as $k=>$v){
if(in_array($v['type'] ,['array']) && !is_array($v['value'])){
$v['value'] = json_decode($v['value'], true);
}
if(in_array($v['type'] ,['selects']) && !is_array($v['value'])){
$v['value'] = explode(',',$v['value']);
}
$list[$v['name']] = $v['value'];
}
$fn = base_path(false) . '/config/site.php';
file_put_contents($fn, "<?php \n return ".var_export($list,true).';');
}
/**
* 颜色检查
* @param string $color
* @return string
* @throws BusinessException
*/
protected function filterColor(string $color): string
{
if (!preg_match('/\#[a-zA-Z]6/', $color)) {
throw new BusinessException('参数错误');
}
return $color;
}
/**
* 配置名称检查
* @param string $color
* @return string
* @throws BusinessException
*/
function check(){
$param = Request()->post('param');
$name = Request()->get('name');
if(ConfigModel::where($name, $param)->count('id')>0){
return $this->fail("已被占用");
}else{
return $this->success();
}
}
/**
* 测试邮件
* @return Response
*/
function testmail(){
$config = Request()->post();
addJob([
'email' => $config['test_mail_address'],
'title' => '这是一封来自'.config('site.name').'的邮件',
'body' => '这是一封来自'.config('site.name').'的校验邮件,用于校验邮件配置是否正常!',
'config' => [
"mail_from"=>$config['mail_from'],
"mail_smtp_host"=>$config['mail_smtp_host'],
"mail_smtp_user"=>$config['mail_smtp_user'],
"mail_smtp_pass"=>$config['mail_smtp_pass'],
"mail_smtp_port"=>$config['mail_smtp_port'],
"mail_verify_type"=>$config['mail_verify_type'],
]
],'Email');
return $this->success($config['test_mail_address']."邮件已经发送");
}
}
+595
View File
@@ -0,0 +1,595 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Tree;
use plugin\admin\app\common\Util;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use support\think\Model;
use support\think\Db;
class Crud extends Base
{
/**
* @var Model
*/
protected $model = null;
/**
* 是否是关联查询
*/
protected $relationSearch = false;
/**
* 是否开启Validate验证
*/
protected $modelValidate = false;
/**
* 是否开启模型场景验证
*/
protected $modelSceneValidate = false;
/**
* Multi方法可批量修改的字段
*/
protected $multiFields = 'status';
/**
* Selectpage可显示的字段
*/
protected $selectpageFields = '*';
/**
* 查询
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
return $this->doFormat($query, $format, $limit);
}
/**
* selectpage
* @param \support\Request $request
*/
public function selectpage(Request $request)
{
$searchValue = $request->input('searchValue');
$searchTable = $request->input('searchTable');
$searchKey = $request->input('searchKey');
$orderBy = $request->input('orderBy');
$showField = $request->input('showField');
$keyField = $request->input('keyField');
$keyValue = $request->input('keyValue');
$searchField = $request->input('searchField');
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
if($searchValue){
$query = $query->whereIn($searchKey,$searchValue);
}
$list = $query->field([$showField,$keyField])->paginate($limit);
return $this->success('ok',$list);
}
function index(Request $request): Response
{
return view();
}
/**
* 添加
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function insert(Request $request): Response
{
if($request->method() == 'POST'){
$data = $this->insertInput($request);
$id = $this->doInsert($data);
$ret = $this->success('操作成功', ['id' => $id]);
return $ret;
}
return view(strtolower(get_controller_name()).'/update');
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function update(Request $request): Response
{
if($request->method() == 'POST'){
[$id, $data] = $this->updateInput($request);
$this->doUpdate($id, $data);
$ret = $this->success('操作成功');
return $ret;
}
$vo = [];
if (!empty($this->model) && $this->relationSearch) {
$name = $this->model->getTable();
$aliasName = $name . '.';
$vo = $this->model->alias($name)->withJoin($this->relationSearch)->whereIn($aliasName.'id',$request->get('ids'))->find();
}else{
$vo = $this->model->whereIn('id',$request->get('ids'))->find();
}
return view('',[
'row' => $vo
]);
}
/**
* 删除
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function delete(Request $request): Response
{
$ids = $this->deleteInput($request);
$this->doDelete($ids);
return $this->success('删除成功');
}
/**
* 查询前置
* @param Request $request
* @return array
* @throws BusinessException
*/
protected function selectInput(Request $request): array
{
$field = $request->input('sort','id');
$order = $request->input('sortOrder', 'asc');
$format = $request->input('format', 'normal');
$limit = (int)$request->input('limit', $format === 'tree' ? 1000 : 10);
$limit = $limit <= 0 ? 10 : $limit;
$order = $order === 'asc' ? 'asc' : 'desc';
$where = $request->input('filter',[]);
$page = (int)$request->input('page');
$page = $page > 0 ? $page : 1;
$allow_column = [];
//var_dump($this->model->getConnectionName());
//if ($this->model->getConnection()->getDriverName() == 'mongodb') {
if ($this->model->getConnection() != 'plugin.admin.mysql') {
} else {
$table = $this->model->getTable();
$allow_column = Util::db()->select("desc `$table`");
if (!$allow_column) {
throw new BusinessException('表不存在');
}
$allow_column = array_column($allow_column, 'Field', 'Field');
if (!in_array($field, $allow_column)) {
$field = null;
}
}
// foreach ($where as $column => $value) {
// if (
// $value === '' || !isset($allow_column[$column]) ||
// is_array($value) && (empty($value) || !in_array($value[0], ['null', 'not null']) && !isset($value[1]))
// ) {
// unset($where[$column]);
// }
// }
// 按照数据限制字段返回数据
if (!Auth::isSuperAdmin()) {
if ($this->dataLimit === 'personal') {
$where[$this->dataLimitField] = ['symbol'=>'=', 'value1'=>admin_id()];
} elseif ($this->dataLimit === 'auth') {
$primary_key = $this->model->getPk();
if (!Auth::isSuperAdmin() && (!isset($where[$primary_key]) || $this->dataLimitField != $primary_key)) {
$where[$this->dataLimitField] = ['symbol'=>'in', 'value1'=>Auth::getScopeAdminIds(true)];
}
}
}
return [$where, $format, $limit, $field, $order, $page];
}
/**
* 指定查询where条件,并没有真正的查询数据库操作
* @param array $where
* @param string|null $field
* @param string $order
* @return Model
*/
protected function doSelect(array $where, string $field = null, string $order = 'desc')
{
$model = $this->model;
$aliasName="";
if (!empty($this->model) && $this->relationSearch) {
$name = $this->model->getTable();
$aliasName = $name . '.';
$model = $model->alias($name)->withJoin($this->relationSearch);
$field = false===strpos($field?:'','.') ? $aliasName.$field : $field;
}
foreach ($where as $column => $value) {
$model = $this->parseOneWhere($model,$column,$value,$aliasName);
}
if ($field) {
$model = $model->order($field, $order);
}
return $model;
}
protected function parseOneWhere($model,$column,$value,$aliasName=''){
$column = false===strpos($column,'.') ? $aliasName.$column : $column;
if (is_array($value)) {
$symbol = isset($value['symbol']) ? $value['symbol'] : '';
$value1 = isset($value['value1']) ? $value['value1'] : '';
$value2 = isset($value['value2']) ? $value['value2'] : '';
if ($symbol === 'like' || $symbol === 'not like') {
$model = $model->where($column, $symbol, "%$value1%");
} elseif (in_array($symbol, ['>', '=', '<', '<>','>=','<='])) {
$model = $model->where($column, $symbol, $value1);
} elseif (($symbol == 'in'|| $symbol == 'not in') && !empty($value1)) {
$valArr = $value1;
if (is_string($value1)) {
$valArr = explode(",", trim($value1));
}
if($symbol == 'in'){
$model = $model->whereIn($column, $valArr);
}else{
$model = $model->whereNotIn($column, $valArr);
}
} elseif ($symbol == 'null') {
$model = $model->whereNull($column);
} elseif ($symbol == 'not null') {
$model = $model->whereNotNull($column);
} elseif ($symbol == 'range' && $$value1 !== '' || $value2 !== '') {
$model = $model->whereBetween($column, [$value1, $value2]);
}
} else {
$model = $model->where($column, $value);
}
return $model;
}
/**
* 执行真正查询,并返回格式化数据
* @param $query
* @param $format
* @param $limit
* @return Response
*/
protected function doFormat($query, $format, $limit,$fields="*"): Response
{
$methods = [
'select' => 'formatSelect',
'tree' => 'formatTree',
'table_tree' => 'formatTableTree',
'normal' => 'formatNormal',
];
if($this->relationSearch){
$fields="";
}
if($limit == 'all'){
$paginator = $query->field($fields)->select();
$total = count($paginator);
$items = $paginator;
}else{
//var_dump($query->field($fields)->buildSql());
$paginator = $query->field($fields)->paginate($limit);
$total = $paginator->total();
$items = $paginator->items();
}
//var_dump($query->getlastsql());
if (method_exists($this, "afterQuery")) {
$items = call_user_func([$this, "afterQuery"], $items);
}
$format_function = $methods[$format] ?? 'formatNormal';
return call_user_func([$this, $format_function], $items, $total);
}
/**
* 插入前置方法
* @param Request $request
* @return array
* @throws BusinessException
*/
protected function insertInput(Request $request): array
{
$data = $this->inputFilter($request->post());
$password_filed = 'password';
if (isset($data[$password_filed])) {
$data[$password_filed] = Util::passwordHash($data[$password_filed]);
}
$password_filed = 'trade_password';
if (isset($data[$password_filed])) {
$data[$password_filed] = Util::passwordHash($data[$password_filed]);
}
if (!Auth::isSuperAdmin()) {
if ($this->dataLimit === 'personal') {
$data[$this->dataLimitField] = admin_id();
} elseif ($this->dataLimit === 'auth') {
if (!empty($data[$this->dataLimitField])) {
$admin_id = $data[$this->dataLimitField];
if (!in_array($admin_id, Auth::getScopeAdminIds(true))) {
throw new BusinessException('无数据权限');
}
} else {
$data[$this->dataLimitField] = admin_id();
}
}
} elseif ($this->dataLimit && empty($data[$this->dataLimitField])) {
$data[$this->dataLimitField] = admin_id();
}
return $data;
}
/**
* 执行插入
* @param array $data
* @return mixed|null
*/
protected function doInsert(array $data)
{
$primary_key = $this->model->getPk();
$model_class = get_class($this->model);
// $model = new $model_class;
// foreach ($data as $key => $val) {
// $model->{$key} = $val;
// }
// $model->save();
$model = $model_class::create($data);
return $primary_key ? $model->$primary_key : null;
}
/**
* 更新前置方法
* @param Request $request
* @return array
* @throws BusinessException
*/
protected function updateInput(Request $request): array
{
$primary_key = $this->model->getPk();
$id = $request->post($primary_key);
$data = $this->inputFilter($request->post());
$model = $this->model->find($id);
if (!$model) {
throw new BusinessException('记录不存在', 2);
}
if (!Auth::isSuperAdmin()) {
if ($this->dataLimit == 'personal') {
if ($model->{$this->dataLimitField} != admin_id()) {
throw new BusinessException('无数据权限');
}
} elseif ($this->dataLimit == 'auth') {
$scopeAdminIds = Auth::getScopeAdminIds(true);
$admin_ids = [
$data[$this->dataLimitField] ?? false, // 检查要更新的数据admin_id是否是有权限的值
$model->{$this->dataLimitField} ?? false // 检查要更新的记录的admin_id是否有权限
];
foreach ($admin_ids as $admin_id) {
if ($admin_id && !in_array($admin_id, $scopeAdminIds)) {
throw new BusinessException('无数据权限');
}
}
}
}
$password_filed = 'password';
if (isset($data[$password_filed])) {
// 密码为空,则不更新密码
if ($data[$password_filed] === '') {
unset($data[$password_filed]);
} else {
$data[$password_filed] = Util::passwordHash($data[$password_filed]);
}
}
$password_filed = 'trade_password';
if (isset($data[$password_filed])) {
// 密码为空,则不更新密码
if ($data[$password_filed] === '') {
unset($data[$password_filed]);
} else {
$data[$password_filed] = Util::passwordHash($data[$password_filed]);
}
}
unset($data[$primary_key]);
return [$id, $data];
}
/**
* 执行更新
* @param $id
* @param $data
* @return void
*/
protected function doUpdate($id, $data)
{
$model = $this->model->find($id);
foreach ($data as $key => $val) {
$model->{$key} = $val;
}
$model->save();
}
/**
* 对用户输入表单过滤
* @param array $data
* @return array
* @throws BusinessException
*/
protected function inputFilter(array $data): array
{
$table = config('plugin.admin.database.connections.mysql.prefix') . $this->model->getTable();
$allow_column = Db::getFields($this->model->getTable());
if (!$allow_column) {
throw new BusinessException('表不存在', 2);
}
//$columns = array_column($allow_column, 'Type', 'Field');
//echo json_encode($allow_column);
foreach ($data as $col => $item) {
if (!isset($allow_column[$col])) {
unset($data[$col]);
continue;
}
// 非字符串类型传空则为null
if ($item === '' && strpos(strtolower($allow_column[$col]['type']), 'varchar') === false && strpos(strtolower($allow_column[$col]['type']), 'text') === false) {
$data[$col] = null;
}
$data[$col] = $item;
// if (is_array($item)) {
// $data[$col] = implode(',', $item);
// }
}
if (empty($data['created_at'])) {
unset($data['created_at']);
}
if (empty($data['updated_at'])) {
unset($data['updated_at']);
}
return $data;
}
/**
* 删除前置方法
* @param Request $request
* @return array
* @throws BusinessException
*/
protected function deleteInput(Request $request): array
{
$primary_key = $this->model->getPk();
if (!$primary_key) {
throw new BusinessException('该表无主键,不支持删除');
}
$ids = $request->post('ids', '');
if(!is_array($ids)){
$ids = explode(',',$ids);
}
if (!Auth::isSuperAdmin()){
$admin_ids = [];
if ($this->dataLimit) {
$admin_ids = $this->model->whereIn($primary_key, $ids)->column($this->dataLimitField);
}
if ($this->dataLimit == 'personal') {
if (!in_array(admin_id(), $admin_ids)) {
throw new BusinessException('无数据权限');
}
} elseif ($this->dataLimit == 'auth') {
if (array_diff($admin_ids, Auth::getScopeAdminIds(true))) {
throw new BusinessException('无数据权限');
}
}
}
return $ids;
}
/**
* 执行删除
* @param array $ids
* @return void
*/
protected function doDelete(array $ids)
{
if (!$ids) {
return;
}
$primary_key = $this->model->getPk();
$this->model->whereIn($primary_key, $ids)->delete();
}
/**
* 格式化树
* @param $items
* @return Response
*/
protected function formatTree($items): Response
{
$format_items = [];
//$primary_key = $this->model->getPk();
$primary_key = $this->model->getPk();
foreach ($items as $item) {
$item->name = $this->guessName($item) ?: $item->$primary_key;
$item->value = (string)$item->$primary_key;
$item->id = $item->$primary_key;
//$item->pid = $item->pid;
$format_items[] = $item;
}
$tree = new Tree($format_items);
return $this->success('ok', $tree->getTree());
}
/**
* 格式化表格树
* @param $items
* @return Response
*/
protected function formatTableTree($items): Response
{
$tree = new Tree($items);
return $this->success('ok', $tree->getTree());
}
/**
* 格式化下拉列表
* @param $items
* @return Response
*/
protected function formatSelect($items): Response
{
$formatted_items = [];
$primary_key = $this->model->getPk();
foreach ($items as $item) {
$formatted_items[] = [
'name' => $this->guessName($item) ?: $item->$primary_key,
'value' => $item->$primary_key
];
}
return $this->success('ok', $formatted_items);
}
/**
* 通用格式化
* @param $items
* @param $total
* @return Response
*/
protected function formatNormal($items, $total): Response
{
return json(['code' => 0, 'msg' => 'ok', 'count' => $total, 'data' => $items]);
}
/**
* 查询数据库后置方法,可用于修改数据
* @param mixed $items 原数据
* @return mixed 修改后数据
*/
protected function afterQuery($items)
{
return $items;
}
/**
* 猜测记录名称
* @param $item
* @return mixed
*/
protected function guessName($item)
{
return $item->title ?? $item->name ?? $item->nickname ?? $item->username ?? $item->id;
}
/**
* 批量操作
* @param $item
* @return mixed
*/
function multi(){
$ids = Request()->post('ids');
$params = Request()->post('params');
parse_str($params,$s);
if(!is_array($ids)){
$ids = explode(',',$ids);
}
$this->model->whereIn('id', $ids)->update($s);
return $this->success('操作成功');
}
}
@@ -0,0 +1,30 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
class DevController extends Base
{
/**
* 无需登录的方法
* @var string[]
*/
protected $noNeedLogin = [''];
/**
* 不需要鉴权的方法
* @var string[]
*/
protected $noNeedAuth = ['*'];
public function index()
{
if(request()->method() == 'POST'){
return '<pre>'.var_export(Request()->post(),true).'</pre>';
}
return view('dev/index',[
]);
}
}
@@ -0,0 +1,45 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
/**
* 礼品卡管理
*
* @icon fa fa-circle-o
*/
class GiftController extends Crud
{
/**
* Product模型对象
* @var \app\model\Gift
*/
protected $model = null;
protected $type = 'default';
protected $noNeedAuth = [];
function __construct()
{
$this->model = new \app\model\Gift;
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
}
public function insert(Request $request): Response
{
if ($request->method() != 'POST') {
return view('update',[
'row' => [
'price' => '10',
'max_quantity' => 0,
'status' => 1
]
]);
}
return parent::insert($request);
}
}
@@ -0,0 +1,31 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
/**
* 礼品记录
*
* @icon fa fa-circle-o
*/
class GiftOrderController extends Crud
{
/**
* GiftOrder模型对象
* @var \app\model\GiftOrder
*/
protected $model = null;
protected $relationSearch = ['user','gift'];
function __construct()
{
$this->model = new \app\model\GiftOrder();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
}
}
@@ -0,0 +1,160 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\common\Util;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Exception;
use support\think\Db;
use Workerman\Worker;
class IndexController extends Base
{
/**
* 无需登录的方法
* @var string[]
*/
protected $noNeedLogin = ['index'];
/**
* 不需要鉴权的方法
* @var string[]
*/
protected $noNeedAuth = ['dashboard','upload'];
/**
* 后台主页
* @param Request $request
* @return Response
* @throws BusinessException|Exception
*/
public function index(Request $request): Response
{
clearstatcache();
$admin = admin();
if (!$admin) {
$title = config('site.name') ?? 'admin';
$logo = cdnurl(config('site.admin_logo') ?? '/app/admin/images/logo.png');
return view('account/login',['logo'=>$logo,'title'=>$title]);
}
//缓存
$list = (new AdminRuleController())->get($request)->rawBody();
//return $this->success($list);
$list = json_decode($list,true);
$menu = $list['data'];
return view('index/index',[
'menu' => $menu,
'user' => admin()
]);
}
/**
* 仪表板
* @param Request $request
* @return Response
* @throws Exception
*/
public function dashboard(Request $request): Response
{
// 今日新增充值
//$today_user_recharge_sum = Recharge::where('status',2)->whereTime('created_at', 'today')->sum('amount');
// 7天内新增充值
$day7_user_recharge_sum = 0;
for ($i=7; $i >= 0; $i--) {
$date = date('Y-m-d',strtotime('-'.$i.' days'));
$day7_user_recharge_sum +=cache('statistics_recharge_amount_'.$date);
}
//$day7_user_recharge_sum = Recharge::where('status',2)->whereTime('created_at', '-7 days')->sum('amount');
// 总用户数
$user_count = \app\model\User::where('status',1)->count('id');
$recharge_total = \app\model\Recharge::where('status',\app\enum\RechargeStatus::COMPLETE->value)->sum('amount');
// mysql版本
$withdrawl_total = \app\model\Withdrawl::where('status',\app\enum\WithdrawlStatus::COMPLETE->value)->sum('recive_amount');
// mysql版本
$version = Db::query('select VERSION() as version');
$mysql_version = $version[0]['version'] ?? 'unknown';
// $recharge = \app\model\Recharge::where('status',2)->field("FROM_UNIXTIME(created_at, '%Y-%m-%d') AS label, sum(amount) AS value")
// ->limit(0,30)->group("label")
// ->select()->toArray();
// $withdrawl = \app\model\Withdrawl::where('status',2)->field("FROM_UNIXTIME(created_at, '%Y-%m-%d') AS label, sum(recive_amount) AS value")
// ->limit(0,30)->group("label")
// ->select()->toArray();
// // if(!cache('last_jiaquan_time')){
// cache('last_jiaquan_time',strtotime('2025-02-27 00:51:00'));
// }
return view('index/dashboard', [
'today_user_recharge_sum' => formatAmount(cache('statistics_recharge_amount_'.date('Y-m-d')),0),
'day7_user_recharge_sum' => formatAmount($day7_user_recharge_sum,0),
'user_count' => $user_count,
//'recharge' => $recharge,
//'withdrawl' => $withdrawl,
'recharge_total' => formatAmount($recharge_total,0),
'withdrawl_total' => formatAmount($withdrawl_total,0),
'user_score_total' => formatAmount(\app\model\User::sum('score')),
'user_money_total' => formatAmount(\app\model\User::sum('money')),
'php_version' => PHP_VERSION,
'workerman_version' => Worker::VERSION,
'webman_version' => Util::getPackageVersion('workerman/webman-framework'),
'admin_version' => config('plugin.admin.app.version'),
'mysql_version' => $mysql_version,
'os' => PHP_OS,
]);
}
function clean(){
return $this->success('');
}
function role_buy_lines()
{
$res = [];
for ($i=7; $i >= 0; $i--) {
$date = date('Y-m-d',strtotime('-'.$i.' days'));
$res[$date] = [
'amount' => cache('role_buy_amount_total_'.$date)?:0,
'reward' => cache('role_buy_reward_total_'.$date)?:0,
'residual' => cache('role_buy_residual_total_'.$date)?:0,
];
}
return $this->success('ok',$res);
}
function recharge_lines()
{
$res = [];
for ($i=7; $i >= 0; $i--) {
$date = date('Y-m-d',strtotime('-'.$i.' days'));
$res[$date] = [
'amount' => cache('statistics_recharge_amount_'.$date)?:0,
];
}
return $this->success('ok',$res);
}
function withdrawl_lines()
{
$res = [];
for ($i=7; $i >= 0; $i--) {
$date = date('Y-m-d',strtotime('-'.$i.' days'));
$res[$date] = [
'amount' => cache('statistics_withdrawl_amount_'.$date)?:0,
];
}
return $this->success('ok',$res);
}
function money_lines()
{
$res = [];
for ($i=7; $i >= 0; $i--) {
$date = date('Y-m-d',strtotime('-'.$i.' days'));
$res[$date] = [
'withdrawl' => cache('statistics_withdrawl_amount_'.$date)?:0,
'recharge' => cache('statistics_recharge_amount_'.$date)?:0,
];
}
return $this->success('ok',$res);
}
}
@@ -0,0 +1,39 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
class InvitecodeController extends Crud
{
/**
* 无需登录的方法
* @var string[]
*/
protected $noNeedLogin = [''];
/**
* 不需要鉴权的方法
* @var string[]
*/
protected $noNeedAuth = ['*'];
/**
* Invitecode模型对象
* @var \app\model\Invitecode
*/
protected $model = null;
function __construct()
{
$this->model = new \app\model\Invitecode();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
}
public function index(Request $request):Response
{
return view();
}
}
@@ -0,0 +1,54 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
/**
* 产品管理
*
* @icon fa fa-circle-o
*/
class ProductController extends Crud
{
/**
* Product模型对象
* @var \app\model\Product
*/
protected $model = null;
protected $type = 'default';
protected $noNeedAuth = [];
function __construct()
{
$this->model = new \app\model\Product;
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$cycleTypeList = $this->model->getCycleTypeList();
$this->assign("cycleTypeList", $cycleTypeList);
$this->assignconfig("cycleTypeList", $cycleTypeList);
$this->assign("CategoryOptions", $this->model->getCategoryOptions($this->type));
}
public function insert(Request $request): Response
{
if ($request->method() != 'POST') {
return view('update',[
'row' => [
'price' => '10',
'interest_rate' => '10',
'cycle_type' => 'day',
'duration_cycle' => 1,
'billing_cycle' => 1,
'max_quantity' => 0,
'interest_type' => 30,
'status' => 1
]
]);
}
return parent::insert($request);
}
}
@@ -0,0 +1,86 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Base;
use plugin\admin\app\controller\Crud;
use app\model\ProductOrder;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 工作室
*/
class ProductOrderController extends Crud
{
/**
* @var ProductOrder
*/
protected $model = null;
protected $relationSearch = ['user','product'];
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new ProductOrder();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
}
public function team(Request $request): Response
{
return view();
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('productorder/index');
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
return parent::insert($request);
}
return view('productorder/update',[
'row' => \plugin\admin\app\model\User::findOrEmpty(0)
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'POST') {
[$id, $data] = $this->updateInput($request);
$this->doUpdate($id, $data);
$ret = $this->success('操作成功');
return $ret;
}
$ids = Request()->get('ids');
$user = $this->model->where('id',$ids)->find();
return view('productorder/update',[
'row' => $user
]);
}
}
@@ -0,0 +1,68 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use Symfony\Component\Console\Input\Input;
use support\think\Db;
/**
* 问卷管理
*
* @icon fa fa-circle-o
*/
class QuestionnaireController extends Crud
{
/**
* Product模型对象
* @var \app\model\Questionnaire
*/
protected $model = null;
protected $noNeedAuth = [];
protected $relationSearch = ['category'];
function __construct()
{
$this->model = new \app\model\Questionnaire;
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$categoryList = $this->model->getCategoryOptions();
$this->assign("categoryList", $categoryList);
$this->assignconfig("categoryList", $categoryList);
}
/**
* selectpage
* @param \support\Request $request
*/
function selectpage(Request $request)
{
$searchValue = $request->input('searchValue');
$searchTable = $request->input('searchTable');
$searchKey = $request->input('searchKey');
$orderBy = $request->input('orderBy');
$showField = $request->input('showField');
$keyField = $request->input('keyField');
$keyValue = $request->input('keyValue');
$searchField = $request->input('searchField');
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
$ids = \app\model\Product::distinct(true)->column('questionnaire_id');
if($keyValue && $keyField){
$query = $query->whereIn($keyField,$keyValue);
$ids =array_diff([$keyValue?:0],$ids);
}
if($showField && input($showField)){
$query = $query->whereLike($showField,'%'.input($showField).'%');
}
//log_alert($ids,'cansnow');
$query = $query->whereNotIn('id',$ids);
$list = $query->field([$showField,$keyField])->paginate($limit);
//log_alert($query->getLastSql(),'cansnow');
return $this->success('ok',$list);
}
}
@@ -0,0 +1,32 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
/**
* 用户充值
*/
class RechargeController extends Crud
{
/**
* @var \app\model\Recharge
*/
protected $model = null;
protected $relationSearch = ['user'];
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new \app\model\Recharge();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$this->assign("networkList", $this->model->getNetworkList());
$this->assignconfig("networkList", $this->model->getNetworkList());
}
}
@@ -0,0 +1,19 @@
<?php
namespace plugin\admin\app\controller;
use support\Request;
use support\Response;
use support\think\Db;
/**
* 单页管理
*
* @icon fa fa-circle-o
*/
class SinglePageController extends ArchivesController
{
protected $type = 'page';
protected $tpl = 'singlepage';
protected $relationSearch = [];
}
@@ -0,0 +1,95 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
use plugin\admin\app\model\User as UserModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 工作室
*/
class StudioController extends Crud
{
/**
* @var UserModel
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new UserModel();
$groupList = [
['value'=>0,'label'=>"普通用户"],
['value'=>1,'label'=>"工作室"],
];
$roleList = \app\model\UserRole::order('id','desc')->column('name as label,id as value');
$this->assign('groupList',$groupList);
$this->assignconfig('groupList',$groupList);
$this->assign('roleList',$roleList);
$this->assignconfig('roleList',$roleList);
}
public function team(Request $request): Response
{
return view();
}
public function select(Request $request): Response
{
$this->model = $this->model->with(['referrer','role'])->where('wa_user.group',1);
return parent::select($request);
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('user/index');
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
return parent::insert($request);
}
return view('user/update',[
'row' => UserModel::findOrEmpty(0)
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'POST') {
[$id, $data] = $this->updateInput($request);
$this->doUpdate($id, $data);
$ret = $this->success('操作成功');
return $ret;
}
$ids = Request()->get('ids');
$user = $this->model->where('id',$ids)->find();
return view('user/update',[
'row' => $user
]);
}
}
@@ -0,0 +1,59 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Crud;
use plugin\admin\app\model\User;
use support\exception\BusinessException;
use support\Request;
use support\Response;
/**
* 用户管理
*/
class TeamController extends Crud
{
/**
* @var User
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new User();
}
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
//log_alert($where);
$user_id = 0;
if($where['user_id']['value1']){
$user_id = $where['user_id']['value1'];
}
if($where['type']['value1'] == 'child'){
$list = \app\model\UserTeam::alias('ut')
->join('user u', 'ut.descendant_id = u.id')
->where('ut.ancestor_id', $user_id)
->field('ut.depth,u.*')
->order('ut.depth asc')
->paginate(10);
}
if($where['type']['value1'] == 'tree'){
$list = \app\model\UserTeam::alias('ut')
->join('user u', 'ut.ancestor_id = u.id')
->where('ut.descendant_id', $user_id)
->field('ut.depth,u.*')
->order('ut.depth asc')
->paginate(10);
}
$total = $list->total();
$items = $list->items();
return $this->formatNormal($items,$total);
}
}
@@ -0,0 +1,97 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Base;
use plugin\admin\app\controller\Crud;
use plugin\admin\app\model\User as UserModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 用户管理
*/
class UserController extends Crud
{
/**
* @var UserModel
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new UserModel();
$groupList = [
['value'=>0,'label'=>"普通用户"],
['value'=>1,'label'=>"内部用户"],
['value'=>2,'label'=>"联盟商"],
];
$roleList = \app\model\UserRole::order('id','desc')->column('name as label,id as value');
$this->assign('groupList',$groupList);
$this->assignconfig('groupList',$groupList);
$this->assign('roleList',$roleList);
$this->assignconfig('roleList',$roleList);
}
public function team(Request $request): Response
{
return view();
}
public function select(Request $request): Response
{
$this->model = $this->model->with(['referrer','role']);
return parent::select($request);
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('user/index');
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
return parent::insert($request);
}
return view('user/update',[
'row' => UserModel::findOrEmpty(0)
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'POST') {
[$id, $data] = $this->updateInput($request);
$this->doUpdate($id, $data);
$ret = $this->success('操作成功');
return $ret;
}
$ids = Request()->get('ids');
$user = $this->model->where('id',$ids)->find();
return view('user/update',[
'row' => $user
]);
}
}
@@ -0,0 +1,286 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Tree;
use app\model\UserRole as UserRoleModel;
use app\model\UserRule as UserRuleModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 角色管理
*/
class UserRoleController extends Crud
{
/**
* 不需要鉴权的方法
* @var array
*/
protected $noNeedAuth = ['select'];
/**
* @var UserRoleModel
*/
protected $model = null;
/**
* 构造函数
*/
function __construct()
{
$this->model = new UserRoleModel;
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('user_role/index');
}
/**
* 查询
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$limit = 100000;
$query = $this->doSelect($where, $field, $order);
return $this->doFormat($query, $format, $limit);
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException
* @throws Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
$data = $this->insertInput($request);
$pid = $data['pid'] ?? null;
// if (!$pid) {
// return $this->fail('请选择父级角色组');
// }
if($pid){
if (!Auth::isSuperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) {
return $this->fail('父级角色组超出权限范围');
}
}
$this->checkRules($pid, $data['rules'] ?? '');
$id = $this->doInsert($data);
return $this->success("操作成功", ['id' => $id]);
}
return view('user_role/update',[
'rolelist'=> $this->model->select()
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'GET') {
return view('user_role/update',[
'rolelist'=> $this->model->select(),
'row' => $this->model->whereIn('id',Request()->get('ids'))->findOrEmpty()
]);
}
[$id, $data] = $this->updateInput($request);
$is_supper_admin = Auth::isSuperAdmin();
$descendant_role_ids = Auth::getScopeRoleIds();
$role = UserRoleModel::find($id);
if (!$role) {
return $this->fail('数据不存在');
}
if (key_exists('pid', $data) && $data['pid']) {
$pid = $data['pid'];
// if (!$pid) {
// return $this->fail('请选择父级角色组');
// }
if ($pid == $id) {
return $this->fail('父级不能是自己');
}
if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) {
return $this->fail('父级超出权限范围');
}
} else {
$pid = $role->pid;
}
$this->checkRules($pid, $data['rules'] ?? '');
$this->doUpdate($id, $data);
// 删除所有子角色组中已经不存在的权限
$tree = new Tree(UserRoleModel::field(['id', 'pid'])->select());
$descendant_roles = $tree->getDescendant([$id]);
$descendant_role_ids = array_column($descendant_roles, 'id');
$rule_ids = $data['rules'] ? explode(',', $data['rules']) : [];
foreach ($descendant_role_ids as $role_id) {
$tmp_role = UserRoleModel::find($role_id);
$tmp_rule_ids = $role->getRuleIds();
$tmp_rule_ids = array_intersect(explode(',',$tmp_role->rules), $tmp_rule_ids);
$tmp_role->rules = implode(',', $tmp_rule_ids);
$tmp_role->save();
}
return $this->success("操作成功");
}
/**
* 删除
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function delete(Request $request): Response
{
$ids = $this->deleteInput($request);
if (in_array(1, $ids)) {
return $this->fail('无法删除超级管理员角色');
}
if (!Auth::isSuperAdmin() && array_diff($ids, Auth::getScopeRoleIds())) {
return $this->fail('无删除权限');
}
$tree = new Tree(UserRoleModel::select());
$descendants = $tree->getDescendant($ids);
if ($descendants) {
$ids = array_merge($ids, array_column($descendants, 'id'));
}
$this->doDelete($ids);
return $this->success("操作成功");
}
/**
* 获取角色权限
* @param Request $request
* @return Response
*/
public function rules(Request $request): Response
{
$role_id = $request->get('id');
if (empty($role_id)) {
return $this->success("操作成功", []);
}
if (!Auth::isSuperAdmin() && !in_array($role_id, Auth::getScopeRoleIds(true))) {
return $this->fail('角色组超出权限范围');
}
$rule_id_string = UserRoleModel::where('id', $role_id)->value('rules');
if ($rule_id_string === '') {
return $this->success("操作成功", []);
}
$rules = UserRuleModel::select();
$include = [];
if ($rule_id_string !== '*') {
$include = explode(',', $rule_id_string);
}
$items = [];
foreach ($rules as $item) {
$items[] = [
'name' => $item->title ?? $item->name ?? $item->id,
'value' => (string)$item->id,
'id' => $item->id,
'pid' => $item->pid,
];
}
$tree = new Tree($items);
return $this->success("操作成功", $tree->getTree($include));
}
/**
* 检查权限字典是否合法
* @param int $role_id
* @param $rule_ids
* @return void
* @throws BusinessException
*/
protected function checkRules(int|string|null $role_id, $rule_ids)
{
if ($rule_ids && $role_id>0) {
$rule_ids = explode(',', $rule_ids);
if (in_array('*', $rule_ids)) {
throw new BusinessException('非法数据');
}
$rule_exists = UserRuleModel::whereIn('id', $rule_ids)->column('id');
if (count($rule_exists) != count($rule_ids)) {
throw new BusinessException('权限不存在');
}
$rule_id_string = UserRoleModel::where('id', $role_id)->value('rules');
if ($rule_id_string === '') {
throw new BusinessException('数据超出权限范围');
}
if ($rule_id_string === '*') {
return;
}
$legal_rule_ids = explode(',', $rule_id_string);
if (array_diff($rule_ids, $legal_rule_ids)) {
throw new BusinessException('数据超出权限范围');
}
}
}
public function tree(Request $request): Response
{
$id = $request->post('id');
$pid = $request->post('pid');
$parent_rules = '*';
if($pid){
$parent_rules = UserRoleModel::where('id', $pid)->value('rules') ?: '';
}
if($parent_rules == '*'){
$rules = UserRuleModel::where('status',1)->Field('id,title as text,pid as parent,"menu" as type')->select();
}else{
$rules = UserRuleModel::whereIn('id', $parent_rules)->where('status',1)->Field('id,title as text,pid as parent,"menu" as type')->select();
}
$selected_ids = '';
if($id){
$selected_ids = UserRoleModel::where('id', $id)->value('rules') ?:'';
}
if($selected_ids == '*'){
$rules->each(function($item){
$item->state = ['selected'=>false];
return $item;
});
}else{
$selected_ids = explode(',',$selected_ids);
$rules->each(function($item)use($selected_ids){
$state = ['selected'=>false];
if(in_array($item->id, $selected_ids)){
$state['selected'] = true;
}
$item->state = $state;
// if($item->parent == 0){
// $item->parent = '#';
// }
return $item;
});
}
$rules->push([
'id' => 0,
'parent' => '#',
'text' => '全部',
'type' => 'menu',
]);
return $this->success('ok',$rules);
}
}
@@ -0,0 +1,413 @@
<?php
namespace plugin\admin\app\controller;
use Exception;
use Illuminate\Support\Facades\Date;
use plugin\admin\app\common\Tree;
use plugin\admin\app\common\Util;
use app\model\UserRole;
use app\model\UserRule;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 权限菜单
*/
class UserRuleController extends Crud
{
/**
* 不需要权限的方法
*
* @var string[]
*/
protected $noNeedAuth = ['get', 'permission'];
/**
* @var UserRule
*/
protected $model = null;
/**
* 构造函数
*/
function __construct()
{
$this->model = new UserRule;
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('user_rule/index');
}
/**
* 权限树形
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function roletree(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
$methods = [
'select' => 'formatSelect',
'tree' => 'formatTree',
'table_tree' => 'formatTableTree',
'normal' => 'formatNormal',
];
$format = 'normal';
$items = $query->field('id,title as text,pid as parent,"menu" as type')->select();
/**
* @var UserRule $item
*/
foreach ($items as $key => $item) {
$items[$key]->state = [
"selected" => false,
];
if($items[$key]->parent == 0){
$items[$key]->parent = '#';
}
};
if (method_exists($this, "afterQuery")) {
$items = call_user_func([$this, "afterQuery"], $items);
}
$format_function = $methods[$format] ?? 'formatNormal';
return call_user_func([$this, $format_function], $items, 0);
}
/**
* 查询
* @param Request $request
* @return Response
* @throws BusinessException
*/
public function select(Request $request): Response
{
[$where, $format, $limit, $field, $order] = $this->selectInput($request);
$query = $this->doSelect($where, $field, $order);
return $this->doFormat($query, $format, 'all');
//return parent::select($request);
}
/**
* 获取菜单
* @param Request $request
* @return Response
* @throws Exception
*/
function get(Request $request): Response
{
$rules = $this->getRules(admin('roles'));
$types = $request->get('type', '0,1');
$types = is_string($types) ? explode(',', $types) : [0, 1];
$items = UserRule::order('weight', 'desc')->select();
$formatted_items = [];
/**
* @var UserRule $item
*/
foreach ($items as $item) {
$item['pid'] = (int)$item['pid'];
$item['name'] = $item['title'];
$item['value'] = $item['id'];
$item['icon'] = $item['icon'] ? "layui-icon {$item->icon}" : '';
$formatted_items[] = $item;
}
$tree = new Tree($formatted_items);
$tree_items = $tree->getTree();
// 超级管理员权限为 *
if (!in_array('*', $rules)) {
$this->removeNotContain($tree_items, 'id', $rules);
}
$this->removeNotContain($tree_items, 'type', $types);
$menus = $this->empty_filter(Tree::arrayValues($tree_items));
return $this->success("操作成功", $menus);
}
private function empty_filter($menus)
{
return array_map(
function ($menu) {
if (isset($menu['children'])) {
$menu['children'] = $this->empty_filter($menu['children']);
}
return $menu;
},
array_values(array_filter(
$menus,
function ($menu) {
return $menu['type'] != 0 || isset($menu['children']) && count($this->empty_filter($menu['children'])) > 0;
}
))
);
}
/**
* 获取权限
* @param Request $request
* @return Response
* @throws Exception
*/
public function permission(Request $request): Response
{
$rules = $this->getRules(admin('roles'));
// 超级管理员
if (in_array('*', $rules)) {
return $this->success("操作成功", ['*']);
}
$keys = UserRule::whereIn('id', $rules)->column('key');
$permissions = [];
foreach ($keys as $key) {
if (!$key = Util::controllerToUrlPath($key)) {
continue;
}
$code = str_replace('/', '.', trim($key, '/'));
$permissions[] = $code;
}
return $this->success("操作成功", $permissions);
}
/**
* 根据类同步规则到数据库
* @return void
*/
public function syncRules(): Response
{
//$items = $this->model->where('key', 'like', '%\\\\%')->get()->keyBy('key');
$items = $this->model->whereLike('key', '%\\\\%')->select();
$methods_in_db = [];
$methods_in_files = [];
/**
* @var UserRule $item
*/
foreach ($items as $item) {
$class = $item->key;
if (strpos($class, '@')) {
$methods_in_db[$class] = $class;
continue;
}
if (class_exists($class)) {
$reflection = new \ReflectionClass($class);
$properties = $reflection->getDefaultProperties();
$no_need_auth = array_merge($properties['noNeedLogin'] ?? [], $properties['noNeedAuth'] ?? []);
$class = $reflection->getName();
$pid = $item->id;
$methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$method_name = $method->getName();
if (strtolower($method_name) === 'index' || strpos($method_name, '__') === 0 || in_array($method_name, $no_need_auth)) {
continue;
}
$name = "$class@$method_name";
$methods_in_files[$name] = $name;
$title = Util::getCommentFirstLine($method->getDocComment()) ?: $method_name;
/**
* @var UserRule $item
*/
$menu = $items[$name] ?? [];
if ($menu) {
if ($menu->title != $title) {
UserRule::where('key', $name)->update(['title' => $title]);
}
continue;
}
$menu = new UserRule;
$menu->pid = $pid;
$menu->key = $name;
$menu->title = $title;
$menu->type = 2;
$menu->save();
}
}
}
// 从数据库中删除已经不存在的方法
$menu_names_to_del = array_diff($methods_in_db, $methods_in_files);
if ($menu_names_to_del) {
UserRule::whereIn('key', $menu_names_to_del)->delete();
}
return $this->success("操作成功");
}
/**
* 查询前置方法
* @param Request $request
* @return array
* @throws BusinessException
*/
protected function selectInput(Request $request): array
{
[$where, $format, $limit, $field, $order] = parent::selectInput($request);
// 允许通过type=0,1格式传递菜单类型
$types = $request->get('type');
if ($types && is_string($types)) {
$where['type'] = ['symbol'=>'in', 'value1'=>explode(',', $types)];
}
// 默认weight排序
if (!$field) {
$field = 'weight';
$order = 'desc';
}
return [$where, $format, $limit, $field, $order];
}
/**
* 添加
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'GET') {
$RuleList = $this->model->where('status',1)->order('id asc')->select();
$tree = new Tree($RuleList);
return view('user_rule/update',[
'RuleList' => $tree->getTree()
]);
}
$data = $this->insertInput($request);
if (empty($data['type'])) {
$data['type'] = strpos($data['key'], '\\') ? 1 : 0;
}
$data['key'] = str_replace('\\\\', '\\', $data['key']);
$key = $data['key'] ?? '';
if ($this->model->where('key', $key)->count('id')) {
return $this->fail("菜单标识 $key 已经存在");
}
$data['pid'] = empty($data['pid']) ? 0 : $data['pid'];
$this->doInsert($data);
return $this->success("操作成功");
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'GET') {
$RuleList = $this->model->where('status',1)->order('id asc')->select();
$ids = Request()->get('ids');
$tree = new Tree($RuleList);
return view('user_rule/update',[
'RuleList' => $tree->getTree(),
'row' => $this->model->where('id',$ids)->find()
]);
}
[$id, $data] = $this->updateInput($request);
if (!$row = $this->model->find($id)) {
return $this->json(2, '记录不存在');
}
if (isset($data['pid'])) {
$data['pid'] = $data['pid'] ?: 0;
if ($data['pid'] == $row['id']) {
return $this->json(2, '不能将自己设置为上级菜单');
}
}
if (isset($data['key'])) {
$data['key'] = str_replace('\\\\', '\\', $data['key']);
}
$this->doUpdate($id, $data);
return $this->success("操作成功");
}
/**
* 删除
* @param Request $request
* @return Response
*/
public function delete(Request $request): Response
{
$ids = $this->deleteInput($request);
// 子规则一起删除
$delete_ids = $children_ids = $ids;
while($children_ids) {
$children_ids = $this->model->whereIn('pid', $children_ids)->column('id');
$delete_ids = array_merge($delete_ids, $children_ids);
}
$this->doDelete($delete_ids);
return $this->success("操作成功");
}
/**
* 移除不包含某些数据的数组
* @param $array
* @param $key
* @param $values
* @return void
*/
protected function removeNotContain(&$array, $key, $values)
{
foreach ($array as $k => &$item) {
if (!is_array($item)) {
continue;
}
if (!$this->arrayContain($item, $key, $values)) {
unset($array[$k]);
} else {
if (!isset($item['children'])) {
continue;
}
$this->removeNotContain($item['children'], $key, $values);
}
}
}
/**
* 判断数组是否包含某些数据
* @param $array
* @param $key
* @param $values
* @return bool
*/
protected function arrayContain(&$array, $key, $values): bool
{
if (!is_array($array)) {
return false;
}
if (isset($array[$key]) && in_array($array[$key], $values)) {
return true;
}
if (!isset($array['children'])) {
return false;
}
foreach ($array['children'] as $item) {
if ($this->arrayContain($item, $key, $values)) {
return true;
}
}
return false;
}
/**
* 获取权限规则
* @param $roles
* @return array
*/
protected function getRules($roles): array
{
$rules_strings = $roles ? UserRole::whereIn('id', $roles)->column('rules') : [];
$rules = [];
foreach ($rules_strings as $rule_string) {
if (!$rule_string) {
continue;
}
$rules = array_merge($rules, explode(',', $rule_string));
}
return $rules;
}
}
@@ -0,0 +1,66 @@
<?php
namespace plugin\admin\app\controller;
use app\model\User;
use plugin\admin\app\controller\Crud;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 用户提现
*/
class WithdrawlController extends Crud
{
/**
* @var \plugin\admin\app\model\Withdrawl
*/
protected $model = null;
protected $relationSearch = ['user'];
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new \plugin\admin\app\model\Withdrawl();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$networkList = $this->model->getNetworkList();
$this->assign("networkList", $networkList);
$this->assignconfig("networkList", $networkList);
}
protected function formatNormal($items, $total): Response
{
return json([
'code' => 0,
'msg' => 'ok',
'count' => $total,
'data' => $items,
'wait_amount' => \app\model\Withdrawl::where('status',0)->sum('recive_amount'),
'wait_count' => \app\model\Withdrawl::where('status',0)->count('id')
]);
}
function multi(){
$ids = Request()->post('ids');
$params = Request()->post('params');
parse_str($params,$s);
if(!is_array($ids)){
$ids = explode(',',$ids);
}
//$this->model = new \app\model\Withdrawl1;
foreach ($ids as $id){
if(\app\model\Withdrawl::where('id',$id)->value('status')!=$s['status']){
$this->doUpdate($id, $s);
}
}
return $this->success('操作成功');
}
}
@@ -0,0 +1,96 @@
<?php
namespace plugin\admin\app\controller;
use plugin\admin\app\controller\Base;
use plugin\admin\app\controller\Crud;
use app\model\WorkRecord;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 工作室
*/
class WorkRecordController extends Crud
{
/**
* @var WorkRecord
*/
protected $model = null;
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new WorkRecord();
$groupList = [
['value'=>0,'label'=>"普通用户"],
['value'=>1,'label'=>"工作室"],
];
$roleList = \app\model\UserRole::order('id','desc')->column('name as label,id as value');
$this->assign('groupList',$groupList);
$this->assignconfig('groupList',$groupList);
$this->assign('roleList',$roleList);
$this->assignconfig('roleList',$roleList);
}
public function team(Request $request): Response
{
return view();
}
public function select(Request $request): Response
{
$this->model = $this->model->with(['product','questionnaire']);
return parent::select($request);
}
/**
* 浏览
* @return Response
* @throws Throwable
*/
public function index(Request $request): Response
{
return view('productorder/index');
}
/**
* 插入
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function insert(Request $request): Response
{
if ($request->method() === 'POST') {
return parent::insert($request);
}
return view('productorder/update',[
'row' => \plugin\admin\app\model\User::findOrEmpty(0)
]);
}
/**
* 更新
* @param Request $request
* @return Response
* @throws BusinessException|Throwable
*/
public function update(Request $request): Response
{
if ($request->method() === 'POST') {
[$id, $data] = $this->updateInput($request);
$this->doUpdate($id, $data);
$ret = $this->success('操作成功');
return $ret;
}
$ids = Request()->get('ids');
$user = $this->model->where('id',$ids)->find();
return view('productorder/update',[
'row' => $user
]);
}
}
@@ -0,0 +1,38 @@
<?php
namespace plugin\admin\app\controller;
use app\model\User;
use plugin\admin\app\controller\Crud;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;
/**
* 用户宣传
*/
class XuanchuanController extends Crud
{
/**
* @var \app\model\UserXuanchuan
*/
protected $model = null;
protected $relationSearch = ['user'];
/**
* 构造函数
* @return void
*/
function __construct()
{
$this->model = new \app\model\UserXuanchuan();
$statusList = $this->model->getStatusList();
$this->assign("statusList", $statusList);
$this->assignconfig("statusList", $statusList);
$typeList = $this->model->getTypeList();
$this->assign("typeList", $typeList);
$this->assignconfig("typeList", $typeList);
}
}