作者 Karson

新增CRUD生成回收站视图和JS文件

新增一键生成API文档排序功能
新增表格默认导出选项
新增buttons中text和title的function支持
修复buttons中visible和disable为false时的判断Bug
修复后台添加子管理员的权限错误
正在显示 35 个修改的文件 包含 517 行增加357 行删除
... ... @@ -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,8 +181,7 @@ 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),
... ... @@ -177,12 +194,24 @@ class Builder
'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'];
/**
* 排除字段
... ... @@ -112,6 +111,24 @@ class Crud extends Command
protected $headingFilterField = 'status';
/**
* 添加时间字段
* @var string
*/
protected $createTimeField = 'createtime';
/**
* 更新时间字段
* @var string
*/
protected $updateTimeField = 'updatetime';
/**
* 软删除时间字段
* @var string
*/
protected $deleteTimeField = 'deletetime';
/**
* 编辑器的Class
*/
protected $editorClass = 'editor';
... ... @@ -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,9 +1378,10 @@ 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);
$searchList = str_replace(['":"', '"}', ')","'], ['":', '}', '),"'], $searchList);
... ... @@ -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';
}
}
... ...
<a class="btn btn-success btn-recyclebin btn-dialog" href="{%controllerUrl%}/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
\ No newline at end of file
... ...
... ... @@ -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();
},
... ...
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);
},
\ No newline at end of file
... ...
... ... @@ -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 = [
... ...
<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,11 +52,12 @@ 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) {
$output->warning($v->name);
... ... @@ -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 = [
... ... @@ -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">
... ...
<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>
... ...
<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');
if ($username) {
$exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();
if ($exists)
{
if ($exists) {
$this->error(__('Username already exists'));
}
$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);
... ...
... ... @@ -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%'];
... ...
... ... @@ -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';
}
... ...