mirror of https://gitee.com/karson/fastadmin.git
新增CRUD一键生成筛选选项卡功能
新增一键生成API文档导航列表功能 优化后台默认加载页的响应速度 优化二级栏目挺拽排序功能 修复后台部分列表会被截断的BUG 修复一键生成API文档@ApiInternal不生效的BUG 修复一键生成API文档空类的BUG 修复一键生成CRUD模型不正在字段的BUGpull/69/head
parent
3683728023
commit
9753d94bc0
|
|
@ -93,6 +93,7 @@ class Api extends Command
|
||||||
$classes[] = $this->get_class_from_file($filePath);
|
$classes[] = $this->get_class_from_file($filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$classes = array_unique(array_filter($classes));
|
||||||
|
|
||||||
$config = [
|
$config = [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ return [
|
||||||
'Required' => '必选',
|
'Required' => '必选',
|
||||||
'Description' => '描述',
|
'Description' => '描述',
|
||||||
'Send' => '提交',
|
'Send' => '提交',
|
||||||
|
'Reset' => '重置',
|
||||||
'Tokentips' => 'Token在会员注册或登录后都会返回,WEB端同时存在于Cookie中',
|
'Tokentips' => 'Token在会员注册或登录后都会返回,WEB端同时存在于Cookie中',
|
||||||
'Apiurltips' => 'API接口URL',
|
'Apiurltips' => 'API接口URL',
|
||||||
'Savetips' => '点击保存后Token和Api url都将保存在本地Localstorage中',
|
'Savetips' => '点击保存后Token和Api url都将保存在本地Localstorage中',
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,18 @@ class Builder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @var \think\View
|
* @var \think\View
|
||||||
*/
|
*/
|
||||||
public $view = null;
|
public $view = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parse classes
|
* parse classes
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $classes = [];
|
protected $classes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param array $classes
|
* @param array $classes
|
||||||
*/
|
*/
|
||||||
public function __construct($classes = [])
|
public function __construct($classes = [])
|
||||||
|
|
@ -37,8 +37,12 @@ class Builder
|
||||||
protected function extractAnnotations()
|
protected function extractAnnotations()
|
||||||
{
|
{
|
||||||
$st_output = [];
|
$st_output = [];
|
||||||
foreach ($this->classes as $class)
|
foreach ($this->classes as $class) {
|
||||||
{
|
$classAnnotation = Extractor::getClassAnnotations($class);
|
||||||
|
// 如果忽略
|
||||||
|
if (isset($classAnnotation['ApiInternal'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$st_output[] = Extractor::getAllClassAnnotations($class);
|
$st_output[] = Extractor::getAllClassAnnotations($class);
|
||||||
}
|
}
|
||||||
return end($st_output);
|
return end($st_output);
|
||||||
|
|
@ -46,14 +50,12 @@ class Builder
|
||||||
|
|
||||||
protected function generateHeadersTemplate($docs)
|
protected function generateHeadersTemplate($docs)
|
||||||
{
|
{
|
||||||
if (!isset($docs['ApiHeaders']))
|
if (!isset($docs['ApiHeaders'])) {
|
||||||
{
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$headerslist = array();
|
$headerslist = array();
|
||||||
foreach ($docs['ApiHeaders'] as $params)
|
foreach ($docs['ApiHeaders'] as $params) {
|
||||||
{
|
|
||||||
$tr = array(
|
$tr = array(
|
||||||
'name' => $params['name'],
|
'name' => $params['name'],
|
||||||
'type' => $params['type'],
|
'type' => $params['type'],
|
||||||
|
|
@ -69,14 +71,12 @@ class Builder
|
||||||
|
|
||||||
protected function generateParamsTemplate($docs)
|
protected function generateParamsTemplate($docs)
|
||||||
{
|
{
|
||||||
if (!isset($docs['ApiParams']))
|
if (!isset($docs['ApiParams'])) {
|
||||||
{
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$paramslist = array();
|
$paramslist = array();
|
||||||
foreach ($docs['ApiParams'] as $params)
|
foreach ($docs['ApiParams'] as $params) {
|
||||||
{
|
|
||||||
$tr = array(
|
$tr = array(
|
||||||
'name' => $params['name'],
|
'name' => $params['name'],
|
||||||
'type' => isset($params['type']) ? $params['type'] : 'string',
|
'type' => isset($params['type']) ? $params['type'] : 'string',
|
||||||
|
|
@ -92,14 +92,12 @@ class Builder
|
||||||
|
|
||||||
protected function generateReturnHeadersTemplate($docs)
|
protected function generateReturnHeadersTemplate($docs)
|
||||||
{
|
{
|
||||||
if (!isset($docs['ApiReturnHeaders']))
|
if (!isset($docs['ApiReturnHeaders'])) {
|
||||||
{
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$headerslist = array();
|
$headerslist = array();
|
||||||
foreach ($docs['ApiReturnHeaders'] as $params)
|
foreach ($docs['ApiReturnHeaders'] as $params) {
|
||||||
{
|
|
||||||
$tr = array(
|
$tr = array(
|
||||||
'name' => $params['name'],
|
'name' => $params['name'],
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
|
|
@ -115,14 +113,12 @@ class Builder
|
||||||
|
|
||||||
protected function generateReturnParamsTemplate($st_params)
|
protected function generateReturnParamsTemplate($st_params)
|
||||||
{
|
{
|
||||||
if (!isset($st_params['ApiReturnParams']))
|
if (!isset($st_params['ApiReturnParams'])) {
|
||||||
{
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$paramslist = array();
|
$paramslist = array();
|
||||||
foreach ($st_params['ApiReturnParams'] as $params)
|
foreach ($st_params['ApiReturnParams'] as $params) {
|
||||||
{
|
|
||||||
$tr = array(
|
$tr = array(
|
||||||
'name' => $params['name'],
|
'name' => $params['name'],
|
||||||
'type' => isset($params['type']) ? $params['type'] : 'string',
|
'type' => isset($params['type']) ? $params['type'] : 'string',
|
||||||
|
|
@ -157,20 +153,14 @@ class Builder
|
||||||
$counter = 0;
|
$counter = 0;
|
||||||
$section = null;
|
$section = null;
|
||||||
$docslist = [];
|
$docslist = [];
|
||||||
foreach ($annotations as $class => $methods)
|
foreach ($annotations as $class => $methods) {
|
||||||
{
|
foreach ($methods as $name => $docs) {
|
||||||
foreach ($methods as $name => $docs)
|
if (isset($docs['ApiSector'][0])) {
|
||||||
{
|
|
||||||
if (isset($docs['ApiSector'][0]))
|
|
||||||
{
|
|
||||||
$section = is_array($docs['ApiSector'][0]) ? $docs['ApiSector'][0]['data'] : $docs['ApiSector'][0];
|
$section = is_array($docs['ApiSector'][0]) ? $docs['ApiSector'][0]['data'] : $docs['ApiSector'][0];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$section = $class;
|
$section = $class;
|
||||||
}
|
}
|
||||||
if (0 === count($docs))
|
if (0 === count($docs)) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,6 +170,7 @@ class Builder
|
||||||
'method_label' => $this->generateBadgeForMethod($docs),
|
'method_label' => $this->generateBadgeForMethod($docs),
|
||||||
'section' => $section,
|
'section' => $section,
|
||||||
'route' => is_array($docs['ApiRoute'][0]) ? $docs['ApiRoute'][0]['data'] : $docs['ApiRoute'][0],
|
'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],
|
||||||
'summary' => is_array($docs['ApiSummary'][0]) ? $docs['ApiSummary'][0]['data'] : $docs['ApiSummary'][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] : '',
|
'body' => isset($docs['ApiBody'][0]) ? is_array($docs['ApiBody'][0]) ? $docs['ApiBody'][0]['data'] : $docs['ApiBody'][0] : '',
|
||||||
'headerslist' => $this->generateHeadersTemplate($docs),
|
'headerslist' => $this->generateHeadersTemplate($docs),
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class Extractor
|
||||||
*/
|
*/
|
||||||
public function setStrict($value)
|
public function setStrict($value)
|
||||||
{
|
{
|
||||||
$this->strict = (bool) $value;
|
$this->strict = (bool)$value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -67,8 +67,7 @@ class Extractor
|
||||||
*/
|
*/
|
||||||
public static function getClassAnnotations($className)
|
public static function getClassAnnotations($className)
|
||||||
{
|
{
|
||||||
if (!isset(self::$annotationCache[$className]))
|
if (!isset(self::$annotationCache[$className])) {
|
||||||
{
|
|
||||||
$class = new \ReflectionClass($className);
|
$class = new \ReflectionClass($className);
|
||||||
self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment());
|
self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment());
|
||||||
}
|
}
|
||||||
|
|
@ -80,8 +79,7 @@ class Extractor
|
||||||
{
|
{
|
||||||
$class = new \ReflectionClass($className);
|
$class = new \ReflectionClass($className);
|
||||||
|
|
||||||
foreach ($class->getMethods() as $object)
|
foreach ($class->getMethods() as $object) {
|
||||||
{
|
|
||||||
self::$annotationCache['annotations'][$className][$object->name] = self::getMethodAnnotations($className, $object->name);
|
self::$annotationCache['annotations'][$className][$object->name] = self::getMethodAnnotations($className, $object->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,29 +89,22 @@ class Extractor
|
||||||
/**
|
/**
|
||||||
* Gets all anotations with pattern @SomeAnnotation() from a determinated method of a given class
|
* Gets all anotations with pattern @SomeAnnotation() from a determinated method of a given class
|
||||||
*
|
*
|
||||||
* @param string $className class name
|
* @param string $className class name
|
||||||
* @param string $methodName method name to get annotations
|
* @param string $methodName method name to get annotations
|
||||||
* @return array self::$annotationCache all annotated elements of a method given
|
* @return array self::$annotationCache all annotated elements of a method given
|
||||||
*/
|
*/
|
||||||
public static function getMethodAnnotations($className, $methodName)
|
public static function getMethodAnnotations($className, $methodName)
|
||||||
{
|
{
|
||||||
if (!isset(self::$annotationCache[$className . '::' . $methodName]))
|
if (!isset(self::$annotationCache[$className . '::' . $methodName])) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
$method = new \ReflectionMethod($className, $methodName);
|
$method = new \ReflectionMethod($className, $methodName);
|
||||||
$class = new \ReflectionClass($className);
|
$class = new \ReflectionClass($className);
|
||||||
if (!$method->isPublic() || $method->isConstructor())
|
if (!$method->isPublic() || $method->isConstructor()) {
|
||||||
{
|
|
||||||
$annotations = array();
|
$annotations = array();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$annotations = self::consolidateAnnotations($method, $class);
|
$annotations = self::consolidateAnnotations($method, $class);
|
||||||
}
|
}
|
||||||
}
|
} catch (\ReflectionException $e) {
|
||||||
catch (\ReflectionException $e)
|
|
||||||
{
|
|
||||||
$annotations = array();
|
$annotations = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +118,7 @@ class Extractor
|
||||||
* Gets all anotations with pattern @SomeAnnotation() from a determinated method of a given class
|
* Gets all anotations with pattern @SomeAnnotation() from a determinated method of a given class
|
||||||
* and instance its abcAnnotation class
|
* and instance its abcAnnotation class
|
||||||
*
|
*
|
||||||
* @param string $className class name
|
* @param string $className class name
|
||||||
* @param string $methodName method name to get annotations
|
* @param string $methodName method name to get annotations
|
||||||
* @return array self::$annotationCache all annotated objects of a method given
|
* @return array self::$annotationCache all annotated objects of a method given
|
||||||
*/
|
*/
|
||||||
|
|
@ -138,42 +129,31 @@ class Extractor
|
||||||
|
|
||||||
$i = 0;
|
$i = 0;
|
||||||
|
|
||||||
foreach ($annotations as $annotationClass => $listParams)
|
foreach ($annotations as $annotationClass => $listParams) {
|
||||||
{
|
|
||||||
$annotationClass = ucfirst($annotationClass);
|
$annotationClass = ucfirst($annotationClass);
|
||||||
$class = $this->defaultNamespace . $annotationClass . 'Annotation';
|
$class = $this->defaultNamespace . $annotationClass . 'Annotation';
|
||||||
|
|
||||||
// verify is the annotation class exists, depending if Annotations::strict is true
|
// verify is the annotation class exists, depending if Annotations::strict is true
|
||||||
// if not, just skip the annotation instance creation.
|
// if not, just skip the annotation instance creation.
|
||||||
if (!class_exists($class))
|
if (!class_exists($class)) {
|
||||||
{
|
if ($this->strict) {
|
||||||
if ($this->strict)
|
|
||||||
{
|
|
||||||
throw new Exception(sprintf('Runtime Error: Annotation Class Not Found: %s', $class));
|
throw new Exception(sprintf('Runtime Error: Annotation Class Not Found: %s', $class));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// silent skip & continue
|
// silent skip & continue
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($objects[$annotationClass]))
|
if (empty($objects[$annotationClass])) {
|
||||||
{
|
|
||||||
$objects[$annotationClass] = new $class();
|
$objects[$annotationClass] = new $class();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($listParams as $params)
|
foreach ($listParams as $params) {
|
||||||
{
|
if (is_array($params)) {
|
||||||
if (is_array($params))
|
foreach ($params as $key => $value) {
|
||||||
{
|
|
||||||
foreach ($params as $key => $value)
|
|
||||||
{
|
|
||||||
$objects[$annotationClass]->set($key, $value);
|
$objects[$annotationClass]->set($key, $value);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$objects[$annotationClass]->set($i++, $params);
|
$objects[$annotationClass]->set($i++, $params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,8 +170,7 @@ class Extractor
|
||||||
|
|
||||||
$methodAnnotations = self::parseAnnotations($docblockMethod);
|
$methodAnnotations = self::parseAnnotations($docblockMethod);
|
||||||
$classAnnotations = self::parseAnnotations($dockblockClass);
|
$classAnnotations = self::parseAnnotations($dockblockClass);
|
||||||
if (isset($methodAnnotations['ApiInternal']) || $methodName == '_initialize' || $methodName == '_empty')
|
if (isset($methodAnnotations['ApiInternal']) || $methodName == '_initialize' || $methodName == '_empty') {
|
||||||
{
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,74 +184,58 @@ class Extractor
|
||||||
$methodTitle = isset($methodArr[1]) && isset($methodArr[1][0]) ? $methodArr[1][0] : '';
|
$methodTitle = isset($methodArr[1]) && isset($methodArr[1][0]) ? $methodArr[1][0] : '';
|
||||||
$classTitle = isset($classArr[1]) && isset($classArr[1][0]) ? $classArr[1][0] : '';
|
$classTitle = isset($classArr[1]) && isset($classArr[1][0]) ? $classArr[1][0] : '';
|
||||||
|
|
||||||
if (!isset($methodAnnotations['ApiMethod']))
|
if (!isset($methodAnnotations['ApiMethod'])) {
|
||||||
{
|
|
||||||
$methodAnnotations['ApiMethod'] = ['get'];
|
$methodAnnotations['ApiMethod'] = ['get'];
|
||||||
}
|
}
|
||||||
if (!isset($methodAnnotations['ApiSummary']))
|
if (!isset($methodAnnotations['ApiSummary'])) {
|
||||||
{
|
|
||||||
$methodAnnotations['ApiSummary'] = [$methodTitle];
|
$methodAnnotations['ApiSummary'] = [$methodTitle];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($methodAnnotations)
|
if ($methodAnnotations) {
|
||||||
{
|
foreach ($classAnnotations as $name => $valueClass) {
|
||||||
foreach ($classAnnotations as $name => $valueClass)
|
if (count($valueClass) !== 1) {
|
||||||
{
|
|
||||||
if (count($valueClass) !== 1)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($name === 'ApiRoute')
|
if ($name === 'ApiRoute') {
|
||||||
{
|
if (isset($methodAnnotations[$name])) {
|
||||||
if (isset($methodAnnotations[$name]))
|
|
||||||
{
|
|
||||||
$methodAnnotations[$name] = [rtrim($valueClass[0], '/') . $methodAnnotations[$name][0]];
|
$methodAnnotations[$name] = [rtrim($valueClass[0], '/') . $methodAnnotations[$name][0]];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$methodAnnotations[$name] = [rtrim($valueClass[0], '/') . '/' . $method->getName()];
|
$methodAnnotations[$name] = [rtrim($valueClass[0], '/') . '/' . $method->getName()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($name === 'ApiSector')
|
if ($name === 'ApiSector') {
|
||||||
{
|
|
||||||
$methodAnnotations[$name] = $valueClass;
|
$methodAnnotations[$name] = $valueClass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isset($methodAnnotations['ApiTitle']))
|
if (!isset($methodAnnotations['ApiTitle'])) {
|
||||||
{
|
|
||||||
$methodAnnotations['ApiTitle'] = [$methodTitle];
|
$methodAnnotations['ApiTitle'] = [$methodTitle];
|
||||||
}
|
}
|
||||||
if (!isset($methodAnnotations['ApiRoute']))
|
if (!isset($methodAnnotations['ApiRoute'])) {
|
||||||
{
|
|
||||||
$urlArr = [];
|
$urlArr = [];
|
||||||
$className = $class->getName();
|
$className = $class->getName();
|
||||||
|
|
||||||
list($prefix, $suffix) = explode('\\' . \think\Config::get('url_controller_layer') . '\\', $className);
|
list($prefix, $suffix) = explode('\\' . \think\Config::get('url_controller_layer') . '\\', $className);
|
||||||
$prefixArr = explode('\\', $prefix);
|
$prefixArr = explode('\\', $prefix);
|
||||||
$suffixArr = explode('\\', $suffix);
|
$suffixArr = explode('\\', $suffix);
|
||||||
if ($prefixArr[0] == \think\Config::get('app_namespace'))
|
if ($prefixArr[0] == \think\Config::get('app_namespace')) {
|
||||||
{
|
|
||||||
$prefixArr[0] = '';
|
$prefixArr[0] = '';
|
||||||
}
|
}
|
||||||
$urlArr = array_merge($urlArr, $prefixArr);
|
$urlArr = array_merge($urlArr, $prefixArr);
|
||||||
$urlArr[] = implode('.', array_map(function($item) {
|
$urlArr[] = implode('.', array_map(function ($item) {
|
||||||
return \think\Loader::parseName($item);
|
return \think\Loader::parseName($item);
|
||||||
}, $suffixArr));
|
}, $suffixArr));
|
||||||
$urlArr[] = $method->getName();
|
$urlArr[] = $method->getName();
|
||||||
$methodAnnotations['ApiRoute'] = [implode('/', $urlArr)];
|
$methodAnnotations['ApiRoute'] = [implode('/', $urlArr)];
|
||||||
}
|
}
|
||||||
if (!isset($methodAnnotations['ApiSector']))
|
if (!isset($methodAnnotations['ApiSector'])) {
|
||||||
{
|
|
||||||
$methodAnnotations['ApiSector'] = isset($classAnnotations['ApiSector']) ? $classAnnotations['ApiSector'] : [$classTitle];
|
$methodAnnotations['ApiSector'] = isset($classAnnotations['ApiSector']) ? $classAnnotations['ApiSector'] : [$classTitle];
|
||||||
}
|
}
|
||||||
if (!isset($methodAnnotations['ApiParams']))
|
if (!isset($methodAnnotations['ApiParams'])) {
|
||||||
{
|
|
||||||
$params = self::parseCustomAnnotations($docblockMethod, 'param');
|
$params = self::parseCustomAnnotations($docblockMethod, 'param');
|
||||||
foreach ($params as $k => $v)
|
foreach ($params as $k => $v) {
|
||||||
{
|
|
||||||
$arr = explode(' ', preg_replace("/[\s]+/", " ", $v));
|
$arr = explode(' ', preg_replace("/[\s]+/", " ", $v));
|
||||||
$methodAnnotations['ApiParams'][] = [
|
$methodAnnotations['ApiParams'][] = [
|
||||||
'name' => isset($arr[1]) ? str_replace('$', '', $arr[1]) : '',
|
'name' => isset($arr[1]) ? str_replace('$', '', $arr[1]) : '',
|
||||||
|
|
@ -299,10 +262,8 @@ class Extractor
|
||||||
$annotations = array();
|
$annotations = array();
|
||||||
|
|
||||||
$docblock = substr($docblock, 3, -2);
|
$docblock = substr($docblock, 3, -2);
|
||||||
if (preg_match_all('/@' . $name . '(?:\s*(?:\(\s*)?(.*?)(?:\s*\))?)??\s*(?:\n|\*\/)/', $docblock, $matches))
|
if (preg_match_all('/@' . $name . '(?:\s*(?:\(\s*)?(.*?)(?:\s*\))?)??\s*(?:\n|\*\/)/', $docblock, $matches)) {
|
||||||
{
|
foreach ($matches[1] as $k => $v) {
|
||||||
foreach ($matches[1] as $k => $v)
|
|
||||||
{
|
|
||||||
$annotations[] = $v;
|
$annotations[] = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -321,36 +282,31 @@ class Extractor
|
||||||
|
|
||||||
// Strip away the docblock header and footer to ease parsing of one line annotations
|
// Strip away the docblock header and footer to ease parsing of one line annotations
|
||||||
$docblock = substr($docblock, 3, -2);
|
$docblock = substr($docblock, 3, -2);
|
||||||
if (preg_match_all('/@(?<name>[A-Za-z_-]+)[\s\t]*\((?<args>(?:(?!\)).)*)\)\r?/s', $docblock, $matches))
|
if (preg_match_all('/@(?<name>[A-Za-z_-]+)[\s\t]*\((?<args>(?:(?!\)).)*)\)\r?/s', $docblock, $matches)) {
|
||||||
{
|
|
||||||
$numMatches = count($matches[0]);
|
$numMatches = count($matches[0]);
|
||||||
for ($i = 0; $i < $numMatches; ++$i)
|
for ($i = 0; $i < $numMatches; ++$i) {
|
||||||
{
|
$name = $matches['name'][$i];
|
||||||
|
$value = '';
|
||||||
// annotations has arguments
|
// annotations has arguments
|
||||||
if (isset($matches['args'][$i]))
|
if (isset($matches['args'][$i])) {
|
||||||
{
|
|
||||||
$argsParts = trim($matches['args'][$i]);
|
$argsParts = trim($matches['args'][$i]);
|
||||||
$name = $matches['name'][$i];
|
if ($name == 'ApiReturn') {
|
||||||
if($name == 'ApiReturn')
|
|
||||||
{
|
|
||||||
$value = $argsParts;
|
$value = $argsParts;
|
||||||
} else {
|
} else if ($matches['args'][$i] != '') {
|
||||||
$argsParts = preg_replace("/\{(\w+)\}/", '#$1#', $argsParts);
|
$argsParts = preg_replace("/\{(\w+)\}/", '#$1#', $argsParts);
|
||||||
$value = self::parseArgs($argsParts);
|
$value = self::parseArgs($argsParts);
|
||||||
if(is_string($value))
|
if (is_string($value)) {
|
||||||
{
|
|
||||||
$value = preg_replace("/\#(\w+)\#/", '{$1}', $argsParts);
|
$value = preg_replace("/\#(\w+)\#/", '{$1}', $argsParts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
$value = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$annotations[$name][] = $value;
|
$annotations[$name][] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (stripos($docblock, '@ApiInternal') !== false) {
|
||||||
|
$annotations['ApiInternal'] = [true];
|
||||||
|
}
|
||||||
|
|
||||||
return $annotations;
|
return $annotations;
|
||||||
}
|
}
|
||||||
|
|
@ -382,39 +338,31 @@ class Extractor
|
||||||
$quoted = false;
|
$quoted = false;
|
||||||
$tokens = array('"', '"', '{', '}', ',', '=');
|
$tokens = array('"', '"', '{', '}', ',', '=');
|
||||||
|
|
||||||
while ($i <= $len)
|
while ($i <= $len) {
|
||||||
{
|
|
||||||
$prev_c = substr($content, $i - 1, 1);
|
$prev_c = substr($content, $i - 1, 1);
|
||||||
$c = substr($content, $i++, 1);
|
$c = substr($content, $i++, 1);
|
||||||
|
|
||||||
if ($c === '"' && $prev_c !== "\\")
|
if ($c === '"' && $prev_c !== "\\") {
|
||||||
{
|
|
||||||
$delimiter = $c;
|
$delimiter = $c;
|
||||||
//open delimiter
|
//open delimiter
|
||||||
if (!$composing && empty($prevDelimiter) && empty($nextDelimiter))
|
if (!$composing && empty($prevDelimiter) && empty($nextDelimiter)) {
|
||||||
{
|
|
||||||
$prevDelimiter = $nextDelimiter = $delimiter;
|
$prevDelimiter = $nextDelimiter = $delimiter;
|
||||||
$val = '';
|
$val = '';
|
||||||
$composing = true;
|
$composing = true;
|
||||||
$quoted = true;
|
$quoted = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// close delimiter
|
// close delimiter
|
||||||
if ($c !== $nextDelimiter)
|
if ($c !== $nextDelimiter) {
|
||||||
{
|
|
||||||
throw new Exception(sprintf(
|
throw new Exception(sprintf(
|
||||||
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// validating syntax
|
// validating syntax
|
||||||
if ($i < $len)
|
if ($i < $len) {
|
||||||
{
|
if (',' !== substr($content, $i, 1) && '\\' !== $prev_c) {
|
||||||
if (',' !== substr($content, $i, 1) && '\\' !== $prev_c)
|
|
||||||
{
|
|
||||||
throw new Exception(sprintf(
|
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)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -423,11 +371,8 @@ class Extractor
|
||||||
$composing = false;
|
$composing = false;
|
||||||
$delimiter = null;
|
$delimiter = null;
|
||||||
}
|
}
|
||||||
}
|
} elseif (!$composing && in_array($c, $tokens)) {
|
||||||
elseif (!$composing && in_array($c, $tokens))
|
switch ($c) {
|
||||||
{
|
|
||||||
switch ($c)
|
|
||||||
{
|
|
||||||
case '=':
|
case '=':
|
||||||
$prevDelimiter = $nextDelimiter = '';
|
$prevDelimiter = $nextDelimiter = '';
|
||||||
$level = 2;
|
$level = 2;
|
||||||
|
|
@ -440,10 +385,9 @@ class Extractor
|
||||||
|
|
||||||
// If composing flag is true yet,
|
// If composing flag is true yet,
|
||||||
// it means that the string was not enclosed, so it is parsing error.
|
// it means that the string was not enclosed, so it is parsing error.
|
||||||
if ($composing === true && !empty($prevDelimiter) && !empty($nextDelimiter))
|
if ($composing === true && !empty($prevDelimiter) && !empty($nextDelimiter)) {
|
||||||
{
|
|
||||||
throw new Exception(sprintf(
|
throw new Exception(sprintf(
|
||||||
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -453,19 +397,16 @@ class Extractor
|
||||||
$subc = '';
|
$subc = '';
|
||||||
$subComposing = true;
|
$subComposing = true;
|
||||||
|
|
||||||
while ($i <= $len)
|
while ($i <= $len) {
|
||||||
{
|
|
||||||
$c = substr($content, $i++, 1);
|
$c = substr($content, $i++, 1);
|
||||||
|
|
||||||
if (isset($delimiter) && $c === $delimiter)
|
if (isset($delimiter) && $c === $delimiter) {
|
||||||
{
|
|
||||||
throw new Exception(sprintf(
|
throw new Exception(sprintf(
|
||||||
"Parse Error: Composite variable is not enclosed correctly."
|
"Parse Error: Composite variable is not enclosed correctly."
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($c === '}')
|
if ($c === '}') {
|
||||||
{
|
|
||||||
$subComposing = false;
|
$subComposing = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -473,37 +414,27 @@ class Extractor
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the string is composing yet means that the structure of var. never was enclosed with '}'
|
// if the string is composing yet means that the structure of var. never was enclosed with '}'
|
||||||
if ($subComposing)
|
if ($subComposing) {
|
||||||
{
|
|
||||||
throw new Exception(sprintf(
|
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
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$val = self::parseArgs($subc);
|
$val = self::parseArgs($subc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if ($level == 1) {
|
||||||
{
|
|
||||||
if ($level == 1)
|
|
||||||
{
|
|
||||||
$var .= $c;
|
$var .= $c;
|
||||||
}
|
} elseif ($level == 2) {
|
||||||
elseif ($level == 2)
|
|
||||||
{
|
|
||||||
$val .= $c;
|
$val .= $c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($level === 3 || $i === $len)
|
if ($level === 3 || $i === $len) {
|
||||||
{
|
if ($type == 'plain' && $i === $len) {
|
||||||
if ($type == 'plain' && $i === $len)
|
|
||||||
{
|
|
||||||
$data = self::castValue($var);
|
$data = self::castValue($var);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
$data[trim($var)] = self::castValue($val, !$quoted);
|
$data[trim($var)] = self::castValue($val, !$quoted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,34 +451,26 @@ class Extractor
|
||||||
/**
|
/**
|
||||||
* Try determinate the original type variable of a string
|
* Try determinate the original type variable of a string
|
||||||
*
|
*
|
||||||
* @param string $val string containing possibles variables that can be cast to bool or int
|
* @param string $val string containing possibles variables that can be cast to bool or int
|
||||||
* @param boolean $trim indicate if the value passed should be trimmed after to try cast
|
* @param boolean $trim indicate if the value passed should be trimmed after to try cast
|
||||||
* @return mixed returns the value converted to original type if was possible
|
* @return mixed returns the value converted to original type if was possible
|
||||||
*/
|
*/
|
||||||
private static function castValue($val, $trim = false)
|
private static function castValue($val, $trim = false)
|
||||||
{
|
{
|
||||||
if (is_array($val))
|
if (is_array($val)) {
|
||||||
{
|
foreach ($val as $key => $value) {
|
||||||
foreach ($val as $key => $value)
|
|
||||||
{
|
|
||||||
$val[$key] = self::castValue($value);
|
$val[$key] = self::castValue($value);
|
||||||
}
|
}
|
||||||
}
|
} elseif (is_string($val)) {
|
||||||
elseif (is_string($val))
|
if ($trim) {
|
||||||
{
|
|
||||||
if ($trim)
|
|
||||||
{
|
|
||||||
$val = trim($val);
|
$val = trim($val);
|
||||||
}
|
}
|
||||||
$val = stripslashes($val);
|
$val = stripslashes($val);
|
||||||
$tmp = strtolower($val);
|
$tmp = strtolower($val);
|
||||||
|
|
||||||
if ($tmp === 'false' || $tmp === 'true')
|
if ($tmp === 'false' || $tmp === 'true') {
|
||||||
{
|
|
||||||
$val = $tmp === 'true';
|
$val = $tmp === 'true';
|
||||||
}
|
} elseif (is_numeric($val)) {
|
||||||
elseif (is_numeric($val))
|
|
||||||
{
|
|
||||||
return $val + 0;
|
return $val + 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
<meta name="author" content="{$config.author}">
|
<meta name="author" content="{$config.author}">
|
||||||
<title>{$config.title}</title>
|
<title>{$config.title}</title>
|
||||||
<link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.bootcss.com/font-awesome/4.6.2/css/font-awesome.min.css" rel="stylesheet">
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
padding-top: 70px; margin-bottom: 15px;
|
padding-top: 70px; margin-bottom: 15px;
|
||||||
|
|
@ -28,6 +29,59 @@
|
||||||
.null { color: magenta; }
|
.null { color: magenta; }
|
||||||
.key { color: red; }
|
.key { color: red; }
|
||||||
.popover { max-width: 400px; max-height: 400px; overflow-y: auto;}
|
.popover { max-width: 400px; max-height: 400px; overflow-y: auto;}
|
||||||
|
.list-group.panel > .list-group-item {
|
||||||
|
}
|
||||||
|
.list-group-item:last-child {
|
||||||
|
border-radius:0;
|
||||||
|
}
|
||||||
|
h4.panel-title a {
|
||||||
|
font-weight:normal;
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
h4.panel-title a .text-muted {
|
||||||
|
font-size:12px;
|
||||||
|
font-weight:normal;
|
||||||
|
font-family: 'Verdana';
|
||||||
|
}
|
||||||
|
#sidebar {
|
||||||
|
width: 220px;
|
||||||
|
position: fixed;
|
||||||
|
margin-left: -240px;
|
||||||
|
overflow-y:auto;
|
||||||
|
}
|
||||||
|
#sidebar > .list-group {
|
||||||
|
margin-bottom:0;
|
||||||
|
}
|
||||||
|
#sidebar > .list-group > a{
|
||||||
|
text-indent:0;
|
||||||
|
}
|
||||||
|
#sidebar .child {
|
||||||
|
border:1px solid #ddd;
|
||||||
|
border-bottom:none;
|
||||||
|
}
|
||||||
|
#sidebar .child > a {
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
#sidebar .list-group a.current {
|
||||||
|
background:#f5f5f5;
|
||||||
|
}
|
||||||
|
@media (max-width: 1620px){
|
||||||
|
#sidebar {
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
#accordion {
|
||||||
|
padding-left:235px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 768px){
|
||||||
|
#sidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#accordion {
|
||||||
|
padding-left:0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -68,15 +122,29 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<!-- menu -->
|
||||||
|
<div id="sidebar">
|
||||||
|
<div class="list-group panel">
|
||||||
|
{foreach name="docslist" id="docs"}
|
||||||
|
<a href="#{$key}" class="list-group-item" data-toggle="collapse" data-parent="#sidebar">{$key} <i class="fa fa-caret-down"></i></a>
|
||||||
|
<div class="child collapse" id="{$key}">
|
||||||
|
{foreach name="docs" id="api" }
|
||||||
|
<a href="javascript:;" data-id="{$api.id}" class="list-group-item">{$api.title}</a>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="panel-group" id="accordion">
|
<div class="panel-group" id="accordion">
|
||||||
{foreach name="docslist" id="docs"}
|
{foreach name="docslist" id="docs"}
|
||||||
<h2>{$key}</h2>
|
<h2>{$key}</h2>
|
||||||
<hr>
|
<hr>
|
||||||
{foreach name="docs" id="api" }
|
{foreach name="docs" id="api" }
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading" id="heading-{$api.id}">
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<span class="label {$api.method_label}">{$api.method|strtoupper}</span> <a data-toggle="collapse" data-parent="#accordion{$api.id}" href="#collapseOne{$api.id}"> {$api.route}</a>
|
<span class="label {$api.method_label}">{$api.method|strtoupper}</span>
|
||||||
|
<a data-toggle="collapse" data-parent="#accordion{$api.id}" href="#collapseOne{$api.id}"> {$api.title} <span class="text-muted">{$api.route}</span></a>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapseOne{$api.id}" class="panel-collapse collapse">
|
<div id="collapseOne{$api.id}" class="panel-collapse collapse">
|
||||||
|
|
@ -198,6 +266,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-success send" rel="{$api.id}">{$lang.Send}</button>
|
<button type="submit" class="btn btn-success send" rel="{$api.id}">{$lang.Send}</button>
|
||||||
|
<button type="reset" class="btn btn-info" rel="{$api.id}">{$lang.Reset}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -349,6 +418,24 @@
|
||||||
placement: 'bottom'
|
placement: 'bottom'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(window).on("resize", function(){
|
||||||
|
$("#sidebar").css("max-height", $(window).height()-80);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(window).trigger("resize");
|
||||||
|
|
||||||
|
$(document).on("click", "#sidebar .list-group > .list-group-item", function(){
|
||||||
|
$("#sidebar .list-group > .list-group-item").removeClass("current");
|
||||||
|
$(this).addClass("current");
|
||||||
|
});
|
||||||
|
$(document).on("click", "#sidebar .child a", function(){
|
||||||
|
var heading = $("#heading-"+$(this).data("id"));
|
||||||
|
if(!heading.next().hasClass("in")){
|
||||||
|
$("a", heading).trigger("click");
|
||||||
|
}
|
||||||
|
$("html,body").animate({scrollTop:heading.offset().top-70});
|
||||||
|
});
|
||||||
|
|
||||||
$('code[id^=response]').hide();
|
$('code[id^=response]').hide();
|
||||||
|
|
||||||
$.each($('pre[id^=sample_response],pre[id^=sample_post_body]'), function () {
|
$.each($('pre[id^=sample_response],pre[id^=sample_post_body]'), function () {
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,12 @@ class Crud extends Command
|
||||||
*/
|
*/
|
||||||
protected $sortField = 'weigh';
|
protected $sortField = 'weigh';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 筛选字段
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $headingFilterField = 'status';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑器的Class
|
* 编辑器的Class
|
||||||
*/
|
*/
|
||||||
|
|
@ -138,6 +144,7 @@ class Crud extends Command
|
||||||
->addOption('selectpagessuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate multiple selectpage component with suffix', null)
|
->addOption('selectpagessuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate multiple selectpage component with suffix', null)
|
||||||
->addOption('ignorefields', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'ignore fields', null)
|
->addOption('ignorefields', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'ignore fields', null)
|
||||||
->addOption('sortfield', null, Option::VALUE_OPTIONAL, 'sort field', null)
|
->addOption('sortfield', null, Option::VALUE_OPTIONAL, 'sort field', null)
|
||||||
|
->addOption('headingfilterfield', null, Option::VALUE_OPTIONAL, 'heading filter field', null)
|
||||||
->addOption('editorclass', null, Option::VALUE_OPTIONAL, 'automatically generate editor class', null)
|
->addOption('editorclass', null, Option::VALUE_OPTIONAL, 'automatically generate editor class', null)
|
||||||
->setDescription('Build CRUD controller and model from table');
|
->setDescription('Build CRUD controller and model from table');
|
||||||
}
|
}
|
||||||
|
|
@ -198,6 +205,8 @@ class Crud extends Command
|
||||||
$ignoreFields = $input->getOption('ignorefields');
|
$ignoreFields = $input->getOption('ignorefields');
|
||||||
//排序字段
|
//排序字段
|
||||||
$sortfield = $input->getOption('sortfield');
|
$sortfield = $input->getOption('sortfield');
|
||||||
|
//顶部筛选过滤字段
|
||||||
|
$headingfilterfield = $input->getOption('headingfilterfield');
|
||||||
//编辑器Class
|
//编辑器Class
|
||||||
$editorclass = $input->getOption('editorclass');
|
$editorclass = $input->getOption('editorclass');
|
||||||
if ($setcheckboxsuffix)
|
if ($setcheckboxsuffix)
|
||||||
|
|
@ -224,6 +233,8 @@ class Crud extends Command
|
||||||
$this->editorClass = $editorclass;
|
$this->editorClass = $editorclass;
|
||||||
if ($sortfield)
|
if ($sortfield)
|
||||||
$this->sortField = $sortfield;
|
$this->sortField = $sortfield;
|
||||||
|
if ($headingfilterfield)
|
||||||
|
$this->headingFilterField = $headingfilterfield;
|
||||||
|
|
||||||
$dbname = Config::get('database.database');
|
$dbname = Config::get('database.database');
|
||||||
$prefix = Config::get('database.prefix');
|
$prefix = Config::get('database.prefix');
|
||||||
|
|
@ -466,6 +477,8 @@ class Crud extends Command
|
||||||
$getEnumArr = [];
|
$getEnumArr = [];
|
||||||
$appendAttrList = [];
|
$appendAttrList = [];
|
||||||
$controllerAssignList = [];
|
$controllerAssignList = [];
|
||||||
|
$headingHtml = '{:build_heading()}';
|
||||||
|
$headingJs = '';
|
||||||
|
|
||||||
//循环所有字段,开始构造视图的HTML和JS信息
|
//循环所有字段,开始构造视图的HTML和JS信息
|
||||||
foreach ($columnList as $k => $v) {
|
foreach ($columnList as $k => $v) {
|
||||||
|
|
@ -681,6 +694,10 @@ class Crud extends Command
|
||||||
//构造JS列信息
|
//构造JS列信息
|
||||||
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr);
|
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr);
|
||||||
}
|
}
|
||||||
|
if ($this->headingFilterField && $this->headingFilterField == $field && $itemArr) {
|
||||||
|
$headingHtml = $this->getReplacedStub('html/heading-html', ['field' => $field]);
|
||||||
|
$headingJs = $this->getReplacedStub('html/heading-js', ['field' => $field]);
|
||||||
|
}
|
||||||
//排序方式,如果有指定排序字段,否则按主键排序
|
//排序方式,如果有指定排序字段,否则按主键排序
|
||||||
$order = $field == $this->sortField ? $this->sortField : $order;
|
$order = $field == $this->sortField ? $this->sortField : $order;
|
||||||
}
|
}
|
||||||
|
|
@ -724,6 +741,7 @@ class Crud extends Command
|
||||||
$modelInit = $this->getReplacedStub('mixins' . DS . 'modelinit', ['order' => $order]);
|
$modelInit = $this->getReplacedStub('mixins' . DS . 'modelinit', ['order' => $order]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'controllerNamespace' => $controllerNamespace,
|
'controllerNamespace' => $controllerNamespace,
|
||||||
'modelNamespace' => $modelNamespace,
|
'modelNamespace' => $modelNamespace,
|
||||||
|
|
@ -753,6 +771,8 @@ class Crud extends Command
|
||||||
'relationWithList' => '',
|
'relationWithList' => '',
|
||||||
'relationMethodList' => '',
|
'relationMethodList' => '',
|
||||||
'controllerIndex' => '',
|
'controllerIndex' => '',
|
||||||
|
'headingHtml' => $headingHtml,
|
||||||
|
'headingJs' => $headingJs,
|
||||||
'visibleFieldList' => $fields ? "\$row->visible(['" . implode("','", array_filter(explode(',', $fields))) . "']);" : '',
|
'visibleFieldList' => $fields ? "\$row->visible(['" . implode("','", array_filter(explode(',', $fields))) . "']);" : '',
|
||||||
'appendAttrList' => implode(",\n", $appendAttrList),
|
'appendAttrList' => implode(",\n", $appendAttrList),
|
||||||
'getEnumList' => implode("\n\n", $getEnumArr),
|
'getEnumList' => implode("\n\n", $getEnumArr),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
<div class="panel-heading">
|
||||||
|
{:build_heading(null,FALSE)}
|
||||||
|
<ul class="nav nav-tabs" data-field="{%field%}">
|
||||||
|
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
|
||||||
|
{foreach name="{%field%}List" item="vo"}
|
||||||
|
<li><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
|
||||||
|
{/foreach}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
// 绑定TAB事件
|
||||||
|
$('.panel-heading a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||||
|
var field = $(this).closest("ul").data("field");
|
||||||
|
var value = $(this).data("value");
|
||||||
|
var options = table.bootstrapTable('getOptions');
|
||||||
|
options.pageNumber = 1;
|
||||||
|
options.queryParams = function (params) {
|
||||||
|
var filter = {};
|
||||||
|
if (value !== '') {
|
||||||
|
filter[field] = value;
|
||||||
|
}
|
||||||
|
params.filter = JSON.stringify(filter);
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
table.bootstrapTable('refresh', {});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="panel panel-default panel-intro">
|
<div class="panel panel-default panel-intro">
|
||||||
{:build_heading()}
|
{%headingHtml%}
|
||||||
|
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<div id="myTabContent" class="tab-content">
|
<div id="myTabContent" class="tab-content">
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{%headingJs%}
|
||||||
|
|
||||||
// 为表格绑定事件
|
// 为表格绑定事件
|
||||||
Table.api.bindevent(table);
|
Table.api.bindevent(table);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
public function {%methodName%}($value, $data)
|
public function {%methodName%}($value, $data)
|
||||||
{
|
{
|
||||||
$value = $value ? $value : $data['{%field%}'];
|
$value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : '');
|
||||||
$valueArr = explode(',', $value);
|
$valueArr = explode(',', $value);
|
||||||
$list = $this->{%listMethodName%}();
|
$list = $this->{%listMethodName%}();
|
||||||
return implode(',', array_intersect_key($list, array_flip($valueArr)));
|
return implode(',', array_intersect_key($list, array_flip($valueArr)));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
public function {%methodName%}($value, $data)
|
public function {%methodName%}($value, $data)
|
||||||
{
|
{
|
||||||
$value = $value ? $value : $data['{%field%}'];
|
$value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : '');
|
||||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
public function {%methodName%}($value, $data)
|
public function {%methodName%}($value, $data)
|
||||||
{
|
{
|
||||||
$value = $value ? $value : $data['{%field%}'];
|
$value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : '');
|
||||||
$valueArr = explode(',', $value);
|
$valueArr = explode(',', $value);
|
||||||
$list = $this->{%listMethodName%}();
|
$list = $this->{%listMethodName%}();
|
||||||
return implode(',', array_intersect_key($list, array_flip($valueArr)));
|
return implode(',', array_intersect_key($list, array_flip($valueArr)));
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
public function {%methodName%}($value, $data)
|
public function {%methodName%}($value, $data)
|
||||||
{
|
{
|
||||||
$value = $value ? $value : $data['{%field%}'];
|
$value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : '');
|
||||||
$list = $this->{%listMethodName%}();
|
$list = $this->{%listMethodName%}();
|
||||||
return isset($list[$value]) ? $list[$value] : '';
|
return isset($list[$value]) ? $list[$value] : '';
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
public function {%methodName%}($value, $data)
|
public function {%methodName%}($value, $data)
|
||||||
{
|
{
|
||||||
$value = $value ? $value : $data['{%field%}'];
|
$value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : '');
|
||||||
$list = $this->{%listMethodName%}();
|
$list = $this->{%listMethodName%}();
|
||||||
return isset($list[$value]) ? $list[$value] : '';
|
return isset($list[$value]) ? $list[$value] : '';
|
||||||
}
|
}
|
||||||
|
|
@ -165,44 +165,30 @@ class Ajax extends Backend
|
||||||
$ids = array_values(array_intersect($ids, $hasids));
|
$ids = array_values(array_intersect($ids, $hasids));
|
||||||
}
|
}
|
||||||
|
|
||||||
//直接修复排序
|
$list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select();
|
||||||
$one = Db::name($table)->field("{$field},COUNT(*) AS nums")->group($field)->having('nums > 1')->find();
|
foreach ($list as $k => $v) {
|
||||||
if ($one) {
|
$sour[] = $v[$prikey];
|
||||||
$list = Db::name($table)->field("$prikey,$field")->order($field, $orderway)->select();
|
$weighdata[$v[$prikey]] = $v[$field];
|
||||||
foreach ($list as $k => $v) {
|
|
||||||
Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]);
|
|
||||||
}
|
|
||||||
$this->success();
|
|
||||||
} else {
|
|
||||||
$list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select();
|
|
||||||
foreach ($list as $k => $v) {
|
|
||||||
$sour[] = $v[$prikey];
|
|
||||||
$weighdata[$v[$prikey]] = $v[$field];
|
|
||||||
}
|
|
||||||
$position = array_search($changeid, $ids);
|
|
||||||
$desc_id = $sour[$position]; //移动到目标的ID值,取出所处改变前位置的值
|
|
||||||
$sour_id = $changeid;
|
|
||||||
$desc_value = $weighdata[$desc_id];
|
|
||||||
$sour_value = $weighdata[$sour_id];
|
|
||||||
//echo "移动的ID:{$sour_id}\n";
|
|
||||||
//echo "替换的ID:{$desc_id}\n";
|
|
||||||
$weighids = array();
|
|
||||||
$temp = array_values(array_diff_assoc($ids, $sour));
|
|
||||||
foreach ($temp as $m => $n) {
|
|
||||||
if ($n == $sour_id) {
|
|
||||||
$offset = $desc_id;
|
|
||||||
} else {
|
|
||||||
if ($sour_id == $temp[0]) {
|
|
||||||
$offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id;
|
|
||||||
} else {
|
|
||||||
$offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$weighids[$n] = $weighdata[$offset];
|
|
||||||
Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]);
|
|
||||||
}
|
|
||||||
$this->success();
|
|
||||||
}
|
}
|
||||||
|
$position = array_search($changeid, $ids);
|
||||||
|
$desc_id = $sour[$position]; //移动到目标的ID值,取出所处改变前位置的值
|
||||||
|
$sour_id = $changeid;
|
||||||
|
$weighids = array();
|
||||||
|
$temp = array_values(array_diff_assoc($ids, $sour));
|
||||||
|
foreach ($temp as $m => $n) {
|
||||||
|
if ($n == $sour_id) {
|
||||||
|
$offset = $desc_id;
|
||||||
|
} else {
|
||||||
|
if ($sour_id == $temp[0]) {
|
||||||
|
$offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id;
|
||||||
|
} else {
|
||||||
|
$offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$weighids[$n] = $weighdata[$offset];
|
||||||
|
Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]);
|
||||||
|
}
|
||||||
|
$this->success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ use fast\Tree;
|
||||||
class Category extends Backend
|
class Category extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\common\model\Category
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
protected $categorylist = [];
|
protected $categorylist = [];
|
||||||
protected $noNeedRight = ['selectpage'];
|
protected $noNeedRight = ['selectpage'];
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class Index extends Backend
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
//左侧菜单
|
//左侧菜单
|
||||||
list($menulist, $navlist) = $this->auth->getSidebar([
|
list($menulist, $navlist, $fixedmenu, $referermenu) = $this->auth->getSidebar([
|
||||||
'dashboard' => 'hot',
|
'dashboard' => 'hot',
|
||||||
'addon' => ['new', 'red', 'badge'],
|
'addon' => ['new', 'red', 'badge'],
|
||||||
'auth/rule' => __('Menu'),
|
'auth/rule' => __('Menu'),
|
||||||
|
|
@ -44,6 +44,8 @@ class Index extends Backend
|
||||||
}
|
}
|
||||||
$this->view->assign('menulist', $menulist);
|
$this->view->assign('menulist', $menulist);
|
||||||
$this->view->assign('navlist', $navlist);
|
$this->view->assign('navlist', $navlist);
|
||||||
|
$this->view->assign('fixedmenu', $fixedmenu);
|
||||||
|
$this->view->assign('referermenu', $referermenu);
|
||||||
$this->view->assign('title', __('Home'));
|
$this->view->assign('title', __('Home'));
|
||||||
return $this->view->fetch();
|
return $this->view->fetch();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ use fast\Tree;
|
||||||
class Admin extends Backend
|
class Admin extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\admin\model\Admin
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
protected $childrenGroupIds = [];
|
protected $childrenGroupIds = [];
|
||||||
protected $childrenAdminIds = [];
|
protected $childrenAdminIds = [];
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ use app\common\controller\Backend;
|
||||||
class Adminlog extends Backend
|
class Adminlog extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\admin\model\AdminLog
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
protected $childrenGroupIds = [];
|
protected $childrenGroupIds = [];
|
||||||
protected $childrenAdminIds = [];
|
protected $childrenAdminIds = [];
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ use fast\Tree;
|
||||||
class Group extends Backend
|
class Group extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\admin\model\AuthGroup
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
//当前登录管理员所有子组别
|
//当前登录管理员所有子组别
|
||||||
protected $childrenGroupIds = [];
|
protected $childrenGroupIds = [];
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ use think\Cache;
|
||||||
class Rule extends Backend
|
class Rule extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\admin\model\AuthRule
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
protected $rulelist = [];
|
protected $rulelist = [];
|
||||||
protected $multiFields = 'ismenu,status';
|
protected $multiFields = 'ismenu,status';
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ use app\common\controller\Backend;
|
||||||
class Attachment extends Backend
|
class Attachment extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\common\model\Attachment
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
|
|
||||||
public function _initialize()
|
public function _initialize()
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ use think\Exception;
|
||||||
class Config extends Backend
|
class Config extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \app\common\model\Config
|
||||||
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
protected $noNeedRight = ['check'];
|
protected $noNeedRight = ['check'];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class Group extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserGroup模型对象
|
* @var \app\admin\model\UserGroup
|
||||||
*/
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@ use fast\Tree;
|
||||||
class Rule extends Backend
|
class Rule extends Backend
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserRule模型对象
|
* @var \app\admin\model\UserRule
|
||||||
*/
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
protected $rulelist = [];
|
protected $rulelist = [];
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,9 @@ class User extends Backend
|
||||||
|
|
||||||
protected $relationSearch = true;
|
protected $relationSearch = true;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User模型对象
|
* @var \app\admin\model\User
|
||||||
*/
|
*/
|
||||||
protected $model = null;
|
protected $model = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ return [
|
||||||
'Del' => '删除',
|
'Del' => '删除',
|
||||||
'Delete' => '删除',
|
'Delete' => '删除',
|
||||||
'Import' => '导入',
|
'Import' => '导入',
|
||||||
|
'Export' => '导出',
|
||||||
|
'All' => '全部',
|
||||||
'Detail' => '详情',
|
'Detail' => '详情',
|
||||||
'Multi' => '批量更新',
|
'Multi' => '批量更新',
|
||||||
'Setting' => '配置',
|
'Setting' => '配置',
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,8 @@ class Auth extends \fast\Auth
|
||||||
|
|
||||||
// 读取管理员当前拥有的权限节点
|
// 读取管理员当前拥有的权限节点
|
||||||
$userRule = $this->getRuleList();
|
$userRule = $this->getRuleList();
|
||||||
$select_id = 0;
|
$selected = $referer = [];
|
||||||
|
$refererUrl = Session::get('referer');
|
||||||
$pinyin = new \Overtrue\Pinyin\Pinyin('Overtrue\Pinyin\MemoryFileDictLoader');
|
$pinyin = new \Overtrue\Pinyin\Pinyin('Overtrue\Pinyin\MemoryFileDictLoader');
|
||||||
// 必须将结果集转换为数组
|
// 必须将结果集转换为数组
|
||||||
$ruleList = collection(\app\admin\model\AuthRule::where('status', 'normal')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
|
$ruleList = collection(\app\admin\model\AuthRule::where('status', 'normal')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
|
||||||
|
|
@ -376,15 +377,20 @@ class Auth extends \fast\Auth
|
||||||
unset($ruleList[$k]);
|
unset($ruleList[$k]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$select_id = $v['name'] == $fixedPage ? $v['id'] : $select_id;
|
|
||||||
$v['icon'] = $v['icon'] . ' fa-fw';
|
$v['icon'] = $v['icon'] . ' fa-fw';
|
||||||
$v['url'] = '/' . $module . '/' . $v['name'];
|
$v['url'] = '/' . $module . '/' . $v['name'];
|
||||||
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
|
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
|
||||||
$v['py'] = $pinyin->abbr($v['title'], '');
|
$v['py'] = $pinyin->abbr($v['title'], '');
|
||||||
$v['pinyin'] = $pinyin->permalink($v['title'], '');
|
$v['pinyin'] = $pinyin->permalink($v['title'], '');
|
||||||
$v['title'] = __($v['title']);
|
$v['title'] = __($v['title']);
|
||||||
|
$selected = $v['name'] == $fixedPage ? $v : $selected;
|
||||||
|
$referer = $v['url'] == $refererUrl ? $v : $referer;
|
||||||
|
}
|
||||||
|
if ($selected == $referer) {
|
||||||
|
$referer = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$select_id = $selected ? $selected['id'] : 0;
|
||||||
$menu = $nav = '';
|
$menu = $nav = '';
|
||||||
if (Config::get('fastadmin.multiplenav')) {
|
if (Config::get('fastadmin.multiplenav')) {
|
||||||
$topList = [];
|
$topList = [];
|
||||||
|
|
@ -412,10 +418,16 @@ class Auth extends \fast\Auth
|
||||||
// 构造菜单数据
|
// 构造菜单数据
|
||||||
Tree::instance()->init($ruleList);
|
Tree::instance()->init($ruleList);
|
||||||
$menu = Tree::instance()->getTreeMenu(0, '<li class="@class"><a href="@url@addtabs" addtabs="@id" url="@url" py="@py" pinyin="@pinyin"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret @badge</span></a> @childlist</li>', $select_id, '', 'ul', 'class="treeview-menu"');
|
$menu = Tree::instance()->getTreeMenu(0, '<li class="@class"><a href="@url@addtabs" addtabs="@id" url="@url" py="@py" pinyin="@pinyin"><i class="@icon"></i> <span>@title</span> <span class="pull-right-container">@caret @badge</span></a> @childlist</li>', $select_id, '', 'ul', 'class="treeview-menu"');
|
||||||
|
if ($selected) {
|
||||||
|
$nav .= '<li role="presentation" id="tab_' . $selected['id'] . '" class="' . ($referer ? '' : 'active') . '"><a href="#con_' . $selected['id'] . '" node-id="' . $selected['id'] . '" aria-controls="' . $selected['id'] . '" role="tab" data-toggle="tab"><i class="' . $selected['icon'] . ' fa-fw"></i> <span>' . $selected['title'] . '</span> </a></li>';
|
||||||
|
}
|
||||||
|
if ($referer) {
|
||||||
|
$nav .= '<li role="presentation" id="tab_' . $referer['id'] . '" class="active"><a href="#con_' . $referer['id'] . '" node-id="' . $referer['id'] . '" aria-controls="' . $referer['id'] . '" role="tab" data-toggle="tab"><i class="' . $referer['icon'] . ' fa-fw"></i> <span>' . $referer['title'] . '</span> </a> <i class="close-tab fa fa-remove"></i></li>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return [$menu, $nav];
|
return [$menu, $nav, $selected, $referer];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,8 @@ trait Backend
|
||||||
}
|
}
|
||||||
} catch (\think\exception\PDOException $e) {
|
} catch (\think\exception\PDOException $e) {
|
||||||
$this->error($e->getMessage());
|
$this->error($e->getMessage());
|
||||||
|
} catch (\think\Exception $e) {
|
||||||
|
$this->error($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->error(__('Parameter %s can not be empty', ''));
|
$this->error(__('Parameter %s can not be empty', ''));
|
||||||
|
|
@ -131,6 +133,8 @@ trait Backend
|
||||||
}
|
}
|
||||||
} catch (\think\exception\PDOException $e) {
|
} catch (\think\exception\PDOException $e) {
|
||||||
$this->error($e->getMessage());
|
$this->error($e->getMessage());
|
||||||
|
} catch (\think\Exception $e) {
|
||||||
|
$this->error($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->error(__('Parameter %s can not be empty', ''));
|
$this->error(__('Parameter %s can not be empty', ''));
|
||||||
|
|
@ -322,6 +326,8 @@ trait Backend
|
||||||
$this->model->saveAll($insert);
|
$this->model->saveAll($insert);
|
||||||
} catch (\think\exception\PDOException $exception) {
|
} catch (\think\exception\PDOException $exception) {
|
||||||
$this->error($exception->getMessage());
|
$this->error($exception->getMessage());
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->error($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->success();
|
$this->success();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<div class="tab-pane fade active in" id="one">
|
<div class="tab-pane fade active in" id="one">
|
||||||
<div class="widget-body no-padding">
|
<div class="widget-body no-padding">
|
||||||
<div id="toolbar" class="toolbar">
|
<div id="toolbar" class="toolbar">
|
||||||
{:build_toolbar()}
|
{:build_toolbar('refresh,add,edit,del')}
|
||||||
<div class="dropdown btn-group {:$auth->check('category/multi')?'':'hide'}">
|
<div class="dropdown btn-group {:$auth->check('category/multi')?'':'hide'}">
|
||||||
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
||||||
<ul class="dropdown-menu text-left" role="menu">
|
<ul class="dropdown-menu text-left" role="menu">
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,12 @@
|
||||||
<!--第二级菜单,只有在multiplenav开启时才显示-->
|
<!--第二级菜单,只有在multiplenav开启时才显示-->
|
||||||
<div id="secondnav">
|
<div id="secondnav">
|
||||||
<ul class="nav nav-tabs nav-addtabs disable-top-badge" role="tablist">
|
<ul class="nav nav-tabs nav-addtabs disable-top-badge" role="tablist">
|
||||||
|
{if $fixedmenu}
|
||||||
|
<li role="presentation" id="tab_{$fixedmenu.id}" class="{:$referermenu?'':'active'}"><a href="#con_{$fixedmenu.id}" node-id="{$fixedmenu.id}" aria-controls="{$fixedmenu.id}" role="tab" data-toggle="tab"><i class="fa fa-dashboard fa-fw"></i> <span>{$fixedmenu.title}</span> <span class="pull-right-container"> </span></a></li>
|
||||||
|
{/if}
|
||||||
|
{if $referermenu}
|
||||||
|
<li role="presentation" id="tab_{$referermenu.id}" class="active"><a href="#con_{$referermenu.id}" node-id="{$referermenu.id}" aria-controls="{$referermenu.id}" role="tab" data-toggle="tab"><i class="fa fa-list fa-fw"></i> <span>{$referermenu.title}</span> <span class="pull-right-container"> </span></a> <i class="close-tab fa fa-remove"></i></li>
|
||||||
|
{/if}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{$config.language}">
|
<html lang="{$config.language}">
|
||||||
<head>
|
<head>
|
||||||
<!-- 加载部部样式及META信息 -->
|
<!-- 加载样式及META信息 -->
|
||||||
{include file="common/meta" /}
|
{include file="common/meta" /}
|
||||||
</head>
|
</head>
|
||||||
<body class="hold-transition skin-green sidebar-mini fixed {if $config.fastadmin.multiplenav}multiplenav{/if}" id="tabs">
|
<body class="hold-transition skin-green sidebar-mini fixed {if $config.fastadmin.multiplenav}multiplenav{/if}" id="tabs">
|
||||||
|
|
@ -19,7 +19,16 @@
|
||||||
|
|
||||||
<!-- 主体内容区域 -->
|
<!-- 主体内容区域 -->
|
||||||
<div class="content-wrapper tab-content tab-addtabs">
|
<div class="content-wrapper tab-content tab-addtabs">
|
||||||
|
{if $fixedmenu}
|
||||||
|
<div role="tabpanel" class="tab-pane {:$referermenu?'':'active'}" id="con_{$fixedmenu.id}">
|
||||||
|
<iframe src="{$fixedmenu.url}?addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{if $referermenu}
|
||||||
|
<div role="tabpanel" class="tab-pane active" id="con_{$referermenu.id}">
|
||||||
|
<iframe src="{$referermenu.url}?addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 底部链接,默认隐藏 -->
|
<!-- 底部链接,默认隐藏 -->
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="tab-pane fade active in" id="one">
|
<div class="tab-pane fade active in" id="one">
|
||||||
<div class="widget-body no-padding">
|
<div class="widget-body no-padding">
|
||||||
<div id="toolbar" class="toolbar">
|
<div id="toolbar" class="toolbar">
|
||||||
{:build_toolbar()}
|
{:build_toolbar('refresh,add,edit,del')}
|
||||||
<div class="dropdown btn-group {:$auth->check('user/group/multi')?'':'hide'}">
|
<div class="dropdown btn-group {:$auth->check('user/group/multi')?'':'hide'}">
|
||||||
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
||||||
<ul class="dropdown-menu text-left" role="menu">
|
<ul class="dropdown-menu text-left" role="menu">
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,37 @@ class Demo extends Api
|
||||||
//如果接口已经设置无需登录,那也就无需鉴权了
|
//如果接口已经设置无需登录,那也就无需鉴权了
|
||||||
//
|
//
|
||||||
// 无需登录的接口,*表示全部
|
// 无需登录的接口,*表示全部
|
||||||
protected $noNeedLogin = ['test1'];
|
protected $noNeedLogin = ['test', 'test1'];
|
||||||
// 无需鉴权的接口,*表示全部
|
// 无需鉴权的接口,*表示全部
|
||||||
protected $noNeedRight = ['test2'];
|
protected $noNeedRight = ['test2'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试方法
|
||||||
|
*
|
||||||
|
* @ApiTitle (测试名称)
|
||||||
|
* @ApiSummary (测试描述信息)
|
||||||
|
* @ApiMethod (POST)
|
||||||
|
* @ApiRoute (/api/demo/test/id/{id}/name/{name})
|
||||||
|
* @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
|
||||||
|
* @ApiParams (name="id", type="integer", required=true, description="会员ID")
|
||||||
|
* @ApiParams (name="name", type="string", required=true, description="用户名")
|
||||||
|
* @ApiParams (name="data", type="object", sample="{'user_id':'int','user_name':'string','profile':{'email':'string','age':'integer'}}", description="扩展数据")
|
||||||
|
* @ApiReturnParams (name="code", type="integer", required=true, sample="0")
|
||||||
|
* @ApiReturnParams (name="msg", type="string", required=true, sample="返回成功")
|
||||||
|
* @ApiReturnParams (name="data", type="object", sample="{'user_id':'int','user_name':'string','profile':{'email':'string','age':'integer'}}", description="扩展数据返回")
|
||||||
|
* @ApiReturn ({
|
||||||
|
'code':'1',
|
||||||
|
'msg':'返回成功'
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
public function test()
|
||||||
|
{
|
||||||
|
$this->success('返回成功', $this->request->param());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 无需登录的接口
|
* 无需登录的接口
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function test1()
|
public function test1()
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +54,7 @@ class Demo extends Api
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 需要登录的接口
|
* 需要登录的接口
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function test2()
|
public function test2()
|
||||||
{
|
{
|
||||||
|
|
@ -39,7 +63,7 @@ class Demo extends Api
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 需要登录且需要验证有相应组的权限
|
* 需要登录且需要验证有相应组的权限
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function test3()
|
public function test3()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ class Backend extends Controller
|
||||||
case 'FINDIN':
|
case 'FINDIN':
|
||||||
case 'FINDINSET':
|
case 'FINDINSET':
|
||||||
case 'FIND_IN_SET':
|
case 'FIND_IN_SET':
|
||||||
$where[] = "FIND_IN_SET('{$v}', " . ($this->relationSearch ? $k : '`' . str_replace('.', '`.`', $k) . '`') . ")";
|
$where[] = "FIND_IN_SET('{$v}', " . ($relationSearch ? $k : '`' . str_replace('.', '`.`', $k) . '`') . ")";
|
||||||
break;
|
break;
|
||||||
case 'IN':
|
case 'IN':
|
||||||
case 'IN(...)':
|
case 'IN(...)':
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"fastadmin-citypicker": "~1.3.0",
|
"fastadmin-citypicker": "~1.3.0",
|
||||||
"fastadmin-cxselect": "~1.4.0",
|
"fastadmin-cxselect": "~1.4.0",
|
||||||
"fastadmin-dragsort": "~1.0.0",
|
"fastadmin-dragsort": "~1.0.0",
|
||||||
"fastadmin-addtabs": "~1.0.0",
|
"fastadmin-addtabs": "~1.0.3",
|
||||||
"fastadmin-selectpage": "~1.0.0",
|
"fastadmin-selectpage": "~1.0.0",
|
||||||
"fastadmin-layer": "~3.1.2"
|
"fastadmin-layer": "~3.1.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1669
public/api.html
1669
public/api.html
File diff suppressed because it is too large
Load Diff
|
|
@ -11,6 +11,10 @@
|
||||||
@import url("../libs/nice-validator/dist/jquery.validator.css");
|
@import url("../libs/nice-validator/dist/jquery.validator.css");
|
||||||
@import url("../libs/bootstrap-select/dist/css/bootstrap-select.min.css");
|
@import url("../libs/bootstrap-select/dist/css/bootstrap-select.min.css");
|
||||||
@import url("../libs/fastadmin-selectpage/selectpage.css");
|
@import url("../libs/fastadmin-selectpage/selectpage.css");
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
background: #f1f4f6;
|
background: #f1f4f6;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
@ -44,18 +48,19 @@ html.ios-fix body {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
.wrapper {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
#header {
|
#header {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
.control-relative {
|
.control-relative {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.tab-addtabs {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.tab-addtabs .tab-pane {
|
.tab-addtabs .tab-pane {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -148,8 +148,8 @@ $(function () {
|
||||||
//Extend options if external options exist
|
//Extend options if external options exist
|
||||||
if (typeof AdminLTEOptions !== "undefined") {
|
if (typeof AdminLTEOptions !== "undefined") {
|
||||||
$.extend(true,
|
$.extend(true,
|
||||||
$.AdminLTE.options,
|
$.AdminLTE.options,
|
||||||
AdminLTEOptions);
|
AdminLTEOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Easy access to options
|
//Easy access to options
|
||||||
|
|
@ -245,11 +245,11 @@ function _init() {
|
||||||
$.AdminLTE.layout = {
|
$.AdminLTE.layout = {
|
||||||
activate: function () {
|
activate: function () {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
_this.fix();
|
//_this.fix();
|
||||||
_this.fixSidebar();
|
_this.fixSidebar();
|
||||||
$('body, html, .wrapper').css('height', 'auto');
|
//$('body, html, .wrapper').css('height', 'auto');
|
||||||
$(window, ".wrapper").resize(function () {
|
$(window, ".wrapper").resize(function () {
|
||||||
_this.fix();
|
//_this.fix();
|
||||||
_this.fixSidebar();
|
_this.fixSidebar();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -365,14 +365,14 @@ function _init() {
|
||||||
//Expand sidebar on hover
|
//Expand sidebar on hover
|
||||||
$('.main-sidebar').hover(function () {
|
$('.main-sidebar').hover(function () {
|
||||||
if ($('body').hasClass('sidebar-mini')
|
if ($('body').hasClass('sidebar-mini')
|
||||||
&& $("body").hasClass('sidebar-collapse')
|
&& $("body").hasClass('sidebar-collapse')
|
||||||
&& $(window).width() > screenWidth) {
|
&& $(window).width() > screenWidth) {
|
||||||
_this.expand();
|
_this.expand();
|
||||||
}
|
}
|
||||||
}, function () {
|
}, function () {
|
||||||
if ($('body').hasClass('sidebar-mini')
|
if ($('body').hasClass('sidebar-mini')
|
||||||
&& $('body').hasClass('sidebar-expanded-on-hover')
|
&& $('body').hasClass('sidebar-expanded-on-hover')
|
||||||
&& $(window).width() > screenWidth) {
|
&& $(window).width() > screenWidth) {
|
||||||
_this.collapse();
|
_this.collapse();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -399,58 +399,58 @@ function _init() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var animationSpeed = $.AdminLTE.options.animationSpeed;
|
var animationSpeed = $.AdminLTE.options.animationSpeed;
|
||||||
$(document).off('click', menu + ' li a')
|
$(document).off('click', menu + ' li a')
|
||||||
.on('click', menu + ' li a', function (e) {
|
.on('click', menu + ' li a', function (e) {
|
||||||
//Get the clicked link and the next element
|
//Get the clicked link and the next element
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
var checkElement = $this.next();
|
var checkElement = $this.next();
|
||||||
|
|
||||||
//Check if the next element is a menu and is visible
|
//Check if the next element is a menu and is visible
|
||||||
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
|
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
|
||||||
//Close the menu
|
//Close the menu
|
||||||
checkElement.slideUp(animationSpeed, function () {
|
checkElement.slideUp(animationSpeed, function () {
|
||||||
checkElement.removeClass('menu-open');
|
checkElement.removeClass('menu-open');
|
||||||
//Fix the layout in case the sidebar stretches over the height of the window
|
//Fix the layout in case the sidebar stretches over the height of the window
|
||||||
//_this.layout.fix();
|
//_this.layout.fix();
|
||||||
});
|
});
|
||||||
checkElement.parent("li").removeClass("active");
|
checkElement.parent("li").removeClass("active");
|
||||||
|
}
|
||||||
|
//If the menu is not visible
|
||||||
|
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
|
||||||
|
//Get the parent menu
|
||||||
|
var parent = $this.parents('ul').first();
|
||||||
|
// modified by FastAdmin
|
||||||
|
if ($(".show-submenu", menu).size() == 0) {
|
||||||
|
//Close all open menus within the parent
|
||||||
|
var ul = parent.find('ul:visible').slideUp(animationSpeed);
|
||||||
|
//Remove the menu-open class from the parent
|
||||||
|
ul.removeClass('menu-open');
|
||||||
}
|
}
|
||||||
//If the menu is not visible
|
//Get the parent li
|
||||||
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
|
var parent_li = $this.parent("li");
|
||||||
//Get the parent menu
|
|
||||||
var parent = $this.parents('ul').first();
|
|
||||||
// modified by FastAdmin
|
|
||||||
if ($(".show-submenu", menu).size() == 0) {
|
|
||||||
//Close all open menus within the parent
|
|
||||||
var ul = parent.find('ul:visible').slideUp(animationSpeed);
|
|
||||||
//Remove the menu-open class from the parent
|
|
||||||
ul.removeClass('menu-open');
|
|
||||||
}
|
|
||||||
//Get the parent li
|
|
||||||
var parent_li = $this.parent("li");
|
|
||||||
|
|
||||||
//Open the target menu and add the menu-open class
|
//Open the target menu and add the menu-open class
|
||||||
checkElement.slideDown(animationSpeed, function () {
|
checkElement.slideDown(animationSpeed, function () {
|
||||||
//Add the class active to the parent li
|
//Add the class active to the parent li
|
||||||
checkElement.addClass('menu-open');
|
checkElement.addClass('menu-open');
|
||||||
//parent.find('li.active').removeClass('active');
|
//parent.find('li.active').removeClass('active');
|
||||||
//parent_li.addClass('active');
|
//parent_li.addClass('active');
|
||||||
//Fix the layout in case the sidebar stretches over the height of the window
|
//Fix the layout in case the sidebar stretches over the height of the window
|
||||||
_this.layout.fix();
|
_this.layout.fix();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (!$this.parent().hasClass("active")) {
|
if (!$this.parent().hasClass("active")) {
|
||||||
$this.parent().addClass("active");
|
$this.parent().addClass("active");
|
||||||
}
|
|
||||||
// modified by FastAdmin
|
|
||||||
if ($(".show-submenu", menu).size() == 0) {
|
|
||||||
$this.parent().siblings().find("ul.menu-open").slideUp();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//if this isn't a link, prevent the page from being redirected
|
// modified by FastAdmin
|
||||||
if (checkElement.is('.treeview-menu')) {
|
if ($(".show-submenu", menu).size() == 0) {
|
||||||
e.preventDefault();
|
$this.parent().siblings().find("ul.menu-open").slideUp();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
//if this isn't a link, prevent the page from being redirected
|
||||||
|
if (checkElement.is('.treeview-menu')) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ControlSidebar
|
/* ControlSidebar
|
||||||
|
|
@ -477,7 +477,7 @@ function _init() {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
//If the sidebar is not open
|
//If the sidebar is not open
|
||||||
if (!sidebar.hasClass('control-sidebar-open')
|
if (!sidebar.hasClass('control-sidebar-open')
|
||||||
&& !$('body').hasClass('control-sidebar-open')) {
|
&& !$('body').hasClass('control-sidebar-open')) {
|
||||||
//Open the sidebar
|
//Open the sidebar
|
||||||
_this.open(sidebar, o.slide);
|
_this.open(sidebar, o.slide);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -588,8 +588,8 @@ function _init() {
|
||||||
if (!box.hasClass("collapsed-box")) {
|
if (!box.hasClass("collapsed-box")) {
|
||||||
//Convert minus into plus
|
//Convert minus into plus
|
||||||
element.children(":first")
|
element.children(":first")
|
||||||
.removeClass(_this.icons.collapse)
|
.removeClass(_this.icons.collapse)
|
||||||
.addClass(_this.icons.open);
|
.addClass(_this.icons.open);
|
||||||
//Hide the content
|
//Hide the content
|
||||||
box_content.slideUp(_this.animationSpeed, function () {
|
box_content.slideUp(_this.animationSpeed, function () {
|
||||||
box.addClass("collapsed-box");
|
box.addClass("collapsed-box");
|
||||||
|
|
@ -597,8 +597,8 @@ function _init() {
|
||||||
} else {
|
} else {
|
||||||
//Convert plus into minus
|
//Convert plus into minus
|
||||||
element.children(":first")
|
element.children(":first")
|
||||||
.removeClass(_this.icons.open)
|
.removeClass(_this.icons.open)
|
||||||
.addClass(_this.icons.collapse);
|
.addClass(_this.icons.collapse);
|
||||||
//Show the content
|
//Show the content
|
||||||
box_content.slideDown(_this.animationSpeed, function () {
|
box_content.slideDown(_this.animationSpeed, function () {
|
||||||
box.removeClass("collapsed-box");
|
box.removeClass("collapsed-box");
|
||||||
|
|
@ -782,16 +782,13 @@ function _init() {
|
||||||
};
|
};
|
||||||
|
|
||||||
//set/get form element value
|
//set/get form element value
|
||||||
$.fn.field = function (name, value)
|
$.fn.field = function (name, value) {
|
||||||
{
|
|
||||||
if (typeof name !== "string")
|
if (typeof name !== "string")
|
||||||
return false;
|
return false;
|
||||||
var element = $(this).find("[name='" + name + "']");
|
var element = $(this).find("[name='" + name + "']");
|
||||||
|
|
||||||
if (typeof value === "undefined" && element.length >= 1)
|
if (typeof value === "undefined" && element.length >= 1) {
|
||||||
{
|
switch (element.attr("type")) {
|
||||||
switch (element.attr("type"))
|
|
||||||
{
|
|
||||||
case "checkbox":
|
case "checkbox":
|
||||||
var result = new Array();
|
var result = new Array();
|
||||||
element.each(function (i, val) {
|
element.each(function (i, val) {
|
||||||
|
|
@ -814,10 +811,8 @@ function _init() {
|
||||||
return element.val();
|
return element.val();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
{
|
switch (element.attr("type")) {
|
||||||
switch (element.attr("type"))
|
|
||||||
{
|
|
||||||
case "checkbox":
|
case "checkbox":
|
||||||
case "radio":
|
case "radio":
|
||||||
value = $.isArray(value) ? value : [value];
|
value = $.isArray(value) ? value : [value];
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
||||||
edit_url: 'category/edit',
|
edit_url: 'category/edit',
|
||||||
del_url: 'category/del',
|
del_url: 'category/del',
|
||||||
multi_url: 'category/multi',
|
multi_url: 'category/multi',
|
||||||
dragsort_url: '',
|
dragsort_url: 'ajax/weigh',
|
||||||
table: 'category',
|
table: 'category',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -29,37 +29,33 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
data: Orderdata.column
|
data: Orderdata.column
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {},
|
||||||
|
|
||||||
},
|
|
||||||
grid: [{
|
grid: [{
|
||||||
left: 'left',
|
left: 'left',
|
||||||
top: 'top',
|
top: 'top',
|
||||||
right: '10',
|
right: '10',
|
||||||
bottom: 30
|
bottom: 30
|
||||||
}],
|
}],
|
||||||
series: [{
|
series: [{
|
||||||
name: __('Sales'),
|
name: __('Sales'),
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
normal: {}
|
||||||
}
|
|
||||||
},
|
|
||||||
lineStyle: {
|
|
||||||
normal: {
|
|
||||||
width: 1.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: Orderdata.paydata
|
|
||||||
},
|
},
|
||||||
|
lineStyle: {
|
||||||
|
normal: {
|
||||||
|
width: 1.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: Orderdata.paydata
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: __('Orders'),
|
name: __('Orders'),
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
normal: {
|
normal: {}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
normal: {
|
normal: {
|
||||||
|
|
@ -92,20 +88,23 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
|
||||||
data: Orderdata.column
|
data: Orderdata.column
|
||||||
},
|
},
|
||||||
series: [{
|
series: [{
|
||||||
name: __('Sales'),
|
name: __('Sales'),
|
||||||
data: Orderdata.paydata
|
data: Orderdata.paydata
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: __('Orders'),
|
name: __('Orders'),
|
||||||
data: Orderdata.createdata
|
data: Orderdata.createdata
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
if ($("#echart").width() != $("#echart canvas").width() && $("#echart canvas").width() < $("#echart").width()) {
|
||||||
|
myChart.resize();
|
||||||
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
$(window).resize(function () {
|
$(window).resize(function () {
|
||||||
myChart.resize();
|
myChart.resize();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("click", ".btn-checkversion", function(){
|
$(document).on("click", ".btn-checkversion", function () {
|
||||||
top.window.$("[data-toggle=checkupdate]").trigger("click");
|
top.window.$("[data-toggle=checkupdate]").trigger("click");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,6 @@
|
||||||
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], function ($, undefined, Backend, undefined, AdminLTE, Form) {
|
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], function ($, undefined, Backend, undefined, AdminLTE, Form) {
|
||||||
var Controller = {
|
var Controller = {
|
||||||
index: function () {
|
index: function () {
|
||||||
//窗口大小改变,修正主窗体最小高度
|
|
||||||
$(window).resize(function () {
|
|
||||||
$(".tab-addtabs").css("height", $(".content-wrapper").height() + "px");
|
|
||||||
});
|
|
||||||
|
|
||||||
//双击重新加载页面
|
//双击重新加载页面
|
||||||
$(document).on("dblclick", ".sidebar-menu li > a", function (e) {
|
$(document).on("dblclick", ".sidebar-menu li > a", function (e) {
|
||||||
$("#con_" + $(this).attr("addtabs") + " iframe").attr('src', function (i, val) {
|
$("#con_" + $(this).attr("addtabs") + " iframe").attr('src', function (i, val) {
|
||||||
|
|
|
||||||
|
|
@ -10517,18 +10517,21 @@ define("drop", function(){});
|
||||||
if (options.close && $("li", navobj).size() > 0) {
|
if (options.close && $("li", navobj).size() > 0) {
|
||||||
tabitem.append(' <i class="close-tab fa fa-remove"></i>');
|
tabitem.append(' <i class="close-tab fa fa-remove"></i>');
|
||||||
}
|
}
|
||||||
//创建新TAB的内容
|
if (conitem.size() === 0) {
|
||||||
conitem = $('<div role="tabpanel" class="tab-pane" id="' + conid + '"></div>');
|
//创建新TAB的内容
|
||||||
//是否指定TAB内容
|
conitem = $('<div role="tabpanel" class="tab-pane" id="' + conid + '"></div>');
|
||||||
if (opts.content) {
|
//是否指定TAB内容
|
||||||
conitem.append(opts.content);
|
if (opts.content) {
|
||||||
} else if (options.iframeUse && !opts.ajax) {//没有内容,使用IFRAME打开链接
|
conitem.append(opts.content);
|
||||||
var height = options.iframeHeight;
|
} else if (options.iframeUse && !opts.ajax) {//没有内容,使用IFRAME打开链接
|
||||||
conitem.append('<iframe src="' + url + '" width="100%" height="' + height + '" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe></div>');
|
var height = options.iframeHeight;
|
||||||
} else {
|
conitem.append('<iframe src="' + url + '" width="100%" height="' + height + '" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe></div>');
|
||||||
$.get(url, function (data) {
|
} else {
|
||||||
conitem.append(data);
|
$.get(url, function (data) {
|
||||||
});
|
conitem.append(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
tabobj.append(conitem);
|
||||||
}
|
}
|
||||||
//加入TABS
|
//加入TABS
|
||||||
if ($('.tabdrop li', navobj).size() > 0) {
|
if ($('.tabdrop li', navobj).size() > 0) {
|
||||||
|
|
@ -10536,7 +10539,6 @@ define("drop", function(){});
|
||||||
} else {
|
} else {
|
||||||
navobj.append(tabitem);
|
navobj.append(tabitem);
|
||||||
}
|
}
|
||||||
tabobj.append(conitem);
|
|
||||||
} else {
|
} else {
|
||||||
//强制刷新iframe
|
//强制刷新iframe
|
||||||
if (options.iframeForceRefresh) {
|
if (options.iframeForceRefresh) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@
|
||||||
@panel-intro-bg: darken(@main-bg, 3%);
|
@panel-intro-bg: darken(@main-bg, 3%);
|
||||||
@panel-nav-bg: #fff;
|
@panel-nav-bg: #fff;
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #f1f4f6;
|
background: #f1f4f6;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
@ -56,7 +61,9 @@ html.ios-fix, html.ios-fix body {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
.wrapper {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
#header {
|
#header {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
//box-shadow: 0 2px 2px rgba(0,0,0,.05),0 1px 0 rgba(0,0,0,.05);
|
//box-shadow: 0 2px 2px rgba(0,0,0,.05),0 1px 0 rgba(0,0,0,.05);
|
||||||
|
|
@ -64,6 +71,7 @@ html.ios-fix, html.ios-fix body {
|
||||||
|
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height:100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-relative {
|
.control-relative {
|
||||||
|
|
@ -71,7 +79,7 @@ html.ios-fix, html.ios-fix body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-addtabs {
|
.tab-addtabs {
|
||||||
overflow: hidden;
|
//overflow: hidden;
|
||||||
.tab-pane {
|
.tab-pane {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue