mirror of https://gitee.com/karson/fastadmin.git
491 lines
16 KiB
PHP
491 lines
16 KiB
PHP
<?php
|
|
|
|
namespace app\admin\controller;
|
|
|
|
use app\common\controller\Backend;
|
|
use fast\Random;
|
|
use fast\Tree;
|
|
use RecursiveDirectoryIterator;
|
|
use RecursiveIteratorIterator;
|
|
use think\Cache;
|
|
use think\Config;
|
|
use think\Db;
|
|
use think\Lang;
|
|
|
|
/**
|
|
* Ajax异步请求接口
|
|
* @internal
|
|
*/
|
|
class Ajax extends Backend
|
|
{
|
|
|
|
protected $noNeedLogin = ['lang'];
|
|
protected $noNeedRight = ['*'];
|
|
protected $layout = '';
|
|
|
|
/**
|
|
* 自动完成
|
|
*/
|
|
public function typeahead()
|
|
{
|
|
$search = $this->request->get("search");
|
|
$field = $this->request->get("field");
|
|
$field = str_replace(['row[', ']'], '', $field);
|
|
if (substr($field, -3) !== '_id' && substr($field, -4) !== '_ids')
|
|
{
|
|
$this->code = -1;
|
|
return;
|
|
}
|
|
$searchfield = 'name';
|
|
$fieldArr = explode('_', $field);
|
|
$field = $fieldArr[0];
|
|
switch ($field)
|
|
{
|
|
case 'category':
|
|
$field = 'category';
|
|
$searchfield = 'name';
|
|
break;
|
|
case 'user':
|
|
$searchfield = 'nickname';
|
|
break;
|
|
}
|
|
|
|
$searchlist = Db::name($field)
|
|
->whereOr($searchfield, 'like', "%{$search}%")
|
|
->whereOr('id', 'like', "%{$search}%")
|
|
->limit(10)
|
|
->field("id,{$searchfield} AS name")
|
|
->select();
|
|
|
|
$this->code = 1;
|
|
$this->data = ['searchlist' => $searchlist];
|
|
}
|
|
|
|
/**
|
|
* SelectPage通用下拉列表搜索
|
|
*/
|
|
public function selectpage()
|
|
{
|
|
//搜索关键词,客户端输入以空格分开,这里接收为数组
|
|
$word = $this->request->request("q_word/a");
|
|
//当前页
|
|
$page = $this->request->request("pageNumber");
|
|
//分页大小
|
|
$pagesize = $this->request->request("pageSize");
|
|
//搜索条件
|
|
$andor = $this->request->request("and_or");
|
|
//排序方式
|
|
$orderby = $this->request->request("order_by/a");
|
|
//表名
|
|
$table = $this->request->request("db_table");
|
|
//显示的字段
|
|
$field = $this->request->request("field");
|
|
//主键
|
|
$primarykey = $this->request->request("pkey_name");
|
|
//主键值
|
|
$primaryvalue = $this->request->request("pkey_value");
|
|
//搜索字段
|
|
$searchfield = $this->request->request("search_field/a");
|
|
//自定义搜索条件
|
|
$custom = $this->request->request("custom/a");
|
|
$order = [];
|
|
foreach ($orderby as $k => $v)
|
|
{
|
|
$order[$v[0]] = $v[1];
|
|
}
|
|
$field = $field ? $field : 'name';
|
|
|
|
//如果不使用ajax/selectpage这个页面提供结果,则是自己的控制器单独写搜索条件,$where按自己的需求写即可
|
|
//这里只是能用考虑,所以搜索条件写得比较复杂
|
|
//如果有primaryvalue,说明当前是初始化传值
|
|
if ($primaryvalue)
|
|
{
|
|
$where = [$primarykey => ['in', $primaryvalue]];
|
|
}
|
|
else
|
|
{
|
|
$where = function($query) use($word, $andor, $field, $searchfield, $custom) {
|
|
$where = $andor == "OR" ? "whereOr" : "where";
|
|
foreach ($word as $k => $v)
|
|
{
|
|
foreach ($searchfield as $m => $n)
|
|
{
|
|
$query->{$where}($n, "like", "%{$v}%");
|
|
}
|
|
}
|
|
if ($custom && is_array($custom))
|
|
{
|
|
foreach ($custom as $k => $v)
|
|
{
|
|
$query->where($k, '=', $v);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
$list = [];
|
|
$total = Db::name($table)->where($where)->count();
|
|
if ($total > 0)
|
|
{
|
|
$list = Db::name($table)->where($where)->order($order)->page($page, $pagesize)->field("{$primarykey},{$field}")->select();
|
|
}
|
|
|
|
//这里一定要返回有list这个字段,total是可选的,如果total<=list的数量,则会隐藏分页按钮
|
|
return json(['list' => $list, 'total' => $total]);
|
|
}
|
|
|
|
/**
|
|
* 加载语言包
|
|
*/
|
|
public function lang()
|
|
{
|
|
header('Content-Type: application/javascript');
|
|
$callback = $this->request->get('callback');
|
|
$controllername = input("controllername");
|
|
$this->loadlang($controllername);
|
|
//强制输出JSON Object
|
|
$result = 'define(' . json_encode(Lang::get(), JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE) . ');';
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 读取角色权限树
|
|
*/
|
|
public function roletree()
|
|
{
|
|
$this->loadlang('auth/group');
|
|
|
|
$model = model('AuthGroup');
|
|
$id = $this->request->post("id");
|
|
$pid = $this->request->post("pid");
|
|
$parentgroupmodel = $model->get($pid);
|
|
$currentgroupmodel = NULL;
|
|
if ($id)
|
|
{
|
|
$currentgroupmodel = $model->get($id);
|
|
}
|
|
if (($pid || $parentgroupmodel) && (!$id || $currentgroupmodel))
|
|
{
|
|
$id = $id ? $id : NULL;
|
|
$ruleList = collection(model('AuthRule')->order('weigh', 'desc')->select())->toArray();
|
|
//读取父类角色所有节点列表
|
|
$parentRuleList = [];
|
|
if (in_array('*', explode(',', $parentgroupmodel->rules)))
|
|
{
|
|
$parentRuleList = $ruleList;
|
|
}
|
|
else
|
|
{
|
|
$parent_rule_ids = explode(',', $parentgroupmodel->rules);
|
|
foreach ($ruleList as $k => $v)
|
|
{
|
|
if (in_array($v['id'], $parent_rule_ids))
|
|
{
|
|
$parentRuleList[] = $v;
|
|
}
|
|
}
|
|
}
|
|
|
|
//当前所有正常规则列表
|
|
Tree::instance()->init($ruleList);
|
|
|
|
//读取当前角色下规则ID集合
|
|
$admin_rule_ids = $this->auth->getRuleIds();
|
|
//是否是超级管理员
|
|
$superadmin = $this->auth->isSuperAdmin();
|
|
//当前拥有的规则ID集合
|
|
$current_rule_ids = $id ? explode(',', $currentgroupmodel->rules) : [];
|
|
|
|
if (!$id || !in_array($pid, Tree::instance()->getChildrenIds($id, TRUE)))
|
|
{
|
|
$ruleList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'name');
|
|
$hasChildrens = [];
|
|
foreach ($ruleList as $k => $v)
|
|
{
|
|
if ($v['haschild'])
|
|
$hasChildrens[] = $v['id'];
|
|
}
|
|
$nodelist = [];
|
|
foreach ($parentRuleList as $k => $v)
|
|
{
|
|
if (!$superadmin && !in_array($v['id'], $admin_rule_ids))
|
|
continue;
|
|
$state = array('selected' => in_array($v['id'], $current_rule_ids) && !in_array($v['id'], $hasChildrens));
|
|
$nodelist[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => $v['title'], 'type' => 'menu', 'state' => $state);
|
|
}
|
|
$this->code = 1;
|
|
$this->data = $nodelist;
|
|
}
|
|
else
|
|
{
|
|
$this->code = -1;
|
|
$this->data = __('Can not change the parent to child');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$this->code = -1;
|
|
$this->data = __('Group not found');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 上传文件
|
|
*/
|
|
public function upload()
|
|
{
|
|
$this->code = -1;
|
|
$file = $this->request->file('file');
|
|
if (empty($file))
|
|
{
|
|
$this->msg = "未上传文件或超出服务器上传限制";
|
|
return;
|
|
}
|
|
|
|
//判断是否已经存在附件
|
|
$sha1 = $file->hash();
|
|
$uploaded = model("attachment")->where('sha1', $sha1)->find();
|
|
if ($uploaded)
|
|
{
|
|
$this->code = 1;
|
|
$this->data = [
|
|
'url' => $uploaded['url']
|
|
];
|
|
return;
|
|
}
|
|
|
|
$upload = Config::get('upload');
|
|
|
|
preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
|
|
$type = strtolower($matches[2]);
|
|
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
|
|
$size = (int) $upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
|
|
$fileInfo = $file->getInfo();
|
|
$suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
|
|
$suffix = $suffix ? $suffix : 'file';
|
|
$replaceArr = [
|
|
'{year}' => date("Y"),
|
|
'{mon}' => date("m"),
|
|
'{day}' => date("d"),
|
|
'{hour}' => date("H"),
|
|
'{min}' => date("i"),
|
|
'{sec}' => date("s"),
|
|
'{random}' => Random::alnum(16),
|
|
'{random32}' => Random::alnum(32),
|
|
'{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
|
|
'{suffix}' => $suffix,
|
|
'{.suffix}' => $suffix ? '.' . $suffix : '',
|
|
'{filemd5}' => md5_file($fileInfo['tmp_name']),
|
|
];
|
|
$savekey = $upload['savekey'];
|
|
$savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);
|
|
|
|
$uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
|
|
$fileName = substr($savekey, strripos($savekey, '/') + 1);
|
|
//
|
|
$splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
|
|
if ($splInfo)
|
|
{
|
|
$imagewidth = $imageheight = 0;
|
|
if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']))
|
|
{
|
|
$imgInfo = getimagesize($splInfo->getPathname());
|
|
$imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
|
|
$imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
|
|
}
|
|
$params = array(
|
|
'filesize' => $fileInfo['size'],
|
|
'imagewidth' => $imagewidth,
|
|
'imageheight' => $imageheight,
|
|
'imagetype' => $suffix,
|
|
'imageframes' => 0,
|
|
'mimetype' => $fileInfo['type'],
|
|
'url' => $uploadDir . $splInfo->getSaveName(),
|
|
'uploadtime' => time(),
|
|
'storage' => 'local',
|
|
'sha1' => $sha1,
|
|
);
|
|
model("attachment")->create(array_filter($params));
|
|
$this->code = 1;
|
|
$this->data = [
|
|
'url' => $uploadDir . $splInfo->getSaveName()
|
|
];
|
|
}
|
|
else
|
|
{
|
|
// 上传失败获取错误信息
|
|
$this->data = $file->getError();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 通用排序
|
|
*/
|
|
public function weigh()
|
|
{
|
|
//排序的数组
|
|
$ids = $this->request->post("ids");
|
|
//拖动的记录ID
|
|
$changeid = $this->request->post("changeid");
|
|
//操作字段
|
|
$field = $this->request->post("field");
|
|
//操作的数据表
|
|
$table = $this->request->post("table");
|
|
//排序的方式
|
|
$orderway = $this->request->post("orderway", 'strtolower');
|
|
$orderway = $orderway == 'asc' ? 'ASC' : 'DESC';
|
|
$sour = $weighdata = [];
|
|
$ids = explode(',', $ids);
|
|
$prikey = 'id';
|
|
$pid = $this->request->post("pid");
|
|
|
|
// 如果设定了pid的值,此时只匹配满足条件的ID,其它忽略
|
|
if ($pid !== '')
|
|
{
|
|
$hasids = [];
|
|
$list = Db::name($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pid)->field('id,pid')->select();
|
|
foreach ($list as $k => $v)
|
|
{
|
|
$hasids[] = $v['id'];
|
|
}
|
|
$ids = array_values(array_intersect($ids, $hasids));
|
|
}
|
|
|
|
//直接修复排序
|
|
$one = Db::name($table)->field("{$field},COUNT(*) AS nums")->group($field)->having('nums > 1')->find();
|
|
if ($one)
|
|
{
|
|
$list = Db::name($table)->field("$prikey,$field")->order($field, $orderway)->select();
|
|
foreach ($list as $k => $v)
|
|
{
|
|
Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]);
|
|
}
|
|
$this->code = 1;
|
|
}
|
|
else
|
|
{
|
|
$list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select();
|
|
foreach ($list as $k => $v)
|
|
{
|
|
$sour[] = $v[$prikey];
|
|
$weighdata[$v[$prikey]] = $v[$field];
|
|
}
|
|
$position = array_search($changeid, $ids);
|
|
$desc_id = $sour[$position]; //移动到目标的ID值,取出所处改变前位置的值
|
|
$sour_id = $changeid;
|
|
$desc_value = $weighdata[$desc_id];
|
|
$sour_value = $weighdata[$sour_id];
|
|
//echo "移动的ID:{$sour_id}\n";
|
|
//echo "替换的ID:{$desc_id}\n";
|
|
$weighids = array();
|
|
$temp = array_values(array_diff_assoc($ids, $sour));
|
|
foreach ($temp as $m => $n)
|
|
{
|
|
if ($n == $sour_id)
|
|
{
|
|
$offset = $desc_id;
|
|
}
|
|
else
|
|
{
|
|
if ($sour_id == $temp[0])
|
|
{
|
|
$offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id;
|
|
}
|
|
else
|
|
{
|
|
$offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id;
|
|
}
|
|
}
|
|
$weighids[$n] = $weighdata[$offset];
|
|
Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]);
|
|
}
|
|
$this->code = 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 清空系统缓存
|
|
*/
|
|
public function wipecache()
|
|
{
|
|
$wipe_cache_type = ['TEMP_PATH', 'LOG_PATH', 'CACHE_PATH'];
|
|
foreach ($wipe_cache_type as $item)
|
|
{
|
|
$dir = constant($item);
|
|
if (!is_dir($dir))
|
|
continue;
|
|
$files = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST
|
|
);
|
|
|
|
foreach ($files as $fileinfo)
|
|
{
|
|
$todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink');
|
|
$todo($fileinfo->getRealPath());
|
|
}
|
|
|
|
//rmdir($dir);
|
|
}
|
|
Cache::clear();
|
|
$this->code = 1;
|
|
}
|
|
|
|
/**
|
|
* 读取分类数据
|
|
*/
|
|
public function category()
|
|
{
|
|
$type = $this->request->get('type');
|
|
$pid = $this->request->get('pid');
|
|
$where = ['status' => 'normal'];
|
|
$categorylist = null;
|
|
if ($pid !== '')
|
|
{
|
|
if ($type)
|
|
{
|
|
$where['type'] = $type;
|
|
}
|
|
if ($pid)
|
|
{
|
|
$where['pid'] = $pid;
|
|
}
|
|
|
|
$categorylist = Db::name('category')->where($where)->field('id as value,name')->order('weigh desc,id desc')->select();
|
|
}
|
|
$this->code = 1;
|
|
$this->data = $categorylist;
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* 读取省市区数据
|
|
*/
|
|
public function area()
|
|
{
|
|
$province = $this->request->get('province');
|
|
$city = $this->request->get('city');
|
|
$where = ['pid' => 0, 'level' => 1];
|
|
$provincelist = null;
|
|
if ($province !== '')
|
|
{
|
|
if ($province)
|
|
{
|
|
$where['pid'] = $province;
|
|
$where['level'] = 2;
|
|
}
|
|
if ($city !== '')
|
|
{
|
|
if ($city)
|
|
{
|
|
$where['pid'] = $city;
|
|
$where['level'] = 3;
|
|
}
|
|
$provincelist = Db::name('area')->where($where)->field('id as value,name')->select();
|
|
}
|
|
}
|
|
$this->code = 1;
|
|
$this->data = $provincelist;
|
|
return;
|
|
}
|
|
|
|
}
|