mirror of https://gitee.com/karson/fastadmin.git
新增CRUD生成回收站视图和JS文件
新增一键生成API文档排序功能 新增表格默认导出选项 新增buttons中text和title的function支持 修复buttons中visible和disable为false时的判断Bug 修复后台添加子管理员的权限错误pull/98/MERGE
parent
a329e5fbb2
commit
88226015a8
|
|
@ -15,7 +15,6 @@ use think\exception\PDOException;
|
|||
|
||||
class Addon extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
|
|
@ -80,7 +79,6 @@ class Addon extends Command
|
|||
$createTableSql = $result[0]['Create Table'];
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
|
@ -235,7 +233,8 @@ class Addon extends Command
|
|||
$zip->open($addonFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
|
||||
|
||||
$files = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($addonDir), \RecursiveIteratorIterator::LEAVES_ONLY
|
||||
new \RecursiveDirectoryIterator($addonDir),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $name => $file) {
|
||||
|
|
@ -251,7 +250,7 @@ class Addon extends Command
|
|||
$output->info("Package Successed!");
|
||||
break;
|
||||
|
||||
default :
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -315,5 +314,4 @@ class Addon extends Command
|
|||
{
|
||||
return __DIR__ . '/Addon/stubs/' . $name . '.stub';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use think\Exception;
|
|||
|
||||
class Api extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$site = Config::get('site');
|
||||
|
|
@ -84,7 +83,8 @@ class Api extends Command
|
|||
|
||||
$controllerDir = $moduleDir . Config::get('url_controller_layer') . DS;
|
||||
$files = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
|
||||
new \RecursiveDirectoryIterator($controllerDir),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $name => $file) {
|
||||
|
|
@ -150,7 +150,7 @@ class Api extends Command
|
|||
|
||||
//Append the token's value to the name of the namespace
|
||||
$namespace .= $token[1];
|
||||
} else if ($token === ';') {
|
||||
} elseif ($token === ';') {
|
||||
|
||||
//If the token is the semicolon, then we're done with the namespace declaration
|
||||
$getting_namespace = false;
|
||||
|
|
@ -175,5 +175,4 @@ class Api extends Command
|
|||
//Build the fully-qualified class name and return it
|
||||
return $namespace ? $namespace . '\\' . $class : $class;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,16 +36,27 @@ class Builder
|
|||
|
||||
protected function extractAnnotations()
|
||||
{
|
||||
$st_output = [];
|
||||
foreach ($this->classes as $class) {
|
||||
$classAnnotation = Extractor::getClassAnnotations($class);
|
||||
// 如果忽略
|
||||
if (isset($classAnnotation['ApiInternal'])) {
|
||||
continue;
|
||||
}
|
||||
$st_output[] = Extractor::getAllClassAnnotations($class);
|
||||
Extractor::getClassMethodAnnotations($class);
|
||||
}
|
||||
return end($st_output);
|
||||
$allClassAnnotation = Extractor::getAllClassAnnotations();
|
||||
$allClassMethodAnnotation = Extractor::getAllClassMethodAnnotations();
|
||||
|
||||
// foreach ($allClassMethodAnnotation as $className => &$methods) {
|
||||
// foreach ($methods as &$method) {
|
||||
// //权重判断
|
||||
// if ($method && !isset($method['ApiWeigh']) && isset($allClassAnnotation[$className]['ApiWeigh'])) {
|
||||
// $method['ApiWeigh'] = $allClassAnnotation[$className]['ApiWeigh'];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// unset($methods);
|
||||
return [$allClassAnnotation, $allClassMethodAnnotation];
|
||||
}
|
||||
|
||||
protected function generateHeadersTemplate($docs)
|
||||
|
|
@ -148,12 +159,19 @@ class Builder
|
|||
|
||||
public function parse()
|
||||
{
|
||||
$annotations = $this->extractAnnotations();
|
||||
list($allClassAnnotations, $allClassMethodAnnotations) = $this->extractAnnotations();
|
||||
|
||||
$sectorArr = [];
|
||||
foreach ($allClassAnnotations as $index => $allClassAnnotation) {
|
||||
$sector = isset($allClassAnnotation['ApiSector']) ? $allClassAnnotation['ApiSector'][0] : $allClassAnnotation['ApiTitle'][0];
|
||||
$sectorArr[$sector] = isset($allClassAnnotation['ApiWeigh']) ? $allClassAnnotation['ApiWeigh'][0] : 0;
|
||||
}
|
||||
arsort($sectorArr);
|
||||
$counter = 0;
|
||||
$section = null;
|
||||
$weigh = 0;
|
||||
$docslist = [];
|
||||
foreach ($annotations as $class => $methods) {
|
||||
foreach ($allClassMethodAnnotations as $class => $methods) {
|
||||
foreach ($methods as $name => $docs) {
|
||||
if (isset($docs['ApiSector'][0])) {
|
||||
$section = is_array($docs['ApiSector'][0]) ? $docs['ApiSector'][0]['data'] : $docs['ApiSector'][0];
|
||||
|
|
@ -163,26 +181,37 @@ class Builder
|
|||
if (0 === count($docs)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$docslist[$section][] = [
|
||||
$docslist[$section][$name] = [
|
||||
'id' => $counter,
|
||||
'method' => is_array($docs['ApiMethod'][0]) ? $docs['ApiMethod'][0]['data'] : $docs['ApiMethod'][0],
|
||||
'method_label' => $this->generateBadgeForMethod($docs),
|
||||
'section' => $section,
|
||||
'route' => is_array($docs['ApiRoute'][0]) ? $docs['ApiRoute'][0]['data'] : $docs['ApiRoute'][0],
|
||||
'title' => is_array($docs['ApiTitle'][0]) ? $docs['ApiTitle'][0]['data'] : $docs['ApiTitle'][0],
|
||||
'title' => is_array($docs['ApiTitle'][0]) ? $docs['ApiTitle'][0]['data'] : $docs['ApiTitle'][0],
|
||||
'summary' => is_array($docs['ApiSummary'][0]) ? $docs['ApiSummary'][0]['data'] : $docs['ApiSummary'][0],
|
||||
'body' => isset($docs['ApiBody'][0]) ? is_array($docs['ApiBody'][0]) ? $docs['ApiBody'][0]['data'] : $docs['ApiBody'][0] : '',
|
||||
'headerslist' => $this->generateHeadersTemplate($docs),
|
||||
'paramslist' => $this->generateParamsTemplate($docs),
|
||||
'returnheaderslist' => $this->generateReturnHeadersTemplate($docs),
|
||||
'returnparamslist' => $this->generateReturnParamsTemplate($docs),
|
||||
'weigh' => is_array($docs['ApiWeigh'][0]) ? $docs['ApiWeigh'][0]['data'] : $docs['ApiWeigh'][0],
|
||||
'return' => isset($docs['ApiReturn']) ? is_array($docs['ApiReturn'][0]) ? $docs['ApiReturn'][0]['data'] : $docs['ApiReturn'][0] : '',
|
||||
];
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
|
||||
//重建排序
|
||||
foreach ($docslist as $index => &$methods) {
|
||||
$methodSectorArr = [];
|
||||
foreach ($methods as $name => $method) {
|
||||
$methodSectorArr[$name] = isset($method['weigh']) ? $method['weigh'] : 0;
|
||||
}
|
||||
arsort($methodSectorArr);
|
||||
$methods = array_merge(array_flip(array_keys($methodSectorArr)), $methods);
|
||||
}
|
||||
$docslist = array_merge(array_flip(array_keys($sectorArr)), $docslist);
|
||||
|
||||
return $docslist;
|
||||
}
|
||||
|
||||
|
|
@ -203,5 +232,4 @@ class Builder
|
|||
|
||||
return $this->view->display(file_get_contents($template), array_merge($vars, ['docslist' => $docslist]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ class Extractor
|
|||
*/
|
||||
private static $annotationCache;
|
||||
|
||||
private static $classAnnotationCache;
|
||||
|
||||
private static $classMethodAnnotationCache;
|
||||
|
||||
/**
|
||||
* Indicates that annotations should has strict behavior, 'false' by default
|
||||
* @var boolean
|
||||
|
|
@ -63,27 +67,43 @@ class Extractor
|
|||
* Gets all anotations with pattern @SomeAnnotation() from a given class
|
||||
*
|
||||
* @param string $className class name to get annotations
|
||||
* @return array self::$annotationCache all annotated elements
|
||||
* @return array self::$classAnnotationCache all annotated elements
|
||||
*/
|
||||
public static function getClassAnnotations($className)
|
||||
{
|
||||
if (!isset(self::$annotationCache[$className])) {
|
||||
if (!isset(self::$classAnnotationCache[$className])) {
|
||||
$class = new \ReflectionClass($className);
|
||||
self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment());
|
||||
self::$classAnnotationCache[$className] = self::parseAnnotations($class->getDocComment());
|
||||
}
|
||||
|
||||
return self::$annotationCache[$className];
|
||||
return self::$classAnnotationCache[$className];
|
||||
}
|
||||
|
||||
public static function getAllClassAnnotations($className)
|
||||
/**
|
||||
* 获取类所有方法的属性配置
|
||||
* @param $className
|
||||
* @return mixed
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function getClassMethodAnnotations($className)
|
||||
{
|
||||
$class = new \ReflectionClass($className);
|
||||
|
||||
foreach ($class->getMethods() as $object) {
|
||||
self::$annotationCache['annotations'][$className][$object->name] = self::getMethodAnnotations($className, $object->name);
|
||||
self::$classMethodAnnotationCache[$className][$object->name] = self::getMethodAnnotations($className, $object->name);
|
||||
}
|
||||
|
||||
return self::$annotationCache['annotations'];
|
||||
return self::$classMethodAnnotationCache[$className];
|
||||
}
|
||||
|
||||
public static function getAllClassAnnotations()
|
||||
{
|
||||
return self::$classAnnotationCache;
|
||||
}
|
||||
|
||||
public static function getAllClassMethodAnnotations()
|
||||
{
|
||||
return self::$classMethodAnnotationCache;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,14 +201,14 @@ class Extractor
|
|||
preg_match_all("/\*[\s]+(.*)(\\r\\n|\\r|\\n)/U", str_replace('/**', '', $docblockMethod), $methodArr);
|
||||
preg_match_all("/\*[\s]+(.*)(\\r\\n|\\r|\\n)/U", str_replace('/**', '', $dockblockClass), $classArr);
|
||||
|
||||
$methodTitle = isset($methodArr[1]) && isset($methodArr[1][0]) ? $methodArr[1][0] : '';
|
||||
$classTitle = isset($classArr[1]) && isset($classArr[1][0]) ? $classArr[1][0] : '';
|
||||
|
||||
if (!isset($methodAnnotations['ApiMethod'])) {
|
||||
$methodAnnotations['ApiMethod'] = ['get'];
|
||||
}
|
||||
if (!isset($methodAnnotations['ApiWeigh'])) {
|
||||
$methodAnnotations['ApiWeigh'] = [0];
|
||||
}
|
||||
if (!isset($methodAnnotations['ApiSummary'])) {
|
||||
$methodAnnotations['ApiSummary'] = [$methodTitle];
|
||||
$methodAnnotations['ApiSummary'] = $methodAnnotations['ApiTitle'];
|
||||
}
|
||||
|
||||
if ($methodAnnotations) {
|
||||
|
|
@ -210,9 +230,6 @@ class Extractor
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!isset($methodAnnotations['ApiTitle'])) {
|
||||
$methodAnnotations['ApiTitle'] = [$methodTitle];
|
||||
}
|
||||
if (!isset($methodAnnotations['ApiRoute'])) {
|
||||
$urlArr = [];
|
||||
$className = $class->getName();
|
||||
|
|
@ -231,7 +248,7 @@ class Extractor
|
|||
$methodAnnotations['ApiRoute'] = [implode('/', $urlArr)];
|
||||
}
|
||||
if (!isset($methodAnnotations['ApiSector'])) {
|
||||
$methodAnnotations['ApiSector'] = isset($classAnnotations['ApiSector']) ? $classAnnotations['ApiSector'] : [$classTitle];
|
||||
$methodAnnotations['ApiSector'] = isset($classAnnotations['ApiSector']) ? $classAnnotations['ApiSector'] : $classAnnotations['ApiTitle'];
|
||||
}
|
||||
if (!isset($methodAnnotations['ApiParams'])) {
|
||||
$params = self::parseCustomAnnotations($docblockMethod, 'param');
|
||||
|
|
@ -292,7 +309,7 @@ class Extractor
|
|||
$argsParts = trim($matches['args'][$i]);
|
||||
if ($name == 'ApiReturn') {
|
||||
$value = $argsParts;
|
||||
} else if ($matches['args'][$i] != '') {
|
||||
} elseif ($matches['args'][$i] != '') {
|
||||
$argsParts = preg_replace("/\{(\w+)\}/", '#$1#', $argsParts);
|
||||
$value = self::parseArgs($argsParts);
|
||||
if (is_string($value)) {
|
||||
|
|
@ -307,6 +324,11 @@ class Extractor
|
|||
if (stripos($docblock, '@ApiInternal') !== false) {
|
||||
$annotations['ApiInternal'] = [true];
|
||||
}
|
||||
if (!isset($annotations['ApiTitle'])) {
|
||||
preg_match_all("/\*[\s]+(.*)(\\r\\n|\\r|\\n)/U", str_replace('/**', '', $docblock), $matchArr);
|
||||
$title = isset($matchArr[1]) && isset($matchArr[1][0]) ? $matchArr[1][0] : '';
|
||||
$annotations['ApiTitle'] = [$title];
|
||||
}
|
||||
|
||||
return $annotations;
|
||||
}
|
||||
|
|
@ -354,7 +376,9 @@ class Extractor
|
|||
// close delimiter
|
||||
if ($c !== $nextDelimiter) {
|
||||
throw new Exception(sprintf(
|
||||
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
||||
"Parse Error: enclosing error -> expected: [%s], given: [%s]",
|
||||
$nextDelimiter,
|
||||
$c
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -362,7 +386,8 @@ class Extractor
|
|||
if ($i < $len) {
|
||||
if (',' !== substr($content, $i, 1) && '\\' !== $prev_c) {
|
||||
throw new Exception(sprintf(
|
||||
"Parse Error: missing comma separator near: ...%s<--", substr($content, ($i - 10), $i)
|
||||
"Parse Error: missing comma separator near: ...%s<--",
|
||||
substr($content, ($i - 10), $i)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -387,7 +412,9 @@ class Extractor
|
|||
// it means that the string was not enclosed, so it is parsing error.
|
||||
if ($composing === true && !empty($prevDelimiter) && !empty($nextDelimiter)) {
|
||||
throw new Exception(sprintf(
|
||||
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
||||
"Parse Error: enclosing error -> expected: [%s], given: [%s]",
|
||||
$nextDelimiter,
|
||||
$c
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -416,7 +443,8 @@ class Extractor
|
|||
// if the string is composing yet means that the structure of var. never was enclosed with '}'
|
||||
if ($subComposing) {
|
||||
throw new Exception(sprintf(
|
||||
"Parse Error: Composite variable is not enclosed correctly. near: ...%s'", $subc
|
||||
"Parse Error: Composite variable is not enclosed correctly. near: ...%s'",
|
||||
$subc
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -479,5 +507,4 @@ class Extractor
|
|||
|
||||
return $val;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@
|
|||
padding-left:0px;
|
||||
}
|
||||
}
|
||||
.label-primary {
|
||||
background-color: #248aff;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
|
@ -547,6 +550,9 @@
|
|||
contentType: false,
|
||||
processData: false,
|
||||
headers: headers,
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
success: function (data, textStatus, xhr) {
|
||||
if (typeof data === 'object') {
|
||||
var str = JSON.stringify(data, null, 2);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use think\Loader;
|
|||
|
||||
class Crud extends Command
|
||||
{
|
||||
|
||||
protected $stubList = [];
|
||||
|
||||
/**
|
||||
|
|
@ -93,7 +92,7 @@ class Crud extends Command
|
|||
/**
|
||||
* 保留字段
|
||||
*/
|
||||
protected $reservedField = ['admin_id', 'createtime', 'updatetime'];
|
||||
protected $reservedField = ['admin_id'];
|
||||
|
||||
/**
|
||||
* 排除字段
|
||||
|
|
@ -111,6 +110,24 @@ class Crud extends Command
|
|||
*/
|
||||
protected $headingFilterField = 'status';
|
||||
|
||||
/**
|
||||
* 添加时间字段
|
||||
* @var string
|
||||
*/
|
||||
protected $createTimeField = 'createtime';
|
||||
|
||||
/**
|
||||
* 更新时间字段
|
||||
* @var string
|
||||
*/
|
||||
protected $updateTimeField = 'updatetime';
|
||||
|
||||
/**
|
||||
* 软删除时间字段
|
||||
* @var string
|
||||
*/
|
||||
protected $deleteTimeField = 'deletetime';
|
||||
|
||||
/**
|
||||
* 编辑器的Class
|
||||
*/
|
||||
|
|
@ -118,7 +135,7 @@ class Crud extends Command
|
|||
|
||||
/**
|
||||
* langList的key最长字节数
|
||||
*/
|
||||
*/
|
||||
protected $fieldMaxLen = 0;
|
||||
|
||||
protected function configure()
|
||||
|
|
@ -215,32 +232,47 @@ class Crud extends Command
|
|||
$headingfilterfield = $input->getOption('headingfilterfield');
|
||||
//编辑器Class
|
||||
$editorclass = $input->getOption('editorclass');
|
||||
if ($setcheckboxsuffix)
|
||||
if ($setcheckboxsuffix) {
|
||||
$this->setCheckboxSuffix = $setcheckboxsuffix;
|
||||
if ($enumradiosuffix)
|
||||
}
|
||||
if ($enumradiosuffix) {
|
||||
$this->enumRadioSuffix = $enumradiosuffix;
|
||||
if ($imagefield)
|
||||
}
|
||||
if ($imagefield) {
|
||||
$this->imageField = $imagefield;
|
||||
if ($filefield)
|
||||
}
|
||||
if ($filefield) {
|
||||
$this->fileField = $filefield;
|
||||
if ($intdatesuffix)
|
||||
}
|
||||
if ($intdatesuffix) {
|
||||
$this->intDateSuffix = $intdatesuffix;
|
||||
if ($switchsuffix)
|
||||
}
|
||||
if ($switchsuffix) {
|
||||
$this->switchSuffix = $switchsuffix;
|
||||
if ($citysuffix)
|
||||
}
|
||||
if ($citysuffix) {
|
||||
$this->citySuffix = $citysuffix;
|
||||
if ($selectpagesuffix)
|
||||
}
|
||||
if ($selectpagesuffix) {
|
||||
$this->selectpageSuffix = $selectpagesuffix;
|
||||
if ($selectpagessuffix)
|
||||
}
|
||||
if ($selectpagessuffix) {
|
||||
$this->selectpagesSuffix = $selectpagessuffix;
|
||||
if ($ignoreFields)
|
||||
}
|
||||
if ($ignoreFields) {
|
||||
$this->ignoreFields = $ignoreFields;
|
||||
if ($editorclass)
|
||||
}
|
||||
if ($editorclass) {
|
||||
$this->editorClass = $editorclass;
|
||||
if ($sortfield)
|
||||
}
|
||||
if ($sortfield) {
|
||||
$this->sortField = $sortfield;
|
||||
if ($headingfilterfield)
|
||||
}
|
||||
if ($headingfilterfield) {
|
||||
$this->headingFilterField = $headingfilterfield;
|
||||
}
|
||||
|
||||
$this->reservedField = array_merge($this->reservedField, [$this->createTimeField, $this->updateTimeField, $this->deleteTimeField]);
|
||||
|
||||
$dbname = Config::get('database.database');
|
||||
$prefix = Config::get('database.prefix');
|
||||
|
|
@ -254,11 +286,11 @@ class Crud extends Command
|
|||
$modelName = $table = stripos($table, $prefix) === 0 ? substr($table, strlen($prefix)) : $table;
|
||||
$modelTableType = 'table';
|
||||
$modelTableTypeName = $modelTableName = $modelName;
|
||||
$modelTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], TRUE);
|
||||
$modelTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true);
|
||||
if (!$modelTableInfo) {
|
||||
$modelTableType = 'name';
|
||||
$modelTableName = $prefix . $modelName;
|
||||
$modelTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], TRUE);
|
||||
$modelTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true);
|
||||
if (!$modelTableInfo) {
|
||||
throw new Exception("table not found");
|
||||
}
|
||||
|
|
@ -275,11 +307,11 @@ class Crud extends Command
|
|||
$relationName = stripos($relationTable, $prefix) === 0 ? substr($relationTable, strlen($prefix)) : $relationTable;
|
||||
$relationTableType = 'table';
|
||||
$relationTableTypeName = $relationTableName = $relationName;
|
||||
$relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], TRUE);
|
||||
$relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], true);
|
||||
if (!$relationTableInfo) {
|
||||
$relationTableType = 'name';
|
||||
$relationTableName = $prefix . $relationName;
|
||||
$relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], TRUE);
|
||||
$relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], true);
|
||||
if (!$relationTableInfo) {
|
||||
throw new Exception("relation table not found");
|
||||
}
|
||||
|
|
@ -338,6 +370,7 @@ class Crud extends Command
|
|||
$addFile = $viewDir . 'add.html';
|
||||
$editFile = $viewDir . 'edit.html';
|
||||
$indexFile = $viewDir . 'index.html';
|
||||
$recyclebinFile = $viewDir . 'recyclebin.html';
|
||||
$langFile = $adminPath . 'lang' . DS . Lang::detect() . DS . $controllerBaseName . '.php';
|
||||
|
||||
//是否为删除模式
|
||||
|
|
@ -355,12 +388,13 @@ class Crud extends Command
|
|||
}
|
||||
}
|
||||
foreach ($readyFiles as $k => $v) {
|
||||
if (file_exists($v))
|
||||
if (file_exists($v)) {
|
||||
unlink($v);
|
||||
}
|
||||
//删除空文件夹
|
||||
if ($v == $modelFile) {
|
||||
$this->removeEmptyBaseDir($v, $modelArr);
|
||||
} else if ($v == $validateFile) {
|
||||
} elseif ($v == $validateFile) {
|
||||
$this->removeEmptyBaseDir($v, $validateArr);
|
||||
} else {
|
||||
$this->removeEmptyBaseDir($v, $controllerArr);
|
||||
|
|
@ -434,7 +468,7 @@ class Crud extends Command
|
|||
$langList = [];
|
||||
$field = 'id';
|
||||
$order = 'id';
|
||||
$priDefined = FALSE;
|
||||
$priDefined = false;
|
||||
$priKey = '';
|
||||
$relationPrimaryKey = '';
|
||||
foreach ($columnList as $k => $v) {
|
||||
|
|
@ -484,6 +518,7 @@ class Crud extends Command
|
|||
$appendAttrList = [];
|
||||
$controllerAssignList = [];
|
||||
$headingHtml = '{:build_heading()}';
|
||||
$recyclebinHtml = '';
|
||||
|
||||
//循环所有字段,开始构造视图的HTML和JS信息
|
||||
foreach ($columnList as $k => $v) {
|
||||
|
|
@ -506,7 +541,7 @@ class Crud extends Command
|
|||
$langList[] = $this->getLangItem($field, $v['COLUMN_COMMENT']);
|
||||
}
|
||||
$inputType = '';
|
||||
//createtime和updatetime是保留字段不能修改和添加
|
||||
//保留字段不能修改和添加
|
||||
if ($v['COLUMN_KEY'] != 'PRI' && !in_array($field, $this->reservedField) && !in_array($field, $this->ignoreFields)) {
|
||||
$inputType = $this->getFieldType($v);
|
||||
|
||||
|
|
@ -534,7 +569,7 @@ class Crud extends Command
|
|||
|
||||
$this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $v['DATA_TYPE'] == 'set' ? 'multiple' : 'select');
|
||||
|
||||
$itemArr = $this->getLangArray($itemArr, FALSE);
|
||||
$itemArr = $this->getLangArray($itemArr, false);
|
||||
//添加一个获取器
|
||||
$this->getAttr($getAttrArr, $field, $v['DATA_TYPE'] == 'set' ? 'multiple' : 'select');
|
||||
if ($v['DATA_TYPE'] == 'set') {
|
||||
|
|
@ -543,28 +578,29 @@ class Crud extends Command
|
|||
$this->appendAttr($appendAttrList, $field);
|
||||
$formAddElement = $this->getReplacedStub('html/select', ['field' => $field, 'fieldName' => $fieldName, 'fieldList' => $this->getFieldListName($field), 'attrStr' => Form::attributes($attrArr), 'selectedValue' => $defaultValue]);
|
||||
$formEditElement = $this->getReplacedStub('html/select', ['field' => $field, 'fieldName' => $fieldName, 'fieldList' => $this->getFieldListName($field), 'attrStr' => Form::attributes($attrArr), 'selectedValue' => "\$row.{$field}"]);
|
||||
} else if ($inputType == 'datetime') {
|
||||
} elseif ($inputType == 'datetime') {
|
||||
$cssClassArr[] = 'datetimepicker';
|
||||
$attrArr['class'] = implode(' ', $cssClassArr);
|
||||
$format = "YYYY-MM-DD HH:mm:ss";
|
||||
$phpFormat = "Y-m-d H:i:s";
|
||||
$fieldFunc = '';
|
||||
switch ($v['DATA_TYPE']) {
|
||||
case 'year';
|
||||
case 'year':
|
||||
$format = "YYYY";
|
||||
$phpFormat = 'Y';
|
||||
break;
|
||||
case 'date';
|
||||
case 'date':
|
||||
$format = "YYYY-MM-DD";
|
||||
$phpFormat = 'Y-m-d';
|
||||
break;
|
||||
case 'time';
|
||||
case 'time':
|
||||
$format = "HH:mm:ss";
|
||||
$phpFormat = 'H:i:s';
|
||||
break;
|
||||
case 'timestamp';
|
||||
case 'timestamp':
|
||||
$fieldFunc = 'datetime';
|
||||
case 'datetime';
|
||||
// no break
|
||||
case 'datetime':
|
||||
$format = "YYYY-MM-DD HH:mm:ss";
|
||||
$phpFormat = 'Y-m-d H:i:s';
|
||||
break;
|
||||
|
|
@ -581,13 +617,13 @@ class Crud extends Command
|
|||
$fieldFunc = $fieldFunc ? "|{$fieldFunc}" : "";
|
||||
$formAddElement = Form::text($fieldName, $defaultDateTime, $attrArr);
|
||||
$formEditElement = Form::text($fieldName, "{\$row.{$field}{$fieldFunc}}", $attrArr);
|
||||
} else if ($inputType == 'checkbox' || $inputType == 'radio') {
|
||||
} elseif ($inputType == 'checkbox' || $inputType == 'radio') {
|
||||
unset($attrArr['data-rule']);
|
||||
$fieldName = $inputType == 'checkbox' ? $fieldName .= "[]" : $fieldName;
|
||||
$attrArr['name'] = "row[{$fieldName}]";
|
||||
|
||||
$this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $inputType);
|
||||
$itemArr = $this->getLangArray($itemArr, FALSE);
|
||||
$itemArr = $this->getLangArray($itemArr, false);
|
||||
//添加一个获取器
|
||||
$this->getAttr($getAttrArr, $field, $inputType);
|
||||
if ($inputType == 'checkbox') {
|
||||
|
|
@ -598,13 +634,13 @@ class Crud extends Command
|
|||
|
||||
$formAddElement = $this->getReplacedStub('html/' . $inputType, ['field' => $field, 'fieldName' => $fieldName, 'fieldList' => $this->getFieldListName($field), 'attrStr' => Form::attributes($attrArr), 'selectedValue' => $defaultValue]);
|
||||
$formEditElement = $this->getReplacedStub('html/' . $inputType, ['field' => $field, 'fieldName' => $fieldName, 'fieldList' => $this->getFieldListName($field), 'attrStr' => Form::attributes($attrArr), 'selectedValue' => "\$row.{$field}"]);
|
||||
} else if ($inputType == 'textarea') {
|
||||
} elseif ($inputType == 'textarea') {
|
||||
$cssClassArr[] = $this->isMatchSuffix($field, $this->editorSuffix) ? $this->editorClass : '';
|
||||
$attrArr['class'] = implode(' ', $cssClassArr);
|
||||
$attrArr['rows'] = 5;
|
||||
$formAddElement = Form::textarea($fieldName, $defaultValue, $attrArr);
|
||||
$formEditElement = Form::textarea($fieldName, $editValue, $attrArr);
|
||||
} else if ($inputType == 'switch') {
|
||||
} elseif ($inputType == 'switch') {
|
||||
unset($attrArr['data-rule']);
|
||||
if ($defaultValue === '1' || $defaultValue === 'Y') {
|
||||
$yes = $defaultValue;
|
||||
|
|
@ -619,7 +655,7 @@ class Crud extends Command
|
|||
$stateNoClass = 'fa-flip-horizontal text-gray';
|
||||
$formAddElement = $this->getReplacedStub('html/' . $inputType, ['field' => $field, 'fieldName' => $fieldName, 'fieldYes' => $yes, 'fieldNo' => $no, 'attrStr' => Form::attributes($attrArr), 'fieldValue' => $defaultValue, 'fieldSwitchClass' => $defaultValue == $no ? $stateNoClass : '']);
|
||||
$formEditElement = $this->getReplacedStub('html/' . $inputType, ['field' => $field, 'fieldName' => $fieldName, 'fieldYes' => $yes, 'fieldNo' => $no, 'attrStr' => Form::attributes($attrArr), 'fieldValue' => "{\$row.{$field}}", 'fieldSwitchClass' => "{eq name=\"\$row.{$field}\" value=\"{$no}\"}fa-flip-horizontal text-gray{/eq}"]);
|
||||
} else if ($inputType == 'citypicker') {
|
||||
} elseif ($inputType == 'citypicker') {
|
||||
$attrArr['class'] = implode(' ', $cssClassArr);
|
||||
$attrArr['data-toggle'] = "city-picker";
|
||||
$formAddElement = sprintf("<div class='control-relative'>%s</div>", Form::input('text', $fieldName, $defaultValue, $attrArr));
|
||||
|
|
@ -692,9 +728,13 @@ class Crud extends Command
|
|||
if ($v['DATA_TYPE'] != 'text') {
|
||||
//主键
|
||||
if ($v['COLUMN_KEY'] == 'PRI' && !$priDefined) {
|
||||
$priDefined = TRUE;
|
||||
$priDefined = true;
|
||||
$javascriptList[] = "{checkbox: true}";
|
||||
}
|
||||
if ($this->deleteTimeField == $field) {
|
||||
$recyclebinHtml = $this->getReplacedStub('html/recyclebin-html', ['controllerUrl' => $controllerUrl]);
|
||||
continue;
|
||||
}
|
||||
if (!$fields || in_array($field, explode(',', $fields))) {
|
||||
//构造JS列信息
|
||||
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr);
|
||||
|
|
@ -743,7 +783,7 @@ class Crud extends Command
|
|||
}
|
||||
}
|
||||
unset($line);
|
||||
$langList = implode(",\n", array_filter($langList)). ",";
|
||||
$langList = implode(",\n", array_filter($langList)) . ",";
|
||||
|
||||
//表注释
|
||||
$tableComment = $modelTableInfo['Comment'];
|
||||
|
|
@ -754,7 +794,6 @@ class Crud extends Command
|
|||
$modelInit = $this->getReplacedStub('mixins' . DS . 'modelinit', ['order' => $order]);
|
||||
}
|
||||
|
||||
|
||||
$data = [
|
||||
'controllerNamespace' => $controllerNamespace,
|
||||
'modelNamespace' => $modelNamespace,
|
||||
|
|
@ -777,14 +816,18 @@ class Crud extends Command
|
|||
'editList' => $editList,
|
||||
'javascriptList' => $javascriptList,
|
||||
'langList' => $langList,
|
||||
'modelAutoWriteTimestamp' => in_array('createtime', $fieldArr) || in_array('updatetime', $fieldArr) ? "'int'" : 'false',
|
||||
'createTime' => in_array('createtime', $fieldArr) ? "'createtime'" : 'false',
|
||||
'updateTime' => in_array('updatetime', $fieldArr) ? "'updatetime'" : 'false',
|
||||
'sofeDeleteClassPath' => in_array($this->deleteTimeField, $fieldArr) ? "use traits\model\SoftDelete;" : '',
|
||||
'softDelete' => in_array($this->deleteTimeField, $fieldArr) ? "use SoftDelete;" : '',
|
||||
'modelAutoWriteTimestamp' => in_array($this->createTimeField, $fieldArr) || in_array($this->updateTimeField, $fieldArr) ? "'int'" : 'false',
|
||||
'createTime' => in_array($this->createTimeField, $fieldArr) ? "'{$this->createTimeField}'" : 'false',
|
||||
'updateTime' => in_array($this->updateTimeField, $fieldArr) ? "'{$this->updateTimeField}'" : 'false',
|
||||
'deleteTime' => in_array($this->deleteTimeField, $fieldArr) ? "'{$this->deleteTimeField}'" : 'false',
|
||||
'relationSearch' => $relations ? 'true' : 'false',
|
||||
'relationWithList' => '',
|
||||
'relationMethodList' => '',
|
||||
'controllerIndex' => '',
|
||||
'headingHtml' => $headingHtml,
|
||||
'recyclebinHtml' => $recyclebinHtml,
|
||||
'visibleFieldList' => $fields ? "\$row->visible(['" . implode("','", array_filter(explode(',', $fields))) . "']);" : '',
|
||||
'appendAttrList' => implode(",\n", $appendAttrList),
|
||||
'getEnumList' => implode("\n\n", $getEnumArr),
|
||||
|
|
@ -832,8 +875,7 @@ class Crud extends Command
|
|||
|
||||
//需要重写index方法
|
||||
$data['controllerIndex'] = $this->getReplacedStub('controllerindex', $data);
|
||||
|
||||
} else if ($fields) {
|
||||
} elseif ($fields) {
|
||||
$data = array_merge($data, ['relationWithList' => '', 'relationMethodList' => '', 'relationVisibleFieldList' => '']);
|
||||
//需要重写index方法
|
||||
$data['controllerIndex'] = $this->getReplacedStub('controllerindex', $data);
|
||||
|
|
@ -852,7 +894,6 @@ class Crud extends Command
|
|||
$result = $this->writeToFile('relationmodel', $relation, $relation['relationFile']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// 生成验证文件
|
||||
$result = $this->writeToFile('validate', $data, $validateFile);
|
||||
|
|
@ -860,6 +901,12 @@ class Crud extends Command
|
|||
$result = $this->writeToFile('add', $data, $addFile);
|
||||
$result = $this->writeToFile('edit', $data, $editFile);
|
||||
$result = $this->writeToFile('index', $data, $indexFile);
|
||||
if ($recyclebinHtml) {
|
||||
$result = $this->writeToFile('recyclebin', $data, $recyclebinFile);
|
||||
$recyclebinTitle = in_array('title', $fieldArr) ? 'title' : (in_array('name', $fieldArr) ? 'name' : '');
|
||||
$recyclebinTitleJs = $recyclebinTitle ? "\n {field: '{$recyclebinTitle}', title: __('" . (ucfirst($recyclebinTitle)) . "'), align: 'left'}," : '';
|
||||
$data['recyclebinJs'] = $this->getReplacedStub('mixins/recyclebinjs', ['recyclebinTitleJs' => $recyclebinTitleJs, 'controllerUrl' => $controllerUrl]);
|
||||
}
|
||||
// 生成JS文件
|
||||
$result = $this->writeToFile('javascript', $data, $javascriptFile);
|
||||
// 生成语言文件
|
||||
|
|
@ -880,8 +927,9 @@ class Crud extends Command
|
|||
|
||||
protected function getEnum(&$getEnum, &$controllerAssignList, $field, $itemArr = '', $inputType = '')
|
||||
{
|
||||
if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio']))
|
||||
if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio'])) {
|
||||
return;
|
||||
}
|
||||
$fieldList = $this->getFieldListName($field);
|
||||
$methodName = 'get' . ucfirst($fieldList);
|
||||
foreach ($itemArr as $k => &$v) {
|
||||
|
|
@ -902,22 +950,24 @@ EOD;
|
|||
|
||||
protected function getAttr(&$getAttr, $field, $inputType = '')
|
||||
{
|
||||
if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio']))
|
||||
if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio'])) {
|
||||
return;
|
||||
}
|
||||
$attrField = ucfirst($this->getCamelizeName($field));
|
||||
$getAttr[] = $this->getReplacedStub("mixins" . DS . $inputType, ['field' => $field, 'methodName' => "get{$attrField}TextAttr", 'listMethodName' => "get{$attrField}List"]);
|
||||
}
|
||||
|
||||
protected function setAttr(&$setAttr, $field, $inputType = '')
|
||||
{
|
||||
if (!in_array($inputType, ['datetime', 'checkbox', 'select']))
|
||||
if (!in_array($inputType, ['datetime', 'checkbox', 'select'])) {
|
||||
return;
|
||||
}
|
||||
$attrField = ucfirst($this->getCamelizeName($field));
|
||||
if ($inputType == 'datetime') {
|
||||
$return = <<<EOD
|
||||
return \$value && !is_numeric(\$value) ? strtotime(\$value) : \$value;
|
||||
EOD;
|
||||
} else if (in_array($inputType, ['checkbox', 'select'])) {
|
||||
} elseif (in_array($inputType, ['checkbox', 'select'])) {
|
||||
$return = <<<EOD
|
||||
return is_array(\$value) ? implode(',', \$value) : \$value;
|
||||
EOD;
|
||||
|
|
@ -1118,7 +1168,7 @@ EOD;
|
|||
* @param boolean $withTpl
|
||||
* @return array
|
||||
*/
|
||||
protected function getLangArray($arr, $withTpl = TRUE)
|
||||
protected function getLangArray($arr, $withTpl = true)
|
||||
{
|
||||
$langArr = [];
|
||||
foreach ($arr as $k => $v) {
|
||||
|
|
@ -1134,8 +1184,9 @@ EOD;
|
|||
*/
|
||||
protected function getArrayString($arr)
|
||||
{
|
||||
if (!is_array($arr))
|
||||
if (!is_array($arr)) {
|
||||
return $arr;
|
||||
}
|
||||
$stringArr = [];
|
||||
foreach ($arr as $k => $v) {
|
||||
$is_var = in_array(substr($v, 0, 1), ['$', '_']);
|
||||
|
|
@ -1197,11 +1248,11 @@ EOD;
|
|||
case 'tinytext':
|
||||
$inputType = 'textarea';
|
||||
break;
|
||||
case 'year';
|
||||
case 'date';
|
||||
case 'time';
|
||||
case 'datetime';
|
||||
case 'timestamp';
|
||||
case 'year':
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'datetime':
|
||||
case 'timestamp':
|
||||
$inputType = 'datetime';
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1327,8 +1378,9 @@ EOD;
|
|||
$formatter = 'label';
|
||||
}
|
||||
foreach ($itemArr as $k => &$v) {
|
||||
if (substr($v, 0, 3) !== '__(')
|
||||
if (substr($v, 0, 3) !== '__(') {
|
||||
$v = "__('" . mb_ucfirst($v) . "')";
|
||||
}
|
||||
}
|
||||
unset($v);
|
||||
$searchList = json_encode($itemArr, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
|
||||
|
|
@ -1338,22 +1390,23 @@ EOD;
|
|||
}
|
||||
if (in_array($datatype, ['date', 'datetime']) || $formatter === 'datetime') {
|
||||
$html .= ", operate:'RANGE', addclass:'datetimerange'";
|
||||
} else if (in_array($datatype, ['float', 'double', 'decimal'])) {
|
||||
} elseif (in_array($datatype, ['float', 'double', 'decimal'])) {
|
||||
$html .= ", operate:'BETWEEN'";
|
||||
}
|
||||
if (in_array($datatype, ['set'])) {
|
||||
$html .= ", operate:'FIND_IN_SET'";
|
||||
}
|
||||
if (in_array($formatter, ['image','images'])) {
|
||||
if (in_array($formatter, ['image', 'images'])) {
|
||||
$html .= ", events: Table.api.events.image";
|
||||
}
|
||||
if ($itemArr && !$formatter) {
|
||||
$formatter = 'normal';
|
||||
}
|
||||
if ($formatter)
|
||||
if ($formatter) {
|
||||
$html .= ", formatter: Table.api.formatter." . $formatter . "}";
|
||||
else
|
||||
} else {
|
||||
$html .= "}";
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
|
@ -1367,5 +1420,4 @@ EOD;
|
|||
{
|
||||
return $this->getCamelizeName($field) . 'List';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<a class="btn btn-success btn-recyclebin btn-dialog" href="{%controllerUrl%}/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{%recyclebinHtml%}
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('{%controllerUrl%}/edit')}"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
},{%recyclebinJs%}
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
recyclebin: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
'dragsort_url': ''
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: '{%controllerUrl%}/recyclebin',
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id')},{%recyclebinTitleJs%}
|
||||
{
|
||||
field: 'deletetime',
|
||||
title: __('Deletetime'),
|
||||
operate: 'RANGE',
|
||||
addclass: 'datetimerange',
|
||||
formatter: Table.api.formatter.datetime
|
||||
},
|
||||
{
|
||||
field: 'operate',
|
||||
width: '130px',
|
||||
title: __('Operate'),
|
||||
table: table,
|
||||
events: Table.api.events.operate,
|
||||
buttons: [
|
||||
{
|
||||
name: 'Restore',
|
||||
text: __('Restore'),
|
||||
classname: 'btn btn-xs btn-info btn-restoreit',
|
||||
icon: 'fa fa-rotate-left',
|
||||
url: '{%controllerUrl%}/restore'
|
||||
},
|
||||
{
|
||||
name: 'Destroy',
|
||||
text: __('Destroy'),
|
||||
classname: 'btn btn-xs btn-danger btn-destroyit',
|
||||
icon: 'fa fa-times',
|
||||
url: '{%controllerUrl%}/destroy'
|
||||
}
|
||||
],
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
|
|
@ -3,9 +3,13 @@
|
|||
namespace {%modelNamespace%};
|
||||
|
||||
use think\Model;
|
||||
{%sofeDeleteClassPath%}
|
||||
|
||||
class {%modelName%} extends Model
|
||||
{
|
||||
|
||||
{%softDelete%}
|
||||
|
||||
// 表名
|
||||
protected ${%modelTableType%} = '{%modelTableTypeName%}';
|
||||
|
||||
|
|
@ -15,6 +19,7 @@ class {%modelName%} extends Model
|
|||
// 定义时间戳字段名
|
||||
protected $createTime = {%createTime%};
|
||||
protected $updateTime = {%updateTime%};
|
||||
protected $deleteTime = {%deleteTime%};
|
||||
|
||||
// 追加属性
|
||||
protected $append = [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
<div class="panel panel-default panel-intro">
|
||||
{:build_heading()}
|
||||
|
||||
<div class="panel-body">
|
||||
<div id="myTabContent" class="tab-content">
|
||||
<div class="tab-pane fade active in" id="one">
|
||||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh')}
|
||||
<a class="btn btn-info btn-multi btn-disabled disabled {:$auth->check('{%controllerUrl%}/restore')?'':'hide'}" href="javascript:;" data-url="{%controllerUrl%}/restore" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
|
||||
<a class="btn btn-danger btn-multi btn-disabled disabled {:$auth->check('{%controllerUrl%}/destroy')?'':'hide'}" href="javascript:;" data-url="{%controllerUrl%}/destroy" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
|
||||
<a class="btn btn-success btn-restoreall {:$auth->check('{%controllerUrl%}/restore')?'':'hide'}" href="javascript:;" data-url="{%controllerUrl%}/restore" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
|
||||
<a class="btn btn-danger btn-destroyall {:$auth->check('{%controllerUrl%}/destroy')?'':'hide'}" href="javascript:;" data-url="{%controllerUrl%}/destroy" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-restore="{:$auth->check('{%controllerUrl%}/restore')}"
|
||||
data-operate-destroy="{:$auth->check('{%controllerUrl%}/destroy')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -13,7 +13,6 @@ use think\Exception;
|
|||
|
||||
class Install extends Command
|
||||
{
|
||||
|
||||
protected $model = null;
|
||||
|
||||
protected function configure()
|
||||
|
|
@ -27,7 +26,7 @@ class Install extends Command
|
|||
->addOption('prefix', 'r', Option::VALUE_OPTIONAL, 'table prefix', $config['prefix'])
|
||||
->addOption('username', 'u', Option::VALUE_OPTIONAL, 'mysql username', $config['username'])
|
||||
->addOption('password', 'p', Option::VALUE_OPTIONAL, 'mysql password', $config['password'])
|
||||
->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', FALSE)
|
||||
->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', false)
|
||||
->setDescription('New installation of FastAdmin');
|
||||
}
|
||||
|
||||
|
|
@ -93,5 +92,4 @@ class Install extends Command
|
|||
|
||||
$output->info("Install Successed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use think\Exception;
|
|||
|
||||
class Menu extends Command
|
||||
{
|
||||
|
||||
protected $model = null;
|
||||
|
||||
protected function configure()
|
||||
|
|
@ -32,7 +31,6 @@ class Menu extends Command
|
|||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
|
||||
$this->model = new AuthRule();
|
||||
$adminPath = dirname(__DIR__) . DS;
|
||||
//控制器名
|
||||
|
|
@ -54,10 +52,11 @@ class Menu extends Command
|
|||
$ids = [];
|
||||
$list = $this->model->where(function ($query) use ($controller, $equal) {
|
||||
foreach ($controller as $index => $item) {
|
||||
if ($equal)
|
||||
if ($equal) {
|
||||
$query->whereOr('name', 'eq', $item);
|
||||
else
|
||||
} else {
|
||||
$query->whereOr('name', 'like', strtolower($item) . "%");
|
||||
}
|
||||
}
|
||||
})->select();
|
||||
foreach ($list as $k => $v) {
|
||||
|
|
@ -94,8 +93,11 @@ class Menu extends Command
|
|||
}
|
||||
$this->importRule($item);
|
||||
}
|
||||
|
||||
} else {
|
||||
$authRuleList = AuthRule::select();
|
||||
//生成权限规则备份文件
|
||||
file_put_contents(RUNTIME_PATH . 'authrule.json', json_encode(collection($authRuleList)->toArray()));
|
||||
|
||||
$this->model->where('id', '>', 0)->delete();
|
||||
$controllerDir = $adminPath . 'controller' . DS;
|
||||
// 扫描新的节点信息并导入
|
||||
|
|
@ -199,7 +201,7 @@ class Menu extends Command
|
|||
}
|
||||
}
|
||||
//忽略的类
|
||||
if (stripos($classComment, "@internal") !== FALSE) {
|
||||
if (stripos($classComment, "@internal") !== false) {
|
||||
return;
|
||||
}
|
||||
preg_match_all('#(@.*?)\n#s', $classComment, $annotations);
|
||||
|
|
@ -208,10 +210,10 @@ class Menu extends Command
|
|||
//判断注释中是否设置了icon值
|
||||
if (isset($annotations[1])) {
|
||||
foreach ($annotations[1] as $tag) {
|
||||
if (stripos($tag, '@icon') !== FALSE) {
|
||||
if (stripos($tag, '@icon') !== false) {
|
||||
$controllerIcon = substr($tag, stripos($tag, ' ') + 1);
|
||||
}
|
||||
if (stripos($tag, '@remark') !== FALSE) {
|
||||
if (stripos($tag, '@remark') !== false) {
|
||||
$controllerRemark = substr($tag, stripos($tag, ' ') + 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -226,7 +228,13 @@ class Menu extends Command
|
|||
$pid = 0;
|
||||
foreach ($controllerArr as $k => $v) {
|
||||
$key = $k + 1;
|
||||
$name = strtolower(implode('/', array_slice($controllerArr, 0, $key)));
|
||||
//驼峰转下划线
|
||||
$controllerNameArr = array_slice($controllerArr, 0, $key);
|
||||
foreach ($controllerNameArr as &$val) {
|
||||
$val = strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $val), "_"));
|
||||
}
|
||||
unset($val);
|
||||
$name = implode('/', $controllerNameArr);
|
||||
$title = (!isset($controllerArr[$key]) ? $controllerTitle : '');
|
||||
$icon = (!isset($controllerArr[$key]) ? $controllerIcon : 'fa fa-list');
|
||||
$remark = (!isset($controllerArr[$key]) ? $controllerRemark : '');
|
||||
|
|
@ -259,7 +267,7 @@ class Menu extends Command
|
|||
}
|
||||
$comment = $reflector->getMethod($n->name)->getDocComment();
|
||||
//忽略的方法
|
||||
if (stripos($comment, "@internal") !== FALSE) {
|
||||
if (stripos($comment, "@internal") !== false) {
|
||||
continue;
|
||||
}
|
||||
//过滤掉其它字符
|
||||
|
|
@ -285,5 +293,4 @@ class Menu extends Command
|
|||
return $id ? $id : null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,10 @@ class Min extends Command
|
|||
$resource = $input->getOption('resource') ?: '';
|
||||
$optimize = $input->getOption('optimize') ?: 'none';
|
||||
|
||||
if (!$module || !in_array($module, ['frontend', 'backend', 'all']))
|
||||
{
|
||||
if (!$module || !in_array($module, ['frontend', 'backend', 'all'])) {
|
||||
throw new Exception('Please input correct module name');
|
||||
}
|
||||
if (!$resource || !in_array($resource, ['js', 'css', 'all']))
|
||||
{
|
||||
if (!$resource || !in_array($resource, ['js', 'css', 'all'])) {
|
||||
throw new Exception('Please input correct resource name');
|
||||
}
|
||||
|
||||
|
|
@ -55,41 +53,31 @@ class Min extends Command
|
|||
|
||||
$nodeExec = '';
|
||||
|
||||
if (!$nodeExec)
|
||||
{
|
||||
if (IS_WIN)
|
||||
{
|
||||
if (!$nodeExec) {
|
||||
if (IS_WIN) {
|
||||
// Winsows下请手动配置配置该值,一般将该值配置为 '"C:\Program Files\nodejs\node.exe"',除非你的Node安装路径有变更
|
||||
$nodeExec = 'C:\Program Files\nodejs\node.exe';
|
||||
if (file_exists($nodeExec)){
|
||||
if (file_exists($nodeExec)) {
|
||||
$nodeExec = '"' . $nodeExec . '"';
|
||||
}else{
|
||||
} else {
|
||||
// 如果 '"C:\Program Files\nodejs\node.exe"' 不存在,可能是node安装路径有变更
|
||||
// 但安装node会自动配置环境变量,直接执行 '"node.exe"' 提高第一次使用压缩打包的成功率
|
||||
$nodeExec = '"node.exe"';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
} else {
|
||||
try {
|
||||
$nodeExec = exec("which node");
|
||||
if (!$nodeExec)
|
||||
{
|
||||
if (!$nodeExec) {
|
||||
throw new Exception("node environment not found!please install node first!");
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($moduleArr as $mod)
|
||||
{
|
||||
foreach ($resourceArr as $res)
|
||||
{
|
||||
foreach ($moduleArr as $mod) {
|
||||
foreach ($resourceArr as $res) {
|
||||
$data = [
|
||||
'publicPath' => $publicPath,
|
||||
'jsBaseName' => str_replace('{module}', $mod, $this->options['jsBaseName']),
|
||||
|
|
@ -104,17 +92,14 @@ class Min extends Command
|
|||
|
||||
//源文件
|
||||
$from = $data["{$res}BasePath"] . $data["{$res}BaseName"] . '.' . $res;
|
||||
if (!is_file($from))
|
||||
{
|
||||
if (!is_file($from)) {
|
||||
$output->error("{$res} source file not found!file:{$from}");
|
||||
continue;
|
||||
}
|
||||
if ($res == "js")
|
||||
{
|
||||
if ($res == "js") {
|
||||
$content = file_get_contents($from);
|
||||
preg_match("/require\.config\(\{[\r\n]?[\n]?+(.*?)[\r\n]?[\n]?}\);/is", $content, $matches);
|
||||
if (!isset($matches[1]))
|
||||
{
|
||||
if (!isset($matches[1])) {
|
||||
$output->error("js config not found!");
|
||||
continue;
|
||||
}
|
||||
|
|
@ -128,16 +113,14 @@ class Min extends Command
|
|||
|
||||
// 执行压缩
|
||||
$command = "{$nodeExec} \"{$minPath}r.js\" -o \"{$tempFile}\" >> \"{$minPath}node.log\"";
|
||||
if ($output->isDebug())
|
||||
{
|
||||
if ($output->isDebug()) {
|
||||
$output->warning($command);
|
||||
}
|
||||
echo exec($command);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$output->isDebug())
|
||||
{
|
||||
if (!$output->isDebug()) {
|
||||
@unlink($tempFile);
|
||||
}
|
||||
|
||||
|
|
@ -154,16 +137,14 @@ class Min extends Command
|
|||
protected function writeToFile($name, $data, $pathname)
|
||||
{
|
||||
$search = $replace = [];
|
||||
foreach ($data as $k => $v)
|
||||
{
|
||||
foreach ($data as $k => $v) {
|
||||
$search[] = "{%{$k}%}";
|
||||
$replace[] = $v;
|
||||
}
|
||||
$stub = file_get_contents($this->getStub($name));
|
||||
$content = str_replace($search, $replace, $stub);
|
||||
|
||||
if (!is_dir(dirname($pathname)))
|
||||
{
|
||||
if (!is_dir(dirname($pathname))) {
|
||||
mkdir(strtolower(dirname($pathname)), 0755, true);
|
||||
}
|
||||
return file_put_contents($pathname, $content);
|
||||
|
|
@ -178,5 +159,4 @@ class Min extends Command
|
|||
{
|
||||
return __DIR__ . DS . 'Min' . DS . 'stubs' . DS . $name . '.stub';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ if (!function_exists('build_category_select')) {
|
|||
* @param string $type
|
||||
* @param mixed $selected
|
||||
* @param array $attr
|
||||
* @param array $header
|
||||
* @return string
|
||||
*/
|
||||
function build_category_select($name, $type, $selected = null, $attr = [], $header = [])
|
||||
|
|
@ -98,14 +99,14 @@ if (!function_exists('build_toolbar')) {
|
|||
* @param array $attr 按钮属性值
|
||||
* @return string
|
||||
*/
|
||||
function build_toolbar($btns = NULL, $attr = [])
|
||||
function build_toolbar($btns = null, $attr = [])
|
||||
{
|
||||
$auth = \app\admin\library\Auth::instance();
|
||||
$controller = str_replace('.', '/', strtolower(think\Request::instance()->controller()));
|
||||
$btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del', 'import'];
|
||||
$btns = is_array($btns) ? $btns : explode(',', $btns);
|
||||
$index = array_search('delete', $btns);
|
||||
if ($index !== FALSE) {
|
||||
if ($index !== false) {
|
||||
$btns[$index] = 'del';
|
||||
}
|
||||
$btnAttr = [
|
||||
|
|
@ -140,7 +141,7 @@ if (!function_exists('build_toolbar')) {
|
|||
}
|
||||
$download .= empty($download) ? '' : "\n ";
|
||||
if (!empty($download)) {
|
||||
$html[] = <<<EOT
|
||||
$html[] = <<<EOT
|
||||
<div class="btn-group">
|
||||
<button type="button" href="{$href}" class="btn btn-info btn-import" title="{$title}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="{$icon}"></i> {$text}</button>
|
||||
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown" title="下载批量导入模版">
|
||||
|
|
@ -169,7 +170,7 @@ if (!function_exists('build_heading')) {
|
|||
* @param string $path 指定的path
|
||||
* @return string
|
||||
*/
|
||||
function build_heading($path = NULL, $container = TRUE)
|
||||
function build_heading($path = null, $container = true)
|
||||
{
|
||||
$title = $content = '';
|
||||
if (is_null($path)) {
|
||||
|
|
@ -183,8 +184,9 @@ if (!function_exists('build_heading')) {
|
|||
$title = __($data['title']);
|
||||
$content = __($data['remark']);
|
||||
}
|
||||
if (!$content)
|
||||
if (!$content) {
|
||||
return '';
|
||||
}
|
||||
$result = '<div class="panel-lead"><em>' . $title . '</em>' . $content . '</div>';
|
||||
if ($container) {
|
||||
$result = '<div class="panel-heading">' . $result . '</div>';
|
||||
|
|
|
|||
|
|
@ -37,21 +37,16 @@ class Group extends Backend
|
|||
|
||||
Tree::instance()->init($groupList);
|
||||
$result = [];
|
||||
if ($this->auth->isSuperAdmin())
|
||||
{
|
||||
if ($this->auth->isSuperAdmin()) {
|
||||
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$groups = $this->auth->getGroups();
|
||||
foreach ($groups as $m => $n)
|
||||
{
|
||||
foreach ($groups as $m => $n) {
|
||||
$result = array_merge($result, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid'])));
|
||||
}
|
||||
}
|
||||
$groupName = [];
|
||||
foreach ($result as $k => $v)
|
||||
{
|
||||
foreach ($result as $k => $v) {
|
||||
$groupName[$v['id']] = $v['name'];
|
||||
}
|
||||
|
||||
|
|
@ -66,20 +61,16 @@ class Group extends Backend
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax())
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
$list = AuthGroup::all(array_keys($this->groupdata));
|
||||
$list = collection($list)->toArray();
|
||||
$groupList = [];
|
||||
foreach ($list as $k => $v)
|
||||
{
|
||||
foreach ($list as $k => $v) {
|
||||
$groupList[$v['id']] = $v;
|
||||
}
|
||||
$list = [];
|
||||
foreach ($this->groupdata as $k => $v)
|
||||
{
|
||||
if (isset($groupList[$k]))
|
||||
{
|
||||
foreach ($this->groupdata as $k => $v) {
|
||||
if (isset($groupList[$k])) {
|
||||
$groupList[$k]['name'] = $v;
|
||||
$list[] = $groupList[$k];
|
||||
}
|
||||
|
|
@ -97,17 +88,14 @@ class Group extends Backend
|
|||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost())
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a", [], 'strip_tags');
|
||||
$params['rules'] = explode(',', $params['rules']);
|
||||
if (!in_array($params['pid'], $this->childrenGroupIds))
|
||||
{
|
||||
if (!in_array($params['pid'], $this->childrenGroupIds)) {
|
||||
$this->error(__('The parent group can not be its own child'));
|
||||
}
|
||||
$parentmodel = model("AuthGroup")->get($params['pid']);
|
||||
if (!$parentmodel)
|
||||
{
|
||||
if (!$parentmodel) {
|
||||
$this->error(__('The parent group can not found'));
|
||||
}
|
||||
// 父级别的规则节点
|
||||
|
|
@ -120,8 +108,7 @@ class Group extends Backend
|
|||
// 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
|
||||
$rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
|
||||
$params['rules'] = implode(',', $rules);
|
||||
if ($params)
|
||||
{
|
||||
if ($params) {
|
||||
$this->model->create($params);
|
||||
$this->success();
|
||||
}
|
||||
|
|
@ -133,24 +120,22 @@ class Group extends Backend
|
|||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function edit($ids = NULL)
|
||||
public function edit($ids = null)
|
||||
{
|
||||
$row = $this->model->get(['id' => $ids]);
|
||||
if (!$row)
|
||||
if (!$row) {
|
||||
$this->error(__('No Results were found'));
|
||||
if ($this->request->isPost())
|
||||
{
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a", [], 'strip_tags');
|
||||
// 父节点不能是它自身的子节点
|
||||
if (!in_array($params['pid'], $this->childrenGroupIds))
|
||||
{
|
||||
if (!in_array($params['pid'], $this->childrenGroupIds)) {
|
||||
$this->error(__('The parent group can not be its own child'));
|
||||
}
|
||||
$params['rules'] = explode(',', $params['rules']);
|
||||
|
||||
$parentmodel = model("AuthGroup")->get($params['pid']);
|
||||
if (!$parentmodel)
|
||||
{
|
||||
if (!$parentmodel) {
|
||||
$this->error(__('The parent group can not found'));
|
||||
}
|
||||
// 父级别的规则节点
|
||||
|
|
@ -163,8 +148,7 @@ class Group extends Backend
|
|||
// 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
|
||||
$rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
|
||||
$params['rules'] = implode(',', $rules);
|
||||
if ($params)
|
||||
{
|
||||
if ($params) {
|
||||
$row->save($params);
|
||||
$this->success();
|
||||
}
|
||||
|
|
@ -180,11 +164,10 @@ class Group extends Backend
|
|||
*/
|
||||
public function del($ids = "")
|
||||
{
|
||||
if ($ids)
|
||||
{
|
||||
if ($ids) {
|
||||
$ids = explode(',', $ids);
|
||||
$grouplist = $this->auth->getGroups();
|
||||
$group_ids = array_map(function($group) {
|
||||
$group_ids = array_map(function ($group) {
|
||||
return $group['id'];
|
||||
}, $grouplist);
|
||||
// 移除掉当前管理员所在组别
|
||||
|
|
@ -193,30 +176,25 @@ class Group extends Backend
|
|||
// 循环判断每一个组别是否可删除
|
||||
$grouplist = $this->model->where('id', 'in', $ids)->select();
|
||||
$groupaccessmodel = model('AuthGroupAccess');
|
||||
foreach ($grouplist as $k => $v)
|
||||
{
|
||||
foreach ($grouplist as $k => $v) {
|
||||
// 当前组别下有管理员
|
||||
$groupone = $groupaccessmodel->get(['group_id' => $v['id']]);
|
||||
if ($groupone)
|
||||
{
|
||||
if ($groupone) {
|
||||
$ids = array_diff($ids, [$v['id']]);
|
||||
continue;
|
||||
}
|
||||
// 当前组别下有子组别
|
||||
$groupone = $this->model->get(['pid' => $v['id']]);
|
||||
if ($groupone)
|
||||
{
|
||||
if ($groupone) {
|
||||
$ids = array_diff($ids, [$v['id']]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!$ids)
|
||||
{
|
||||
if (!$ids) {
|
||||
$this->error(__('You can not delete group that contain child group and administrators'));
|
||||
}
|
||||
$count = $this->model->where('id', 'in', $ids)->delete();
|
||||
if ($count)
|
||||
{
|
||||
if ($count) {
|
||||
$this->success();
|
||||
}
|
||||
}
|
||||
|
|
@ -246,35 +224,32 @@ class Group extends Backend
|
|||
$id = $this->request->post("id");
|
||||
$pid = $this->request->post("pid");
|
||||
$parentGroupModel = $model->get($pid);
|
||||
$currentGroupModel = NULL;
|
||||
if ($id)
|
||||
{
|
||||
$currentGroupModel = null;
|
||||
if ($id) {
|
||||
$currentGroupModel = $model->get($id);
|
||||
}
|
||||
if (($pid || $parentGroupModel) && (!$id || $currentGroupModel))
|
||||
{
|
||||
$id = $id ? $id : NULL;
|
||||
if (($pid || $parentGroupModel) && (!$id || $currentGroupModel)) {
|
||||
$id = $id ? $id : null;
|
||||
$ruleList = collection(model('AuthRule')->order('weigh', 'desc')->order('id', 'asc')->select())->toArray();
|
||||
//读取父类角色所有节点列表
|
||||
$parentRuleList = [];
|
||||
if (in_array('*', explode(',', $parentGroupModel->rules)))
|
||||
{
|
||||
if (in_array('*', explode(',', $parentGroupModel->rules))) {
|
||||
$parentRuleList = $ruleList;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$parentRuleIds = explode(',', $parentGroupModel->rules);
|
||||
foreach ($ruleList as $k => $v)
|
||||
{
|
||||
if (in_array($v['id'], $parentRuleIds))
|
||||
{
|
||||
foreach ($ruleList as $k => $v) {
|
||||
if (in_array($v['id'], $parentRuleIds)) {
|
||||
$parentRuleList[] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ruleTree = new Tree();
|
||||
$groupTree = new Tree();
|
||||
//当前所有正常规则列表
|
||||
Tree::instance()->init($parentRuleList);
|
||||
$ruleTree->init($parentRuleList);
|
||||
//角色组列表
|
||||
$groupTree->init(collection(model('AuthGroup')->where('id', 'in', $this->childrenGroupIds)->select())->toArray());
|
||||
|
||||
//读取当前角色下规则ID集合
|
||||
$adminRuleIds = $this->auth->getRuleIds();
|
||||
|
|
@ -283,39 +258,34 @@ class Group extends Backend
|
|||
//当前拥有的规则ID集合
|
||||
$currentRuleIds = $id ? explode(',', $currentGroupModel->rules) : [];
|
||||
|
||||
if (!$id || !in_array($pid, Tree::instance()->getChildrenIds($id, TRUE)))
|
||||
{
|
||||
$parentRuleList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'name');
|
||||
if (!$id || !in_array($pid, $this->childrenGroupIds) || !in_array($pid, $groupTree->getChildrenIds($id, true))) {
|
||||
$parentRuleList = $ruleTree->getTreeList($ruleTree->getTreeArray(0), 'name');
|
||||
$hasChildrens = [];
|
||||
foreach ($parentRuleList as $k => $v)
|
||||
{
|
||||
if ($v['haschild'])
|
||||
foreach ($parentRuleList as $k => $v) {
|
||||
if ($v['haschild']) {
|
||||
$hasChildrens[] = $v['id'];
|
||||
}
|
||||
}
|
||||
$parentRuleIds = array_map(function($item) {
|
||||
$parentRuleIds = array_map(function ($item) {
|
||||
return $item['id'];
|
||||
}, $parentRuleList);
|
||||
$nodeList = [];
|
||||
foreach ($parentRuleList as $k => $v)
|
||||
{
|
||||
if (!$superadmin && !in_array($v['id'], $adminRuleIds))
|
||||
foreach ($parentRuleList as $k => $v) {
|
||||
if (!$superadmin && !in_array($v['id'], $adminRuleIds)) {
|
||||
continue;
|
||||
if ($v['pid'] && !in_array($v['pid'], $parentRuleIds))
|
||||
}
|
||||
if ($v['pid'] && !in_array($v['pid'], $parentRuleIds)) {
|
||||
continue;
|
||||
}
|
||||
$state = array('selected' => in_array($v['id'], $currentRuleIds) && !in_array($v['id'], $hasChildrens));
|
||||
$nodeList[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => __($v['title']), 'type' => 'menu', 'state' => $state);
|
||||
}
|
||||
$this->success('', null, $nodeList);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->error(__('Can not change the parent to child'));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->error(__('Group not found'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,6 +113,12 @@ return [
|
|||
'%d year%s ago' => '%d年前',
|
||||
'Set to normal' => '设为正常',
|
||||
'Set to hidden' => '设为隐藏',
|
||||
'Recycle bin' => '回收站',
|
||||
'Restore' => '还原',
|
||||
'Restore all' => '还原全部',
|
||||
'Destroy' => '销毁',
|
||||
'Destroy all' => '清空回收站',
|
||||
'Nothing need restore' => '没有需要还原的数据',
|
||||
//提示
|
||||
'Go back' => '返回首页',
|
||||
'Jump now' => '立即跳转',
|
||||
|
|
@ -130,6 +136,7 @@ return [
|
|||
'Are you sure you want to delete the %s selected item?' => '确定删除选中的 %s 项?',
|
||||
'Are you sure you want to delete this item?' => '确定删除此项?',
|
||||
'Are you sure you want to delete or turncate?' => '确定删除或清空?',
|
||||
'Are you sure you want to truncate?' => '确定清空?',
|
||||
'You have no permission' => '你没有权限访问',
|
||||
'Please enter your username' => '请输入你的用户名',
|
||||
'Please enter your password' => '请输入你的密码',
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
|||
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Xls;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Csv;
|
||||
use think\Exception;
|
||||
|
||||
trait Backend
|
||||
{
|
||||
|
||||
|
|
@ -19,15 +21,12 @@ trait Backend
|
|||
{
|
||||
if (is_array($this->excludeFields)) {
|
||||
foreach ($this->excludeFields as $field) {
|
||||
if (key_exists($field,$params))
|
||||
{
|
||||
if (key_exists($field, $params)) {
|
||||
unset($params[$field]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (key_exists($this->excludeFields,$params))
|
||||
{
|
||||
if (key_exists($this->excludeFields, $params)) {
|
||||
unset($params[$this->excludeFields]);
|
||||
}
|
||||
}
|
||||
|
|
@ -104,7 +103,6 @@ trait Backend
|
|||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a");
|
||||
if ($params) {
|
||||
|
||||
$params = $this->preExcludeFields($params);
|
||||
|
||||
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
|
||||
|
|
@ -137,11 +135,12 @@ trait Backend
|
|||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function edit($ids = NULL)
|
||||
public function edit($ids = null)
|
||||
{
|
||||
$row = $this->model->get($ids);
|
||||
if (!$row)
|
||||
if (!$row) {
|
||||
$this->error(__('No Results were found'));
|
||||
}
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
if (!in_array($row[$this->dataLimitField], $adminIds)) {
|
||||
|
|
@ -151,7 +150,6 @@ trait Backend
|
|||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a");
|
||||
if ($params) {
|
||||
|
||||
$params = $this->preExcludeFields($params);
|
||||
|
||||
try {
|
||||
|
|
@ -419,5 +417,4 @@ trait Backend
|
|||
|
||||
$this->success();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@
|
|||
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
|
||||
</div>
|
||||
{/case}
|
||||
|
|
@ -109,6 +110,7 @@
|
|||
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
{/case}
|
||||
{case switch}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><small>{:__('Check all')}</small></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-status" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<div class="radio">
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><small>{:__('Check all')}</small></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-status" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
||||
<div class="radio">
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
<div class="form-group">
|
||||
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Ismenu')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Ismenu')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_radios('row[ismenu]', ['1'=>__('Yes'), '0'=>__('No')])}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="c-pid" class="control-label col-xs-12 col-sm-2">{:__('Pid')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Pid')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_select('row[pid]', $ruledata, null, ['class'=>'form-control', 'required'=>''])}
|
||||
</div>
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Ismenu')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Ismenu')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_radios('row[ismenu]', ['1'=>__('Yes'), '0'=>__('No')], $row['ismenu'])}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pid" class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_select('row[pid]', $ruledata, $row['pid'], ['class'=>'form-control', 'required'=>''])}
|
||||
</div>
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-password" data-rule="" class="form-control" name="row[password]" type="text" value="" placeholder="{:__('Leave password blank if dont want to change')}" autocomplete="new-password" />
|
||||
<input id="c-password" data-rule="password" class="form-control" name="row[password]" type="text" value="" placeholder="{:__('Leave password blank if dont want to change')}" autocomplete="new-password" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -40,18 +40,14 @@ class User extends Api
|
|||
{
|
||||
$account = $this->request->request('account');
|
||||
$password = $this->request->request('password');
|
||||
if (!$account || !$password)
|
||||
{
|
||||
if (!$account || !$password) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$ret = $this->auth->login($account, $password);
|
||||
if ($ret)
|
||||
{
|
||||
if ($ret) {
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Logged in successful'), $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
|
@ -66,36 +62,27 @@ class User extends Api
|
|||
{
|
||||
$mobile = $this->request->request('mobile');
|
||||
$captcha = $this->request->request('captcha');
|
||||
if (!$mobile || !$captcha)
|
||||
{
|
||||
if (!$mobile || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if (!Validate::regex($mobile, "^1\d{10}$"))
|
||||
{
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
if (!Sms::check($mobile, $captcha, 'mobilelogin'))
|
||||
{
|
||||
if (!Sms::check($mobile, $captcha, 'mobilelogin')) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
$user = \app\common\model\User::getByMobile($mobile);
|
||||
if ($user)
|
||||
{
|
||||
if ($user) {
|
||||
//如果已经有账号则直接登录
|
||||
$ret = $this->auth->direct($user->id);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
|
||||
}
|
||||
if ($ret)
|
||||
{
|
||||
if ($ret) {
|
||||
Sms::flush($mobile, 'mobilelogin');
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Logged in successful'), $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
|
@ -114,26 +101,20 @@ class User extends Api
|
|||
$password = $this->request->request('password');
|
||||
$email = $this->request->request('email');
|
||||
$mobile = $this->request->request('mobile');
|
||||
if (!$username || !$password)
|
||||
{
|
||||
if (!$username || !$password) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if ($email && !Validate::is($email, "email"))
|
||||
{
|
||||
if ($email && !Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
if ($mobile && !Validate::regex($mobile, "^1\d{10}$"))
|
||||
{
|
||||
if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
$ret = $this->auth->register($username, $password, $email, $mobile, []);
|
||||
if ($ret)
|
||||
{
|
||||
if ($ret) {
|
||||
$data = ['userinfo' => $this->auth->getUserinfo()];
|
||||
$this->success(__('Sign up successful'), $data);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
|
@ -162,12 +143,13 @@ class User extends Api
|
|||
$nickname = $this->request->request('nickname');
|
||||
$bio = $this->request->request('bio');
|
||||
$avatar = $this->request->request('avatar');
|
||||
$exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();
|
||||
if ($exists)
|
||||
{
|
||||
$this->error(__('Username already exists'));
|
||||
if ($username) {
|
||||
$exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();
|
||||
if ($exists) {
|
||||
$this->error(__('Username already exists'));
|
||||
}
|
||||
$user->username = $username;
|
||||
}
|
||||
$user->username = $username;
|
||||
$user->nickname = $nickname;
|
||||
$user->bio = $bio;
|
||||
$user->avatar = $avatar;
|
||||
|
|
@ -186,21 +168,17 @@ class User extends Api
|
|||
$user = $this->auth->getUser();
|
||||
$email = $this->request->post('email');
|
||||
$captcha = $this->request->request('captcha');
|
||||
if (!$email || !$captcha)
|
||||
{
|
||||
if (!$email || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if (!Validate::is($email, "email"))
|
||||
{
|
||||
if (!Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find())
|
||||
{
|
||||
if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) {
|
||||
$this->error(__('Email already exists'));
|
||||
}
|
||||
$result = Ems::check($email, $captcha, 'changeemail');
|
||||
if (!$result)
|
||||
{
|
||||
if (!$result) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
$verification = $user->verification;
|
||||
|
|
@ -224,21 +202,17 @@ class User extends Api
|
|||
$user = $this->auth->getUser();
|
||||
$mobile = $this->request->request('mobile');
|
||||
$captcha = $this->request->request('captcha');
|
||||
if (!$mobile || !$captcha)
|
||||
{
|
||||
if (!$mobile || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if (!Validate::regex($mobile, "^1\d{10}$"))
|
||||
{
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find())
|
||||
{
|
||||
if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find()) {
|
||||
$this->error(__('Mobile already exists'));
|
||||
}
|
||||
$result = Sms::check($mobile, $captcha, 'changemobile');
|
||||
if (!$result)
|
||||
{
|
||||
if (!$result) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
$verification = $user->verification;
|
||||
|
|
@ -263,18 +237,15 @@ class User extends Api
|
|||
$platform = $this->request->request("platform");
|
||||
$code = $this->request->request("code");
|
||||
$config = get_addon_config('third');
|
||||
if (!$config || !isset($config[$platform]))
|
||||
{
|
||||
if (!$config || !isset($config[$platform])) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$app = new \addons\third\library\Application($config);
|
||||
//通过code换access_token和绑定会员
|
||||
$result = $app->{$platform}->getUserInfo(['code' => $code]);
|
||||
if ($result)
|
||||
{
|
||||
if ($result) {
|
||||
$loginret = \addons\third\library\Service::connect($platform, $result);
|
||||
if ($loginret)
|
||||
{
|
||||
if ($loginret) {
|
||||
$data = [
|
||||
'userinfo' => $this->auth->getUserinfo(),
|
||||
'thirdinfo' => $result
|
||||
|
|
@ -299,42 +270,32 @@ class User extends Api
|
|||
$email = $this->request->request("email");
|
||||
$newpassword = $this->request->request("newpassword");
|
||||
$captcha = $this->request->request("captcha");
|
||||
if (!$newpassword || !$captcha)
|
||||
{
|
||||
if (!$newpassword || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
if ($type == 'mobile')
|
||||
{
|
||||
if (!Validate::regex($mobile, "^1\d{10}$"))
|
||||
{
|
||||
if ($type == 'mobile') {
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
}
|
||||
$user = \app\common\model\User::getByMobile($mobile);
|
||||
if (!$user)
|
||||
{
|
||||
if (!$user) {
|
||||
$this->error(__('User not found'));
|
||||
}
|
||||
$ret = Sms::check($mobile, $captcha, 'resetpwd');
|
||||
if (!$ret)
|
||||
{
|
||||
if (!$ret) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
Sms::flush($mobile, 'resetpwd');
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Validate::is($email, "email"))
|
||||
{
|
||||
} else {
|
||||
if (!Validate::is($email, "email")) {
|
||||
$this->error(__('Email is incorrect'));
|
||||
}
|
||||
$user = \app\common\model\User::getByEmail($email);
|
||||
if (!$user)
|
||||
{
|
||||
if (!$user) {
|
||||
$this->error(__('User not found'));
|
||||
}
|
||||
$ret = Ems::check($email, $captcha, 'resetpwd');
|
||||
if (!$ret)
|
||||
{
|
||||
if (!$ret) {
|
||||
$this->error(__('Captcha is incorrect'));
|
||||
}
|
||||
Ems::flush($email, 'resetpwd');
|
||||
|
|
@ -342,12 +303,9 @@ class User extends Api
|
|||
//模拟一次登录
|
||||
$this->auth->direct($user->id);
|
||||
$ret = $this->auth->changepwd($newpassword, '', true);
|
||||
if ($ret)
|
||||
{
|
||||
if ($ret) {
|
||||
$this->success(__('Reset password successful'));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->error($this->auth->getError());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class Frontend extends Controller
|
|||
$this->auth->init($token);
|
||||
//检测是否登录
|
||||
if (!$this->auth->isLogin()) {
|
||||
$this->error(__('Please login first'), 'user/login');
|
||||
$this->error(__('Please login first'), 'index/user/login');
|
||||
}
|
||||
// 判断是否需要验证权限
|
||||
if (!$this->auth->match($this->noNeedRight)) {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,9 @@
|
|||
padding-left:0px;
|
||||
}
|
||||
}
|
||||
.label-primary {
|
||||
background-color: #248aff;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
|
@ -3727,7 +3730,7 @@
|
|||
|
||||
<div class="row mt0 footer">
|
||||
<div class="col-md-6" align="left">
|
||||
Generated on 2018-10-19 17:00:36 </div>
|
||||
Generated on 2019-02-26 17:13:43 </div>
|
||||
<div class="col-md-6" align="right">
|
||||
<a href="https://www.fastadmin.net" target="_blank">FastAdmin</a>
|
||||
</div>
|
||||
|
|
@ -3929,6 +3932,9 @@
|
|||
contentType: false,
|
||||
processData: false,
|
||||
headers: headers,
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
success: function (data, textStatus, xhr) {
|
||||
if (typeof data === 'object') {
|
||||
var str = JSON.stringify(data, null, 2);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -92,7 +92,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
'click .btn-chooseone': function (e, value, row, index) {
|
||||
var multiple = Backend.api.query('multiple');
|
||||
multiple = multiple == 'true' ? true : false;
|
||||
Fast.api.close({url: row.url, multiple: false});
|
||||
Fast.api.close({url: row.url, multiple: multiple});
|
||||
},
|
||||
}, formatter: function () {
|
||||
return '<a href="javascript:;" class="btn btn-danger btn-chooseone btn-xs"><i class="fa fa-check"></i> ' + __('Choose') + '</a>';
|
||||
|
|
@ -110,7 +110,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
});
|
||||
var multiple = Backend.api.query('multiple');
|
||||
multiple = multiple == 'true' ? true : false;
|
||||
Fast.api.close({url: urlArr.join(","), multiple: true});
|
||||
Fast.api.close({url: urlArr.join(","), multiple: multiple});
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@
|
|||
var searchQuery = getSearchQuery(this);
|
||||
this.trigger('common-search', this, searchQuery);
|
||||
this.options.pageNumber = 1;
|
||||
this.options.pageSize = $.fn.bootstrapTable.defaults.pageSize;
|
||||
//this.options.pageSize = $.fn.bootstrapTable.defaults.pageSize;
|
||||
this.refresh({});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine
|
|||
},
|
||||
//打开一个弹出窗口
|
||||
open: function (url, title, options) {
|
||||
title = title ? title : "";
|
||||
title = options && options.title ? options.title : (title ? title : "");
|
||||
url = Fast.api.fixurl(url);
|
||||
url = url + (url.indexOf("?") > -1 ? "&" : "?") + "dialog=1";
|
||||
var area = [$(window).width() > 800 ? '800px' : '95%', $(window).height() > 600 ? '600px' : '95%'];
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -16,6 +16,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
showExport: true,
|
||||
exportDataType: "all",
|
||||
exportTypes: ['json', 'xml', 'csv', 'txt', 'doc', 'excel'],
|
||||
exportOptions: {
|
||||
fileName: 'export_' + Moment().format("YYYY-MM-DD"),
|
||||
ignoreColumn: [0, 'operate'] //默认不导出第一列(checkbox)与操作(operate)列
|
||||
},
|
||||
pageSize: 10,
|
||||
pageList: [10, 25, 50, 'All'],
|
||||
pagination: true,
|
||||
|
|
@ -62,6 +66,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
multibtn: '.btn-multi',
|
||||
disabledbtn: '.btn-disabled',
|
||||
editonebtn: '.btn-editone',
|
||||
restoreonebtn: '.btn-restoreone',
|
||||
destroyonebtn: '.btn-destroyone',
|
||||
restoreallbtn: '.btn-restoreall',
|
||||
destroyallbtn: '.btn-destroyall',
|
||||
dragsortfield: 'weigh',
|
||||
},
|
||||
api: {
|
||||
|
|
@ -203,6 +211,29 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
Fast.api.open(url, __('Edit'), $(that).data() || {});
|
||||
});
|
||||
});
|
||||
//清空回收站
|
||||
$(document).on('click', Table.config.destroyallbtn, function () {
|
||||
var that = this;
|
||||
Layer.confirm(__('Are you sure you want to truncate?'), function () {
|
||||
var url = $(that).data("url") ? $(that).data("url") : $(that).attr("href");
|
||||
Fast.api.ajax(url, function () {
|
||||
Layer.closeAll();
|
||||
table.bootstrapTable('refresh');
|
||||
}, function () {
|
||||
Layer.closeAll();
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
//还原或删除
|
||||
$(document).on('click', Table.config.restoreallbtn + ',' + Table.config.restoreonebtn + ',' + Table.config.destroyonebtn, function () {
|
||||
var that = this;
|
||||
var url = $(that).data("url") ? $(that).data("url") : $(that).attr("href");
|
||||
Fast.api.ajax(url, function () {
|
||||
table.bootstrapTable('refresh');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
// 批量操作按钮事件
|
||||
$(toolbar).on('click', Table.config.multibtn, function () {
|
||||
var ids = Table.api.selectedids(table);
|
||||
|
|
@ -369,14 +400,14 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
},//单元格图片预览
|
||||
image: {
|
||||
'click .img-center': function (e, value, row, index) {
|
||||
data = [];
|
||||
value= value.split(",");
|
||||
var data = [];
|
||||
value = value.split(",");
|
||||
$.each(value, function (index, value) {
|
||||
data.push({
|
||||
src: Fast.api.cdnurl(value),
|
||||
});
|
||||
});
|
||||
layer.photos({
|
||||
Layer.photos({
|
||||
photos: {
|
||||
"data": data
|
||||
},
|
||||
|
|
@ -558,7 +589,8 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
type = typeof type === 'undefined' ? 'buttons' : type;
|
||||
var options = table ? table.bootstrapTable('getOptions') : {};
|
||||
var html = [];
|
||||
var hidden, visible, disable, url, classname, icon, text, title, refresh, confirm, extend, click, dropdown, link;
|
||||
var hidden, visible, disable, url, classname, icon, text, title, refresh, confirm, extend,
|
||||
dropdown, link;
|
||||
var fieldIndex = column.fieldIndex;
|
||||
var dropdowns = {};
|
||||
|
||||
|
|
@ -573,11 +605,11 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
}
|
||||
var attr = table.data(type + "-" + j.name);
|
||||
if (typeof attr === 'undefined' || attr) {
|
||||
hidden = typeof j.hidden === 'function' ? j.hidden.call(table, row, j) : (j.hidden ? j.hidden : false);
|
||||
hidden = typeof j.hidden === 'function' ? j.hidden.call(table, row, j) : (typeof j.hidden !== 'undefined' ? j.hidden : false);
|
||||
if (hidden) {
|
||||
return true;
|
||||
}
|
||||
visible = typeof j.visible === 'function' ? j.visible.call(table, row, j) : (j.visible ? j.visible : true);
|
||||
visible = typeof j.visible === 'function' ? j.visible.call(table, row, j) : (typeof j.visible !== 'undefined' ? j.visible : true);
|
||||
if (!visible) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -586,12 +618,12 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
url = typeof url === 'function' ? url.call(table, row, j) : (url ? Fast.api.fixurl(Table.api.replaceurl(url, row, table)) : 'javascript:;');
|
||||
classname = j.classname ? j.classname : 'btn-primary btn-' + name + 'one';
|
||||
icon = j.icon ? j.icon : '';
|
||||
text = j.text ? j.text : '';
|
||||
title = j.title ? j.title : text;
|
||||
text = typeof j.text === 'function' ? j.text.call(table, row, j) : j.text ? j.text : '';
|
||||
title = typeof j.title === 'function' ? j.title.call(table, row, j) : j.title ? j.title : text;
|
||||
refresh = j.refresh ? 'data-refresh="' + j.refresh + '"' : '';
|
||||
confirm = j.confirm ? 'data-confirm="' + j.confirm + '"' : '';
|
||||
extend = j.extend ? j.extend : '';
|
||||
disable = typeof j.disable === 'function' ? j.disable.call(table, row, j) : (j.disable ? j.disable : false);
|
||||
disable = typeof j.disable === 'function' ? j.disable.call(table, row, j) : (typeof j.disable !== 'undefined' ? j.disable : false);
|
||||
if (disable) {
|
||||
classname = classname + ' disabled';
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue