新增系统配置功能模块,后台配置参数更加方便

新增php think crud一键删除功能
新增php think menu一键删除菜单节点功能
新增默认生成validate服务端验证器的文件
新增添加编辑时启用validate的功能,默认关闭
新增固定一个后台页面的功能
新增微信配置管理,采用独立的wechat_config表存储
分类配置变更在后台系统配置中增改
变更CRUD生成的视图文件,取消调用函数生成,而是通过foreach标签生成
修复时间字段为int时不能修改的BUG
修复窗口过小导致部分组件被隐藏的BUG
pull/323483/MERGE
Karson 2017-06-14 17:38:29 +08:00
parent f16c4e0048
commit 81ddcd143c
55 changed files with 1602 additions and 746 deletions

View File

@ -15,6 +15,8 @@ use think\Lang;
class Crud extends Command
{
protected $stubList = [];
protected function configure()
{
$this
@ -28,7 +30,8 @@ class Crud extends Command
->addOption('relationmodel', 'e', Option::VALUE_OPTIONAL, 'relation model name', null)
->addOption('relationforeignkey', 'k', Option::VALUE_OPTIONAL, 'relation foreign key', null)
->addOption('relationprimarykey', 'p', Option::VALUE_OPTIONAL, 'relation primary key', null)
->addOption('mode', 'o', Option::VALUE_OPTIONAL, 'relation table mode,hasone or belongsto', 'hasone')
->addOption('mode', 'o', Option::VALUE_OPTIONAL, 'relation table mode,hasone or belongsto', 'belongsto')
->addOption('delete', 'd', Option::VALUE_OPTIONAL, 'delete all files generated by CRUD', null)
->setDescription('Build CRUD controller and model from table');
}
@ -98,25 +101,66 @@ class Crud extends Command
$controllerName = ucfirst(array_pop($controllerArr));
$controllerDir = implode(DS, $controllerArr);
$controllerFile = ($controllerDir ? $controllerDir . DS : '') . $controllerName . '.php';
$viewDir = $adminPath . 'view' . DS . $controllerUrl . DS;
//非覆盖模式时如果存在控制器文件则报错
if (is_file($controllerFile) && !$force)
{
throw new Exception('controller already exists!\nIf you need to rebuild again, use the parameter --force=true ');
}
//最终将生成的文件路径
$controllerFile = $adminPath . 'controller' . DS . $controllerFile;
$javascriptFile = ROOT_PATH . 'public' . DS . 'assets' . DS . 'js' . DS . 'backend' . DS . $controllerUrl . '.js';
$addFile = $viewDir . 'add.html';
$editFile = $viewDir . 'edit.html';
$indexFile = $viewDir . 'index.html';
$langFile = $adminPath . 'lang' . DS . Lang::detect() . DS . $controllerUrl . '.php';
//模型默认以表名进行处理,以下划线进行分隔,如果需要自定义则需要传入model,不支持目录层级
$modelName = $this->getModelName($model, $table);
$modelFile = ($local ? $adminPath : APP_PATH . 'common' . DS) . 'model' . DS . $modelName . '.php';
$validateFile = $adminPath . 'validate' . DS . $modelName . '.php';
//关联模型默认以表名进行处理,以下划线进行分隔,如果需要自定义则需要传入relationmodel,不支持目录层级
$relationModelName = $this->getModelName($relationModel, $relation);
$relationModelFile = ($local ? $adminPath : APP_PATH . 'common' . DS) . 'model' . DS . $relationModelName . '.php';
//是否为删除模式
$delete = $input->getOption('delete');
if ($delete)
{
$readyFiles = [$controllerFile, $modelFile, $validateFile, $addFile, $editFile, $indexFile, $langFile, $javascriptFile];
foreach ($readyFiles as $k => $v)
{
$output->warning($v);
}
$output->info("Are you sure you want to delete all those files? Type 'yes' to continue: ");
$line = fgets(STDIN);
if (trim($line) != 'yes')
{
throw new Exception("Operation is aborted!");
}
foreach ($readyFiles as $k => $v)
{
unlink($v);
}
$output->info("Delete Successed");
return;
}
//非覆盖模式时如果存在控制器文件则报错
if (is_file($controllerFile) && !$force)
{
throw new Exception("controller already exists!\nIf you need to rebuild again, use the parameter --force=true ");
}
//非覆盖模式时如果存在模型文件则报错
if (is_file($modelFile) && !$force)
{
throw new Exception('model already exists!\nIf you need to rebuild again, use the parameter --force=true ');
throw new Exception("model already exists!\nIf you need to rebuild again, use the parameter --force=true ");
}
//非覆盖模式时如果存在验证文件则报错
if (is_file($validateFile) && !$force)
{
throw new Exception("validate already exists!\nIf you need to rebuild again, use the parameter --force=true ");
}
require $adminPath . 'common.php';
@ -219,7 +263,9 @@ class Crud extends Command
Form::setEscapeHtml(false);
$setAttrArr = [];
$getAttrArr = [];
$getEnumArr = [];
$appendAttrList = [];
$controllerAssignList = [];
//循环所有字段,开始构造视图的HTML和JS信息
foreach ($columnList as $k => $v)
@ -231,12 +277,14 @@ class Crud extends Command
{
$itemArr = substr($v['COLUMN_TYPE'], strlen($v['DATA_TYPE']) + 1, -1);
$itemArr = explode(',', str_replace("'", '', $itemArr));
$itemArr = $this->getItemArray($itemArr, $field, $v['COLUMN_COMMENT']);
}
// 语言列表
if ($v['COLUMN_COMMENT'] != '')
{
$langList[] = $this->getLangItem($field, $v['COLUMN_COMMENT']);
}
$inputType = '';
//createtime和updatetime是保留字段不能修改和添加
if ($v['COLUMN_KEY'] != 'PRI' && !in_array($field, ['createtime', 'updatetime']))
{
@ -255,13 +303,7 @@ class Crud extends Command
{
$attrArr['data-rule'] = 'required';
}
if ($field == 'status' && in_array($inputType, ['text', 'number']))
{
//如果状态类型不是enum或set
$itemArr = !$itemArr ? ['normal', 'hidden'] : $itemArr;
$inputType = 'radio';
$this->getAttr($getAttrArr, $field);
}
if ($inputType == 'select')
{
$cssClassArr[] = 'selectpicker';
@ -271,15 +313,16 @@ class Crud extends Command
$attrArr['multiple'] = '';
$fieldName .= "[]";
}
$attrStr = $this->getArrayString($attrArr);
$itemArr = $this->getLangArray($itemArr, FALSE);
$itemString = $this->getArrayString($itemArr);
$attrArr['name'] = $fieldName;
$this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $v['DATA_TYPE'] == 'set' ? 'multiple' : 'select');
$itemArr = $this->getLangArray($itemArr, FALSE);
//添加一个获取器
$this->getAttr($getAttrArr, $field, $itemArr, $v['DATA_TYPE'] == 'set' ? 'multiple' : 'select');
$this->getAttr($getAttrArr, $field, $v['DATA_TYPE'] == 'set' ? 'multiple' : 'select');
$this->appendAttr($appendAttrList, $field);
$formAddElement = "{:build_select('{$fieldName}', [{$itemString}], '{$defaultValue}', [{$attrStr}])}";
$formEditElement = "{:build_select('{$fieldName}', [{$itemString}], \$row.{$field}, [{$attrStr}])}";
$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')
{
@ -310,8 +353,8 @@ class Crud extends Command
break;
default:
$fieldFunc = 'datetime';
$this->getAttr($getAttrArr, $field, '', $inputType);
$this->setAttr($setAttrArr, $field, '', $inputType);
$this->getAttr($getAttrArr, $field, $inputType);
$this->setAttr($setAttrArr, $field, $inputType);
$this->appendAttr($appendAttrList, $field);
break;
}
@ -322,27 +365,19 @@ class Crud extends Command
$formAddElement = Form::text($fieldName, $defaultDateTime, $attrArr);
$formEditElement = Form::text($fieldName, "{\$row.{$field}{$fieldFunc}}", $attrArr);
}
else if ($inputType == 'checkbox')
else if ($inputType == 'checkbox' || $inputType == 'radio')
{
$fieldName .= "[]";
$fieldName = $inputType == 'checkbox' ? $fieldName .= "[]" : $fieldName;
$attrArr['name'] = "row[{$fieldName}]";
$itemArr = $this->getLangArray($itemArr, FALSE);
$itemString = $this->getArrayString($itemArr);
$this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $inputType);
//添加一个获取器
$this->getAttr($getAttrArr, $field, $itemArr, $inputType);
$this->getAttr($getAttrArr, $field, $inputType);
$this->appendAttr($appendAttrList, $field);
$formAddElement = "{:build_checkboxs('{$fieldName}', [{$itemString}], '{$defaultValue}')}";
$formEditElement = "{:build_checkboxs('{$fieldName}', [{$itemString}], \$row.{$field})}";
}
else if ($inputType == 'radio')
{
$itemArr = $this->getLangArray($itemArr, FALSE);
$itemString = $this->getArrayString($itemArr);
$defaultValue = $defaultValue ? $defaultValue : key($itemArr);
//添加一个获取器
$this->getAttr($getAttrArr, $field, $itemArr, $inputType);
$this->appendAttr($appendAttrList, $field);
$formAddElement = "{:build_radios('{$fieldName}', [{$itemString}], '{$defaultValue}')}";
$formEditElement = "{:build_radios('{$fieldName}', [{$itemString}], \$row.{$field})}";
$defaultValue = $inputType == 'radio' && !$defaultValue ? key($itemArr) : $defaultValue;
$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')
{
@ -410,7 +445,11 @@ class Crud extends Command
$javascriptList[] = "{field: 'state', checkbox: true}";
}
//构造JS列信息
$javascriptList[] = $this->getJsColumn($field);
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE']);
if ($inputType && in_array($inputType, ['select', 'checkbox', 'radio']))
{
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], '_text');
}
//排序方式,如果有weigh则按weigh,否则按主键排序
$order = $field == 'weigh' ? 'weigh' : $order;
}
@ -434,7 +473,7 @@ class Crud extends Command
if ($v['DATA_TYPE'] != 'text')
{
//构造JS列信息
$javascriptList[] = $this->getJsColumn($relationField);
$javascriptList[] = $this->getJsColumn($relationField, $v['DATA_TYPE']);
}
}
@ -450,27 +489,23 @@ class Crud extends Command
$tableComment = $tableInfo['Comment'];
$tableComment = mb_substr($tableComment, -1) == '表' ? mb_substr($tableComment, 0, -1) . '管理' : $tableComment;
//最终将生成的文件路径
$controllerFile = $adminPath . 'controller' . DS . $controllerFile;
$javascriptFile = ROOT_PATH . 'public' . DS . 'assets' . DS . 'js' . DS . 'backend' . DS . $controllerUrl . '.js';
$addFile = $adminPath . 'view' . DS . $controllerUrl . DS . 'add.html';
$editFile = $adminPath . 'view' . DS . $controllerUrl . DS . 'edit.html';
$indexFile = $adminPath . 'view' . DS . $controllerUrl . DS . 'index.html';
$langFile = $adminPath . 'lang' . DS . Lang::detect() . DS . $controllerUrl . '.php';
$appNamespace = Config::get('app_namespace');
$moduleName = 'admin';
$controllerNamespace = "{$appNamespace}\\{$moduleName}\\controller" . ($controllerDir ? "\\" : "") . str_replace('/', "\\", $controllerDir);
$modelNamespace = "{$appNamespace}\\" . ($local ? $moduleName : "common") . "\\model";
$validateNamespace = "{$appNamespace}\\" . $moduleName . "\\validate";
$validateName = $modelName;
$data = [
'controllerNamespace' => $controllerNamespace,
'modelNamespace' => $modelNamespace,
'validateNamespace' => $validateNamespace,
'controllerUrl' => $controllerUrl,
'controllerDir' => $controllerDir,
'controllerName' => $controllerName,
'controllerAssignList' => implode("\n", $controllerAssignList),
'modelName' => $modelName,
'validateName' => $validateName,
'tableComment' => $tableComment,
'iconName' => $iconName,
'pk' => $priKey,
@ -495,6 +530,7 @@ class Crud extends Command
'relationSearch' => $relation ? 'true' : 'false',
'controllerIndex' => '',
'appendAttrList' => implode(",\n", $appendAttrList),
'getEnumList' => implode("\n\n", $getEnumArr),
'getAttrList' => implode("\n\n", $getAttrArr),
'setAttrList' => implode("\n\n", $setAttrArr),
'modelMethod' => '',
@ -527,6 +563,8 @@ class Crud extends Command
// 生成关联模型文件
$result = $this->writeToFile('relationmodel', $data, $relationModelFile);
}
// 生成验证文件
$result = $this->writeToFile('validate', $data, $validateFile);
// 生成视图文件
$result = $this->writeToFile('add', $data, $addFile);
$result = $this->writeToFile('edit', $data, $editFile);
@ -541,79 +579,56 @@ class Crud extends Command
}
catch (\think\exception\ErrorException $e)
{
print_r($e);
throw new Exception("Code: " . $e->getCode() . "\nLine: " . $e->getLine() . "\nMessage: " . $e->getMessage());
}
$output->writeln("<info>Build Successed</info>");
$output->info("Build Successed");
}
protected function getAttr(&$getAttr, $field, $itemArr = '', $inputType = '')
protected function getEnum(&$getEnum, &$controllerAssignList, $field, $itemArr = '', $inputType = '')
{
if (preg_match("/[_\-]+/", $field))
{
return;
}
if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio']))
return;
$attrField = ucfirst($field);
if ($inputType == 'datetime')
$fieldList = $this->getFieldListName($field);
$methodName = 'get' . ucfirst($fieldList);
unset($v);
foreach ($itemArr as $k => &$v)
{
$return = <<<EOD
\$value = \$data['{$field}'];
return is_numeric(\$value) ? date("Y-m-d H:i:s", \$value) : \$value;
EOD;
$v = "__('" . ucfirst($v) . "')";
}
else if (in_array($inputType, ['multiple', 'checkbox']))
{
unset($v);
$itemString = $this->getArrayString($itemArr);
$return = <<<EOD
\$value = \$data['{$field}'];
\$valueArr = explode(',', \$value);
\$arr = [{$itemString}];
\$resultArr = [];
foreach (\$valueArr as \$k => \$v)
$getEnum[] = <<<EOD
public function {$methodName}()
{
if (isset(\$arr[\$v]))
{
\$resultArr[] = \$arr[\$v];
return [{$itemString}];
}
}
return implode(',', \$resultArr);
EOD;
}
else
{
$itemString = $this->getArrayString($itemArr);
$return = <<<EOD
\$value = \$data['{$field}'];
\$arr = [{$itemString}];
return isset(\$arr[\$value]) ? \$arr[\$value] : '';
EOD;
}
$getAttr[] = <<<EOD
protected function get{$attrField}TextAttr(\$value, \$data)
{
$return
}
$controllerAssignList[] = <<<EOD
\$this->view->assign("{$fieldList}", \$this->model->{$methodName}());
EOD;
}
protected function setAttr(&$setAttr, $field, $itemArr = '', $inputType = '')
{
if (preg_match("/[_\-]+/", $field))
protected function getAttr(&$getAttr, $field, $inputType = '')
{
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 ($inputType != 'datetime')
return;
$field = ucfirst($field);
$attrField = ucfirst($this->getCamelizeName($field));
if ($inputType == 'datetime')
{
$return = <<<EOD
return \$value && is_numeric(\$value) ? strtotime(\$value) : \$value;
return \$value && !is_numeric(\$value) ? strtotime(\$value) : \$value;
EOD;
}
$setAttr[] = <<<EOD
protected function set{$field}Attr(\$value)
protected function set{$attrField}Attr(\$value)
{
$return
}
@ -622,10 +637,6 @@ EOD;
protected function appendAttr(&$appendAttrList, $field)
{
if (preg_match("/[_\-]+/", $field))
{
return;
}
$appendAttrList[] = <<<EOD
'{$field}_text'
EOD;
@ -680,7 +691,15 @@ EOD;
$search[] = "{%{$k}%}";
$replace[] = $v;
}
$stub = file_get_contents($this->getStub($name));
$stubname = $this->getStub($name);
if (isset($this->stubList[$stubname]))
{
$stub = $this->stubList[$stubname];
}
else
{
$this->stubList[$stubname] = $stub = file_get_contents($stubname);
}
$content = str_replace($search, $replace, $stub);
return $content;
}
@ -697,11 +716,29 @@ EOD;
protected function getLangItem($field, $content)
{
if (!Lang::has($field))
if ($content || !Lang::has($field))
{
return <<<EOD
'{$field}' => '{$content}'
EOD;
$itemArr = [];
if (stripos($content, ':') !== false && stripos($content, ',') && stripos($content, '=') !== false)
{
list($fieldLang, $item) = explode(':', $content);
$itemArr = [$field => $fieldLang];
foreach (explode(',', $item) as $k => $v)
{
list($key, $value) = explode('=', $v);
$itemArr[$field . ' ' . $key] = $value;
}
}
else
{
$itemArr = [$field => $content];
}
$resultArr = [];
foreach ($itemArr as $k => $v)
{
$resultArr[] = " '" . ucfirst($k) . "' => '{$v}'";
}
return implode(",\n", $resultArr);
}
else
{
@ -731,6 +768,8 @@ EOD;
*/
protected function getArrayString($arr)
{
if (!is_array($arr))
return $arr;
$stringArr = [];
foreach ($arr as $k => $v)
{
@ -740,11 +779,34 @@ EOD;
$v = str_replace("'", "\'", $v);
$k = str_replace("'", "\'", $k);
}
$stringArr[] = "'" . (is_numeric($k) ? $v : $k) . "' => " . (is_numeric($k) ? "__('" . ucfirst($k) . "')" : $is_var ? $v : "'{$v}'");
$stringArr[] = "'" . $k . "' => " . ($is_var ? $v : "'{$v}'");
}
return implode(",", $stringArr);
}
protected function getItemArray($item, $field, $comment)
{
$itemArr = [];
if (stripos($comment, ':') !== false && stripos($comment, ',') && stripos($comment, '=') !== false)
{
list($fieldLang, $item) = explode(':', $comment);
$itemArr = [];
foreach (explode(',', $item) as $k => $v)
{
list($key, $value) = explode('=', $v);
$itemArr[$key] = $field . ' ' . $key;
}
}
else
{
foreach ($item as $k => $v)
{
$itemArr[$v] = is_numeric($v) ? $field . ' ' . $v : $v;
}
}
return $itemArr;
}
protected function getFieldType(& $v)
{
$inputType = 'text';
@ -848,10 +910,10 @@ EOD;
* @param string $field
* @return string
*/
protected function getJsColumn($field)
protected function getJsColumn($field, $datatype = '', $extend = '')
{
$lang = ucfirst($field);
$html = str_repeat(" ", 24) . "{field: '{$field}', title: __('{$lang}')";
$html = str_repeat(" ", 24) . "{field: '{$field}{$extend}', title: __('{$lang}')";
$field = stripos($field, ".") !== false ? substr($field, stripos($field, '.') + 1) : $field;
$formatter = '';
if ($field == 'status')
@ -860,17 +922,32 @@ EOD;
$formatter = 'icon';
else if ($field == 'flag')
$formatter = 'flag';
else if (substr($field, -4) == 'time')
else if (substr($field, -4) == 'time' && in_array($datatype, ['int', 'timestamp']))
$formatter = 'datetime';
else if (substr($field, -3) == 'url')
else if (substr($field, -3) == 'url' || substr($field, -4) == 'file')
$formatter = 'url';
else if (substr($field, -5) == 'image')
$formatter = 'image';
if ($formatter)
else if (substr($field, -6) == 'images')
$formatter = 'images';
if ($extend)
$html .= ", operate:false";
if ($formatter && !$extend)
$html .= ", formatter: Table.api.formatter." . $formatter . "}";
else
$html .= "}";
return $html;
}
protected function getCamelizeName($uncamelized_words, $separator = '_')
{
$uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words));
return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator);
}
protected function getFieldListName($field)
{
return $this->getCamelizeName($field) . 'List';
}
}

View File

@ -15,12 +15,23 @@ use think\Request;
class {%controllerName%} extends Backend
{
/**
* {%modelName%}模型对象
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = model('{%modelName%}');
{%controllerAssignList%}
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个方法
* 因此在当前控制器中可不用编写增删改查的代码,如果需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
{%controllerIndex%}
}

View File

@ -0,0 +1,4 @@
{foreach name="{%fieldList%}" item="vo"}
<label for="{%fieldName%}-{$key}"><input id="{%fieldName%}-{$key}" name="{%fieldName%}" type="checkbox" value="{$key}" {in name="key" value="{%selectedValue%}"}checked{/in} /> {$vo}</label>
{/foreach}

View File

@ -0,0 +1,4 @@
{foreach name="{%fieldList%}" item="vo"}
<label for="{%fieldName%}-{$key}"><input id="{%fieldName%}-{$key}" name="{%fieldName%}" type="radio" value="{$key}" {in name="key" value="{%selectedValue%}"}checked{/in} /> {$vo}</label>
{/foreach}

View File

@ -0,0 +1,6 @@
<select {%attrStr%}>
{foreach name="{%fieldList%}" item="vo"}
<option value="{$key}" {in name="key" value="{%selectedValue%}"}selected{/in}>{$vo}</option>
{/foreach}
</select>

View File

@ -0,0 +1,8 @@
public function {%methodName%}($value, $data)
{
$value = $value ? $value : $data['{%field%}'];
$valueArr = explode(',', $value);
$list = $this->{%listMethodName%}();
return implode(',', array_intersect_key($list, array_flip($valueArr)));
}

View File

@ -0,0 +1,6 @@
public function {%methodName%}($value, $data)
{
$value = $value ? $value : $data['{%field%}'];
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}

View File

@ -0,0 +1,8 @@
public function {%methodName%}($value, $data)
{
$value = $value ? $value : $data['{%field%}'];
$valueArr = explode(',', $value);
$list = $this->{%listMethodName%}();
return implode(',', array_intersect_key($list, array_flip($valueArr)));
}

View File

@ -0,0 +1,7 @@
public function {%methodName%}($value, $data)
{
$value = $value ? $value : $data['{%field%}'];
$list = $this->{%listMethodName%}();
return isset($list[$value]) ? $list[$value] : '';
}

View File

@ -0,0 +1,7 @@
public function {%methodName%}($value, $data)
{
$value = $value ? $value : $data['{%field%}'];
$list = $this->{%listMethodName%}();
return isset($list[$value]) ? $list[$value] : '';
}

View File

@ -21,6 +21,9 @@ class {%modelName%} extends Model
{%appendAttrList%}
];
{%getEnumList%}
{%getAttrList%}
{%setAttrList%}

View File

@ -0,0 +1,27 @@
<?php
namespace {%validateNamespace%};
use think\Validate;
class {%validateName%} extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}

File diff suppressed because one or more lines are too long

View File

@ -23,6 +23,7 @@ class Menu extends Command
$this
->setName('menu')
->addOption('controller', 'c', Option::VALUE_REQUIRED, 'controller name,use \'all-controller\' when build all menu', null)
->addOption('delete', 'd', Option::VALUE_OPTIONAL, 'delete the specified menu', '')
->setDescription('Build auth menu from controller');
}
@ -30,12 +31,45 @@ class Menu extends Command
{
$this->model = new AuthRule();
$adminPath = dirname(__DIR__) . DS;
$moduleName = 'admin';
//控制器名
$controller = $input->getOption('controller') ?: '';
if (!$controller)
{
throw new Exception("please input controller name");
}
//是否为删除模式
$delete = $input->getOption('delete');
if ($delete)
{
if ($controller == 'all-controller')
{
throw new Exception("could not delete all menu");
}
$ids = [];
$list = $this->model->where('name', 'like', "/{$moduleName}/" . strtolower($controller) . "%")->select();
foreach ($list as $k => $v)
{
$output->warning($v->name);
$ids[] = $v->id;
}
if (!$ids)
{
throw new Exception("There is no menu to delete");
}
$readyMenu = [];
$output->info("Are you sure you want to delete all those menu? Type 'yes' to continue: ");
$line = fgets(STDIN);
if (trim($line) != 'yes')
{
throw new Exception("Operation is aborted!");
}
AuthRule::destroy($ids);
Cache::rm("__menu__");
$output->info("Delete Successed");
return;
}
if ($controller != 'all-controller')
{

View File

@ -82,12 +82,12 @@ function build_checkboxs($name, $list = [], $selected = null)
* @param array $attr
* @return string
*/
function build_category_select($name, $type, $selected = null, $attr = [])
function build_category_select($name, $type, $selected = null, $attr = [], $header = [])
{
$tree = Tree::instance();
$tree->init(Category::getCategoryArray($type), 'pid');
$categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name');
$categorydata = [0 => __('None')];
$categorydata = $header ? $header : [];
foreach ($categorylist as $k => $v)
{
$categorydata[$v['id']] = $v['name'];

View File

@ -33,7 +33,7 @@ class Index extends Backend
'auth/admin' => 12,
'auth/rule' => 4,
'general' => ['18', 'purple'],
]);
], $this->view->site['fixedpage']);
$this->view->assign('menulist', $menulist);
$this->view->assign('title', __('Home'));
return $this->view->fetch();

View File

@ -0,0 +1,236 @@
<?php
namespace app\admin\controller\general;
use app\common\controller\Backend;
/**
* 系统配置
*
* @icon fa fa-circle-o
*/
class Config extends Backend
{
protected $model = null;
protected $noNeedRight = ['check'];
public function _initialize()
{
parent::_initialize();
$this->model = model('Config');
}
public function index()
{
$siteList = [];
$groupList = \app\admin\model\Config::getGroupList();
foreach ($groupList as $k => $v)
{
$siteList[$k]['name'] = $k;
$siteList[$k]['title'] = $v;
$siteList[$k]['list'] = [];
}
foreach ($this->model->all() as $k => $v)
{
if (!isset($siteList[$v['group']]))
{
continue;
}
$value = $v->toArray();
if (in_array($value['type'], ['select', 'selects', 'checkbox', 'radio']))
{
$value['value'] = explode(',', $value['value']);
}
if ($value['type'] == 'array')
{
$value['value'] = (array) json_decode($value['value'], TRUE);
}
$value['content'] = json_decode($value['content'], TRUE);
$siteList[$v['group']]['list'][] = $value;
}
$index = 0;
foreach ($siteList as $k => &$v)
{
$v['active'] = !$index ? true : false;
$index++;
}
$this->view->assign('siteList', $siteList);
$this->view->assign('typeList', \app\admin\model\Config::getTypeList());
$this->view->assign('groupList', \app\admin\model\Config::getGroupList());
return $this->view->fetch();
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost())
{
$this->code = -1;
$params = $this->request->post("row/a");
if ($params)
{
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
try
{
if ($params['content'] && in_array($params['type'], ['select', 'selects', 'checkbox', 'radio']))
{
$content = explode("\r\n", $params['content']);
$arr = [];
foreach ($content as $k => &$v)
{
if (stripos($v, "|") !== false)
{
$item = explode('|', $v);
$arr[$item[0]] = $item[1];
}
}
$params['content'] = $arr ? json_encode($arr, JSON_UNESCAPED_UNICODE) : '';
}
else
{
$params['content'] = '';
}
$result = $this->model->create($params);
if ($result !== false)
{
try
{
$this->refreshFile();
$this->code = 1;
}
catch (Exception $e)
{
$this->msg = $e->getMessage();
}
}
else
{
$this->msg = $this->model->getError();
}
}
catch (think\Exception $e)
{
$this->msg = $e->getMessage();
}
}
else
{
$this->msg = __('Parameter %s can not be empty', '');
}
return;
}
return $this->view->fetch();
}
public function edit($ids = NULL)
{
$this->code = -1;
if ($this->request->isPost())
{
$params = $this->request->post("row/a");
if ($params)
{
$configList = [];
foreach ($this->model->all() as $k => $v)
{
if (isset($params[$v['name']]))
{
if ($v['type'] == 'array')
{
$fieldarr = $valuearr = [];
$field = $params[$v['name']]['field'];
$value = $params[$v['name']]['value'];
foreach ($field as $m => $n)
{
if ($n != '')
{
$fieldarr[] = $field[$m];
$valuearr[] = $value[$m];
}
}
$params[$v['name']] = array_combine($fieldarr, $valuearr);
$value = json_encode($params[$v['name']], JSON_UNESCAPED_UNICODE);
}
else
{
$value = is_array($params[$v['name']]) ? implode(',', $params[$v['name']]) : $params[$v['name']];
}
$configList[] = ['id' => $v['id'], 'value' => $value];
}
}
$this->model->saveAll($configList);
try
{
$this->refreshFile();
$this->code = 1;
}
catch (Exception $e)
{
$this->msg = $e->getMessage();
}
}
else
{
$this->msg = __('Parameter %s can not be empty', '');
}
return;
}
}
protected function refreshFile()
{
$config = [];
foreach ($this->model->all() as $k => $v)
{
$value = $v->toArray();
if (in_array($value['type'], ['selects', 'checkbox', 'images', 'files']))
{
$value['value'] = explode(',', $value['value']);
}
if ($value['type'] == 'array')
{
$value['value'] = (array) json_decode($value['value'], TRUE);
}
$config[$value['name']] = $value['value'];
}
file_put_contents(APP_PATH . 'extra' . DS . 'site.php', '<?php' . "\n\nreturn " . var_export($config, true) . ";");
}
/**
* @internal
*/
public function check()
{
$params = $this->request->post("row/a");
if ($params)
{
$config = $this->model->get($params);
if (!$config)
{
return json(['ok' => '']);
}
else
{
return json(['error' => __('Name already exist')]);
}
}
else
{
return json(['error' => __('Invalid parameters')]);
}
}
}

View File

@ -9,6 +9,7 @@ use app\common\controller\Backend;
*
* @icon fa fa-cog
* @remark 用于管理一些字典数据,通常以键值格式进行录入,保存的数据格式为JSON
* @internal
*/
class Configvalue extends Backend
{

View File

@ -3,45 +3,23 @@
namespace app\admin\controller\wechat;
use app\common\controller\Backend;
use app\common\model\Configvalue;
use think\Controller;
use think\Request;
/**
* 配置管理
* 微信配置管理
*
* @icon fa fa-list-alt
* @icon fa fa-circle-o
*/
class Config extends Backend
{
protected $wechatcfg = NULL;
protected $obj = [];
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->wechatcfg = Configvalue::get('wechat');
$this->obj = $this->wechatcfg->content;
}
/**
* 查看
*/
public function index()
{
if ($this->request->isAjax())
{
$configlist = isset($this->obj['config']) ? $this->obj['config'] : [];
$list = array();
foreach ($configlist as $row)
{
$list[] = $row;
}
$total = count($list);
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
$this->model = model('WechatConfig');
}
/**
@ -51,10 +29,61 @@ class Config extends Backend
{
if ($this->request->isPost())
{
$this->obj['config'][] = $this->request->post('row/a');
$this->wechatcfg->content = $this->obj;
$this->wechatcfg->save();
$this->code = -1;
$params = $this->request->post("row/a");
if ($params)
{
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
if ($params['mode'] == 'json')
{
//JSON字段
$fieldarr = $valuearr = [];
$field = $this->request->post('field/a');
$value = $this->request->post('value/a');
foreach ($field as $k => $v)
{
if ($v != '')
{
$fieldarr[] = $field[$k];
$valuearr[] = $value[$k];
}
}
$params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE);
}
unset($params['mode']);
try
{
//是否采用模型验证
if ($this->modelValidate)
{
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->model->validate($validate);
}
$result = $this->model->save($params);
if ($result !== false)
{
$this->code = 1;
}
else
{
$this->msg = $this->model->getError();
}
}
catch (\think\exception\PDOException $e)
{
$this->msg = $e->getMessage();
}
}
else
{
$this->msg = __('Parameter %s can not be empty', '');
}
return;
}
return $this->view->fetch();
@ -65,63 +94,71 @@ class Config extends Backend
*/
public function edit($ids = NULL)
{
$row = [];
foreach ($this->obj['config'] as $k => $v)
{
if ($v['id'] == $ids)
{
$row = $v;
break;
}
}
$row = $this->model->get($ids);
if (!$row)
$this->error(__('No Results were found'));
if ($this->request->isPost())
{
$params = $this->request->post('row/a');
$this->obj['config'][$k] = $params;
$this->obj['config'] = array_values($this->obj['config']);
$this->wechatcfg->content = $this->obj;
$this->wechatcfg->save();
$this->code = -1;
$params = $this->request->post("row/a");
if ($params)
{
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
if ($params['mode'] == 'json')
{
//JSON字段
$fieldarr = $valuearr = [];
$field = $this->request->post('field/a');
$value = $this->request->post('value/a');
foreach ($field as $k => $v)
{
if ($v != '')
{
$fieldarr[] = $field[$k];
$valuearr[] = $value[$k];
}
}
$params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE);
}
unset($params['mode']);
try
{
//是否采用模型验证
if ($this->modelValidate)
{
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$row->validate($validate);
}
$result = $row->save($params);
if ($result !== false)
{
$this->code = 1;
}
else
{
$this->msg = $row->getError();
}
}
catch (think\exception\PDOException $e)
{
$this->msg = $e->getMessage();
}
}
else
{
$this->msg = __('Parameter %s can not be empty', '');
}
return;
}
$this->view->assign("row", $row);
$this->view->assign("value", (array) json_decode($row->value, true));
return $this->view->fetch();
}
/**
* 删除
*/
public function del($ids = "")
{
$this->code = -1;
if ($ids)
{
$ids = is_array($ids) ? $ids : explode(',', $ids);
foreach ($this->obj['config'] as $k => $v)
{
if (in_array($v['id'], $ids))
{
unset($this->obj['config'][$k]);
}
}
$this->wechatcfg->content = $this->obj;
$this->wechatcfg->save();
$this->code = 1;
}
return;
}
/**
* 批量更新
*/
public function multi($ids = "")
{
$this->code = -1;
//不支持指操作
return;
}
}

View File

@ -22,7 +22,7 @@ class Menu extends Backend
public function _initialize()
{
parent::_initialize();
$this->wechatcfg = Configvalue::get('wechat');
$this->wechatcfg = \app\common\model\WechatConfig::get(['name' => 'menu']);
}
/**
@ -37,7 +37,7 @@ class Menu extends Backend
$responselist[$v['eventkey']] = $v['title'];
}
$this->view->assign('responselist', $responselist);
$this->view->assign('menu', $this->wechatcfg->content['menu']);
$this->view->assign('menu', (array) json_decode($this->wechatcfg->value, TRUE));
return $this->view->fetch();
}
@ -48,9 +48,7 @@ class Menu extends Backend
{
$menu = $this->request->post("menu");
$menu = (array) json_decode($menu, TRUE);
$content = $this->wechatcfg->content;
$content['menu'] = $menu;
$this->wechatcfg->content = $content;
$this->wechatcfg->value = json_encode($menu, JSON_UNESCAPED_UNICODE);
$this->wechatcfg->save();
$this->code = 1;
return;
@ -66,7 +64,7 @@ class Menu extends Backend
try
{
$ret = $app->menu->add($this->wechatcfg->content['menu']);
$ret = $app->menu->add(json_decode($this->wechatcfg->value, TRUE));
if ($ret->errcode == 0)
{
$this->code = 1;

View File

@ -86,7 +86,8 @@ return [
'Network error' => '网络错误!',
'Auth manager' => '权限管理',
'General manager' => '常规管理',
'Example manager' => '测试管理',
'Example manager' => '示例管理',
'Wechat manager' => '微信管理',
'Common search' => '普通搜索',
'Search %s' => '搜索 %s',
'%d second%s ago' => '%d秒前',

View File

@ -0,0 +1,9 @@
<?php
return [
'name' => '变量名称',
'intro' => '描述',
'group' => '分组',
'type' => '类型',
'value' => '变量值'
];

View File

@ -6,8 +6,9 @@ return [
'Imageheight' => '宽度',
'Imagetype' => '图片类型',
'Imageframes' => '图片帧数',
'Preview' => '预览',
'Filesize' => '文件大小',
'Mimetype' => 'mime类型',
'Mimetype' => 'Mime类型',
'Extparam' => '透传数据',
'Createtime' => '创建日期',
'Uploadtime' => '上传时间',

View File

@ -0,0 +1,36 @@
<?php
return [
'Name' => '变量名',
'Tip' => '提示信息',
'Group' => '分组',
'Type' => '类型',
'Title' => '变量标题',
'Value' => '变量值',
'Basic' => '基础配置',
'Email' => '邮件配置',
'Attachment' => '附件配置',
'User' => '会员配置',
'Example' => '示例分组',
'Extend' => '扩展属性',
'String' => '字符',
'Text' => '文本',
'Number' => '数字',
'Date' => '日期',
'Time' => '时间',
'Datetime' => '日期时间',
'Image' => '图片',
'Images' => '图片(多)',
'File' => '文件',
'Files' => '文件(多)',
'Select' => '列表',
'Selects' => '列表(多选)',
'Checkbox' => '复选',
'Radio' => '单选',
'Array' => '数组',
'Array key' => '键名',
'Array value' => '键值',
'Content' => '数据列表',
'Rule' => '校验规则',
'Name already exist' => '变量名称已经存在',
];

View File

@ -0,0 +1,10 @@
<?php
return [
'name' => '配置名称',
'value' => '配置值',
'Json key' => '键',
'Json value' => '值',
'createtime' => '创建时间',
'updatetime' => '更新时间'
];

View File

@ -235,7 +235,7 @@ class Auth extends \fast\Auth
* @param array $params URL对应的badge数据
* @return string
*/
public function getSidebar($params = [])
public function getSidebar($params = [], $fixedPage = 'dashboard')
{
$colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple'];
$colorNums = count($colorArr);
@ -275,7 +275,7 @@ class Auth extends \fast\Auth
// 读取管理员当前拥有的权限节点
$userRule = $this->getRuleList();
$select_id = 0;
$dashboard = '/' . $module . '/dashboard';
$activeUrl = '/' . $module . '/' . $fixedPage;
// 必须将结果集转换为数组
$ruleList = collection(model('AuthRule')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
foreach ($ruleList as $k => &$v)
@ -285,7 +285,7 @@ class Auth extends \fast\Auth
unset($ruleList[$k]);
continue;
}
$select_id = $v['name'] == $dashboard ? $v['id'] : $select_id;
$select_id = $v['name'] == $activeUrl ? $v['id'] : $select_id;
$v['url'] = $v['name'];
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
}

View File

@ -48,7 +48,14 @@ trait Backend
}
try
{
$result = $this->model->create($params);
//是否采用模型验证
if ($this->modelValidate)
{
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->model->validate($validate);
}
$result = $this->model->save($params);
if ($result !== false)
{
$this->code = 1;
@ -58,7 +65,7 @@ trait Backend
$this->msg = $this->model->getError();
}
}
catch (think\Exception $e)
catch (\think\exception\PDOException $e)
{
$this->msg = $e->getMessage();
}
@ -93,6 +100,13 @@ trait Backend
}
try
{
//是否采用模型验证
if ($this->modelValidate)
{
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$row->validate($validate);
}
$result = $row->save($params);
if ($result !== false)
{
@ -103,7 +117,7 @@ trait Backend
$this->msg = $row->getError();
}
}
catch (think\Exception $e)
catch (think\exception\PDOException $e)
{
$this->msg = $e->getMessage();
}

View File

@ -0,0 +1,55 @@
<?php
namespace app\admin\model;
use think\Model;
class Config extends Model
{
// 表名,不含前缀
protected $name = 'config';
// 自动写入时间戳字段
protected $autoWriteTimestamp = false;
// 定义时间戳字段名
protected $createTime = false;
protected $updateTime = false;
// 追加属性
protected $append = [
];
/**
* 读取配置类型
* @return array
*/
public static function getTypeList()
{
$typeList = [
'string' => __('String'),
'text' => __('Text'),
'number' => __('Number'),
'datetime' => __('Datetime'),
'select' => __('Select'),
'selects' => __('Selects'),
'image' => __('Image'),
'images' => __('Images'),
'file' => __('File'),
'files' => __('Files'),
'checkbox' => __('Checkbox'),
'radio' => __('Radio'),
'array' => __('Array'),
];
return $typeList;
}
/**
* 读取分类分组列表
* @return array
*/
public static function getGroupList()
{
$groupList = config('site.configgroup');
return $groupList;
}
}

View File

@ -0,0 +1,207 @@
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<div class="panel-lead"><em>系统配置</em>可以在此增改系统的变量和分组,也可以自定义分组和变量,如果需要删除请从数据库中删除</div>
<ul class="nav nav-tabs">
{foreach $siteList as $index=>$vo}
<li class="{$vo.active?'active':''}"><a href="#{$vo.name}" data-toggle="tab">{$vo.title}</a></li>
{/foreach}
<li>
<a href="#addcfg" data-toggle="tab"><i class="fa fa-plus"></i></a>
</li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
{foreach $siteList as $index=>$vo}
<div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="{$vo.name}">
<div class="widget-body no-padding">
<form id="{$vo.name}-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/edit')}">
<table class="table table-striped">
<thead>
<tr>
<th width="15%">{:__('Title')}</th>
<th width="70%">{:__('Value')}</th>
<th width="15%">{:__('Name')}</th>
</tr>
</thead>
<tbody>
{foreach $vo.list as $item}
<tr>
<td>{$item.title}</td>
<td>
<div class="row">
<div class="col-sm-8 col-xs-12">
{switch $item.type}
{case string}
<input type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}" {$item.extend} />
{/case}
{case text}
<textarea name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}" {$item.extend}>{$item.value}</textarea>
{/case}
{case array}
<dl class="fieldlist" rel="{$item.value|count}" data-name="row[{$item.name}]">
<dd>
<ins>{:__('Array key')}</ins>
<ins>{:__('Array value')}</ins>
</dd>
{foreach $item.value as $key => $vo}
<dd class="form-inline">
<input type="text" name="row[{$item.name}][field][{$key}]" class="form-control" value="{$key}" size="10" />
<input type="text" name="row[{$item.name}][value][{$key}]" class="form-control" value="{$vo}" size="40" />
<span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
<span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
</dd>
{/foreach}
<dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
</dl>
{/case}
{case datetime}
<input type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-tip="{$item.tip}" data-rule="{$item.rule}" {$item.extend} />
{/case}
{case number}
<input type="number" name="row[{$item.name}]" value="{$item.value}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}" {$item.extend} />
{/case}
{case checkbox}
{foreach name="item.content" item="vo"}
<label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value"}checked{/in} /> {$vo}</label>
{/foreach}
{/case}
{case radio}
{foreach name="item.content" item="vo"}
<label for="row[{$item.name}]-{$key}"><input id="row[{$item.name}]-{$key}" name="row[{$item.name}]" type="radio" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value"}checked{/in} /> {$vo}</label>
{/foreach}
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
<select name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
{foreach name="item.content" item="vo"}
<option value="{$key}" {in name="key" value="$item.value"}selected{/in}>{$vo}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="form-inline">
<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>
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
</div>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="form-inline">
<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>
</div>
{/case}
{case bool}
<label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
<label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
{/case}
{/switch}
</div>
<div class="col-sm-4"></div>
</div>
</td>
<td>{php}echo "{\$site.". $item['name'] . "}";{/php}</td>
</tr>
{/foreach}
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</td>
<td></td>
</tr>
</tfoot>
</table>
</form>
</div>
</div>
{/foreach}
<div class="tab-pane fade" id="addcfg">
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/add')}">
<div class="form-group">
<label for="type" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[type]" class="form-control selectpicker">
{foreach name="typeList" item="vo"}
<option value="{$key}" {in name="key" value="string"}selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="group" class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[group]" class="form-control selectpicker">
{foreach name="groupList" item="vo"}
<option value="{$key}" {in name="key" value="basic"}selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required; length(3~30); remote(general/config/check)" />
</div>
</div>
<div class="form-group">
<label for="title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required" />
</div>
</div>
<div class="form-group">
<label for="value" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="value" name="row[value]" value="" data-rule="" />
</div>
</div>
<div class="form-group hide" id="add-content-container">
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-4">
<textarea name="row[content]" id="content" cols="30" rows="5" class="form-control" data-rule="required">key1|value1
key2|value2</textarea>
</div>
</div>
<div class="form-group">
<label for="tip" class="control-label col-xs-12 col-sm-2">{:__('Tip')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="tip" name="row[tip]" value="" data-rule="" />
</div>
</div>
<div class="form-group">
<label for="rule" class="control-label col-xs-12 col-sm-2">{:__('Rule')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="rule" name="row[rule]" value="" />
</div>
</div>
<div class="form-group">
<label for="extend" class="control-label col-xs-12 col-sm-2">{:__('Extend')}:</label>
<div class="col-xs-12 col-sm-4">
<textarea name="row[extend]" id="extend" cols="30" rows="5" class="form-control" data-rule=""></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-4">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>

View File

@ -1,9 +1,3 @@
<style type="text/css">
#fieldlist dd {display:block;margin:5px 0;}
#fieldlist dd input{display: inline-block;width:300px;}
#fieldlist dd input:first-child{width:110px;}
#fieldlist dd ins{width:110px;display: inline-block;text-decoration:none;font-weight: bold;}
</style>
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">ID:</label>
@ -20,7 +14,7 @@
<div class="form-group">
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<dl id="fieldlist" rel="1">
<dl class="fieldlist" rel="1">
<dd>
<ins>{:__('Key')}</ins>
<ins>{:__('Value')}</ins>

View File

@ -1,9 +1,3 @@
<style type="text/css">
#fieldlist dd {display:block;margin:5px 0;}
#fieldlist dd input{display: inline-block;width:300px;}
#fieldlist dd input:first-child{width:110px;}
#fieldlist dd ins{width:110px;display: inline-block;text-decoration:none;font-weight: bold;}
</style>
<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">ID:</label>
@ -20,7 +14,7 @@
<div class="form-group">
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<dl id="fieldlist" rel="{$row.content|count}">
<dl class="fieldlist" rel="{$row.content|count}">
<dd>
<ins>{:__('Key')}</ins>
<ins>{:__('Value')}</ins>

View File

@ -1,154 +0,0 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="c-category_id" class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_category_select('row[category_id]', 'test', '0', ['id' => 'c-category_id'])}
</div>
</div>
<div class="form-group">
<label for="c-category_ids" class="control-label col-xs-12 col-sm-2">{:__('Category_ids')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_category_select('row[category_ids]', 'test', '', ['id' => 'c-category_ids','required' => '','multiple' => ''])}
</div>
</div>
<div class="form-group">
<label for="c-user_id" class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-user_id" class="form-control typeahead" name="row[user_id]" type="number" value="0">
</div>
</div>
<div class="form-group">
<label for="c-user_ids" class="control-label col-xs-12 col-sm-2">{:__('User_ids')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-user_ids" required="" class="form-control tagsinput" name="row[user_ids]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-week" class="control-label col-xs-12 col-sm-2">{:__('Week')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[week]', ['monday' => __('Monday'),'tuesday' => __('Tuesday'),'wednesday' => __('Wednesday')], '', ['id' => 'c-week','required' => '','class' => 'form-control selectpicker'])}
</div>
</div>
<div class="form-group">
<label for="c-flag" class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[flag][]', ['hot' => __('Hot'),'index' => __('Index'),'recommend' => __('Recommend')], '', ['id' => 'c-flag','required' => '','class' => 'form-control selectpicker','multiple' => ''])}
</div>
</div>
<div class="form-group">
<label for="c-genderdata" class="control-label col-xs-12 col-sm-2">{:__('Genderdata')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[genderdata]', ['male' => __('Male'),'female' => __('Female')], 'male')}
</div>
</div>
<div class="form-group">
<label for="c-hobbydata" class="control-label col-xs-12 col-sm-2">{:__('Hobbydata')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_checkboxs('row[hobbydata][]', ['music' => __('Music'),'reading' => __('Reading'),'swimming' => __('Swimming')], '')}
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-title" required="" class="form-control" name="row[title]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-content" required="" class="form-control summernote" rows="5" name="row[content]" cols="50"></textarea>
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="form-inline">
<input id="c-image" required="" class="form-control" size="50" name="row[image]" type="text" value="">
<span><button id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image"data-mimetype="image/*"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-attachfile" class="control-label col-xs-12 col-sm-2">{:__('Attachfile')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="form-inline">
<input id="c-attachfile" required="" class="form-control" size="50" name="row[attachfile]" type="text" value="">
<span><button id="plupload-attachfile" class="btn btn-danger plupload" data-input-id="c-attachfile"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-keywords" required="" class="form-control" name="row[keywords]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-description" class="control-label col-xs-12 col-sm-2">{:__('Description')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-description" required="" class="form-control " rows="5" name="row[description]" cols="50"></textarea>
</div>
</div>
<div class="form-group">
<label for="c-price" class="control-label col-xs-12 col-sm-2">{:__('Price')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-price" class="form-control" step="0.01" name="row[price]" type="number" value="0.00">
</div>
</div>
<div class="form-group">
<label for="c-views" class="control-label col-xs-12 col-sm-2">{:__('Views')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-views" class="form-control" name="row[views]" type="number" value="0">
</div>
</div>
<div class="form-group">
<label for="c-startdate" class="control-label col-xs-12 col-sm-2">{:__('Startdate')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-startdate" required="" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-use-current="true" name="row[startdate]" type="text" value="{:date('Y-m-d')}">
</div>
</div>
<div class="form-group">
<label for="c-activitydate" class="control-label col-xs-12 col-sm-2">{:__('Activitydate')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-activitydate" required="" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[activitydate]" type="text" value="{:date('Y-m-d H:i:s')}">
</div>
</div>
<div class="form-group">
<label for="c-year" class="control-label col-xs-12 col-sm-2">{:__('Year')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-year" required="" class="form-control datetimepicker" data-date-format="YYYY" data-use-current="true" name="row[year]" type="text" value="{:date('Y')}">
</div>
</div>
<div class="form-group">
<label for="c-times" class="control-label col-xs-12 col-sm-2">{:__('Times')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-times" required="" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-use-current="true" name="row[times]" type="text" value="{:date('H:i:s')}">
</div>
</div>
<div class="form-group">
<label for="c-refreshtime" class="control-label col-xs-12 col-sm-2">{:__('Refreshtime')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-refreshtime" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[refreshtime]" type="text" value="{:date('Y-m-d H:i:s')}">
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="0">
</div>
</div>
<div class="form-group">
<label for="c-status" 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')], 'normal')}
</div>
</div>
<div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@ -1,154 +0,0 @@
<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="c-category_id" class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_category_select('row[category_id]', 'test', $row.category_id, ['id' => 'c-category_id'])}
</div>
</div>
<div class="form-group">
<label for="c-category_ids" class="control-label col-xs-12 col-sm-2">{:__('Category_ids')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_category_select('row[category_ids]', 'test', $row.category_ids, ['id' => 'c-category_ids','required' => '','multiple' => ''])}
</div>
</div>
<div class="form-group">
<label for="c-user_id" class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-user_id" class="form-control typeahead" name="row[user_id]" type="number" value="{$row.user_id}">
</div>
</div>
<div class="form-group">
<label for="c-user_ids" class="control-label col-xs-12 col-sm-2">{:__('User_ids')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-user_ids" required="" class="form-control tagsinput" name="row[user_ids]" type="text" value="{$row.user_ids}">
</div>
</div>
<div class="form-group">
<label for="c-week" class="control-label col-xs-12 col-sm-2">{:__('Week')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[week]', ['monday' => __('Monday'),'tuesday' => __('Tuesday'),'wednesday' => __('Wednesday')], $row.week, ['id' => 'c-week','required' => '','class' => 'form-control selectpicker'])}
</div>
</div>
<div class="form-group">
<label for="c-flag" class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[flag][]', ['hot' => __('Hot'),'index' => __('Index'),'recommend' => __('Recommend')], $row.flag, ['id' => 'c-flag','required' => '','class' => 'form-control selectpicker','multiple' => ''])}
</div>
</div>
<div class="form-group">
<label for="c-genderdata" class="control-label col-xs-12 col-sm-2">{:__('Genderdata')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[genderdata]', ['male' => __('Male'),'female' => __('Female')], $row.genderdata)}
</div>
</div>
<div class="form-group">
<label for="c-hobbydata" class="control-label col-xs-12 col-sm-2">{:__('Hobbydata')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_checkboxs('row[hobbydata][]', ['music' => __('Music'),'reading' => __('Reading'),'swimming' => __('Swimming')], $row.hobbydata)}
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-title" required="" class="form-control" name="row[title]" type="text" value="{$row.title}">
</div>
</div>
<div class="form-group">
<label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-content" required="" class="form-control summernote" rows="5" name="row[content]" cols="50">{$row.content}</textarea>
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="form-inline">
<input id="c-image" required="" class="form-control" size="50" name="row[image]" type="text" value="{$row.image}">
<span><button id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image"data-mimetype="image/*"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-attachfile" class="control-label col-xs-12 col-sm-2">{:__('Attachfile')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="form-inline">
<input id="c-attachfile" required="" class="form-control" size="50" name="row[attachfile]" type="text" value="{$row.attachfile}">
<span><button id="plupload-attachfile" class="btn btn-danger plupload" data-input-id="c-attachfile"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-keywords" required="" class="form-control" name="row[keywords]" type="text" value="{$row.keywords}">
</div>
</div>
<div class="form-group">
<label for="c-description" class="control-label col-xs-12 col-sm-2">{:__('Description')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-description" required="" class="form-control " rows="5" name="row[description]" cols="50">{$row.description}</textarea>
</div>
</div>
<div class="form-group">
<label for="c-price" class="control-label col-xs-12 col-sm-2">{:__('Price')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-price" class="form-control" step="0.01" name="row[price]" type="number" value="{$row.price}">
</div>
</div>
<div class="form-group">
<label for="c-views" class="control-label col-xs-12 col-sm-2">{:__('Views')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-views" class="form-control" name="row[views]" type="number" value="{$row.views}">
</div>
</div>
<div class="form-group">
<label for="c-startdate" class="control-label col-xs-12 col-sm-2">{:__('Startdate')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-startdate" required="" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-use-current="true" name="row[startdate]" type="text" value="{$row.startdate}">
</div>
</div>
<div class="form-group">
<label for="c-activitydate" class="control-label col-xs-12 col-sm-2">{:__('Activitydate')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-activitydate" required="" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[activitydate]" type="text" value="{$row.activitydate}">
</div>
</div>
<div class="form-group">
<label for="c-year" class="control-label col-xs-12 col-sm-2">{:__('Year')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-year" required="" class="form-control datetimepicker" data-date-format="YYYY" data-use-current="true" name="row[year]" type="text" value="{$row.year}">
</div>
</div>
<div class="form-group">
<label for="c-times" class="control-label col-xs-12 col-sm-2">{:__('Times')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-times" required="" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-use-current="true" name="row[times]" type="text" value="{$row.times}">
</div>
</div>
<div class="form-group">
<label for="c-refreshtime" class="control-label col-xs-12 col-sm-2">{:__('Refreshtime')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-refreshtime" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-use-current="true" name="row[refreshtime]" type="text" value="{$row.refreshtime|datetime}">
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh}">
</div>
</div>
<div class="form-group">
<label for="c-status" 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>
</div>
<div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@ -1,25 +0,0 @@
<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()}
<div class="dropdown btn-group">
<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">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<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>
</div>
<table id="table" class="table table-striped table-bordered table-hover" width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,25 +1,42 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<input type="hidden" name="row[mode]" value="textarea" />
<div class="form-group">
<label for="module" class="control-label col-xs-12 col-sm-2">{:__('Id')}:</label>
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="id" name="row[id]" value="" pattern="[A-Za-z0-9_\.]{3,}" data-rule="required" />
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="controller" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required" />
<input id="c-title" data-rule="required" class="form-control" name="row[title]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="action" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<label for="c-value" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="value" name="row[value]" data-rule="required"></textarea>
<a href="javascript:;" class="btn-insertlink">{:__('Insert link')}</a>
<p>
<a href="javascript:;" class="btn btn-info btn-jsoneditor"><i class="fa fa-pencil"></i> {:__('Json editor')}</a>
<a href="javascript:;" class="btn btn-primary btn-insertlink"><i class="fa fa-link"></i> {:__('Insert link')}</a>
</p>
<textarea id="c-value" class="form-control " rows="15" name="row[value]"></textarea>
<dl class="fieldlist hide" rel="1">
<dd>
<ins>{:__('Json key')}</ins>
<ins>{:__('Json value')}</ins>
</dd>
<dd>
<input type="text" name="field[0]" class="form-control" id="field-0" value="" size="10" required />
<input type="text" name="value[0]" class="form-control" id="value-0" value="" size="40" required />
<span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
<span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
</dd>
<dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
</dl>
</div>
</div>
<div class="form-group hidden layer-footer">
<div class="col-xs-2"></div>
<div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>

View File

@ -1,25 +1,44 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<input type="hidden" name="row[mode]" value="textarea" />
<div class="form-group">
<label for="module" class="control-label col-xs-12 col-sm-2">{:__('Id')}:</label>
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="id" name="row[id]" value="{$row.id}" pattern="[A-Za-z0-9_\.]{3,}" data-rule="required" />
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name}">
</div>
</div>
<div class="form-group">
<label for="controller" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" data-rule="required" />
<input id="c-title" data-rule="required" class="form-control" name="row[title]" type="text" value="{$row.title}">
</div>
</div>
<div class="form-group">
<label for="action" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<label for="c-value" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="value" name="row[value]" data-rule="required">{$row.value}</textarea>
<a href="javascript:;" class="btn-insertlink">{:__('Insert link')}</a>
<p>
<a href="javascript:;" class="btn btn-info btn-jsoneditor"><i class="fa fa-pencil"></i> {:__('Json editor')}</a>
<a href="javascript:;" class="btn btn-primary btn-insertlink"><i class="fa fa-link"></i> {:__('Insert link')}</a>
</p>
<textarea id="c-value" class="form-control " rows="15" name="row[value]">{$row.value}</textarea>
<dl class="fieldlist hide" rel="{$value|count}">
<dd>
<ins>{:__('Json key')}</ins>
<ins>{:__('Json value')}</ins>
</dd>
{foreach $value as $key => $vo}
<dd class="form-inline">
<input type="text" name="field[{$key}]" class="form-control" id="field-{$key}" value="{$key}" size="10" />
<input type="text" name="value[{$key}]" class="form-control" id="value-{$key}" value="{$vo}" size="40" />
<span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
<span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
</dd>
{/foreach}
<dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
</dl>
</div>
</div>
<div class="form-group hidden layer-footer">
<div class="col-xs-2"></div>
<div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>

View File

@ -7,9 +7,15 @@
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar()}
<div class="dropdown btn-group">
<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">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<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>
<table id="table" class="table table-bordered table-hover" width="100%">
</div>
<table id="table" class="table table-striped table-bordered table-hover" width="100%">
</table>
</div>
</div>

View File

@ -69,6 +69,16 @@ class Backend extends Controller
*/
protected $relationSearch = false;
/**
* 是否开启Validate验证
*/
protected $modelValidate = false;
/**
* 是否开启模型场景验证
*/
protected $modelSceneValidate = false;
/**
* 引入后台控制器的traits
*/
@ -140,9 +150,11 @@ class Backend extends Controller
// 语言检测
$lang = Lang::detect();
$site = Config::get("site");
// 配置信息
$config = [
'site' => Config::get("site"),
'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),
'upload' => Configvalue::upload(),
'modulename' => $modulename,
'controllername' => $controllername,
@ -155,7 +167,7 @@ class Backend extends Controller
Lang::load(APP_PATH . $modulename . '/lang/' . $lang . '/' . str_replace('.', '/', $controllername) . '.php');
$this->assign('site', Config::get("site"));
$this->assign('site', $site);
$this->assign('config', $config);
$this->assign('admin', Session::get('admin'));
@ -182,16 +194,6 @@ class Backend extends Controller
$op = json_decode($op, TRUE);
$filter = $filter ? $filter : [];
$where = [];
if ($search)
{
$searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields);
$searchlist = [];
foreach ($searcharr as $k => $v)
{
$searchlist[] = "`{$v}` LIKE '%{$search}%'";
}
$where[] = "(" . implode(' OR ', $searchlist) . ")";
}
$modelName = '';
if ($relationSearch)
{
@ -207,6 +209,16 @@ class Backend extends Controller
$sort = $modelName . $sort;
}
}
if ($search)
{
$searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields);
$searchlist = [];
foreach ($searcharr as $k => $v)
{
$searchlist[] = "{$modelName}`{$v}` LIKE '%{$search}%'";
}
$where[] = "(" . implode(' OR ', $searchlist) . ")";
}
foreach ($filter as $k => $v)
{
$sym = isset($op[$k]) ? $op[$k] : '=';

View File

@ -25,11 +25,7 @@ class Category Extends Model
*/
public static function getTypeList()
{
$typelist = [
'default' => __('Default'),
'page' => __('Page'),
'article' => __('Article'),
];
$typelist = config('site', 'categorytype');
return $typelist;
}

View File

@ -0,0 +1,32 @@
<?php
namespace app\common\model;
use think\Model;
class WechatConfig extends Model
{
// 表名,不含前缀
public $name = 'wechat_config';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
];
/**
* 读取指定配置名称的值
* @param string $name
* @return string
*/
public static function value($name)
{
$item = self::get(['name' => $name]);
return $item ? $item->value : '';
}
}

View File

@ -1,35 +1,31 @@
<?php
//站点配置
return [
/**
* 站点名称
*/
return array (
'name' => 'FastAdmin',
/**
* 备案号
*/
'beian' => '',
/**
* CDN地址,建议使用upload中配置的cdnurl
*/
'cdnurl' => '',
/**
* 版本号
*/
'version' => '1.0.1',
/**
* 时区
*/
'timezone' => 'Asia/Shanghai',
/**
* 禁止访问的IP
*/
'forbiddenip' => '',
/**
* 模块语言
*/
'languages' => [
'languages' =>
array (
'backend' => 'zh-cn',
],
];
'frontend' => 'zh-cn',
),
'fixedpage' => 'dashboard',
'categorytype' =>
array (
'default' => '默认',
'page' => '单页',
'article' => '文章',
'test' => '测试',
),
'configgroup' =>
array (
'basic' => '基础配置',
'email' => '邮件配置',
'dictionary' => '字典配置',
'user' => '会员配置',
'example' => '示例分组',
),
);

View File

@ -6,6 +6,7 @@ use app\common\controller\Frontend;
use app\common\model\WechatAutoreply;
use app\common\model\WechatContext;
use app\common\model\WechatResponse;
use app\common\model\WechatConfig;
use EasyWeChat\Foundation\Application;
use EasyWeChat\Payment\Order;
use fast\service\Wechat as WechatService;
@ -31,15 +32,7 @@ class Wechat extends Frontend
*/
public function api()
{
$this->app->server->setMessageHandler(function ($message)
{
$content = configvalue('wechat');
//微信配置信息
$wechat_config = [];
foreach ($content['config'] as $k => $v)
{
$wechat_config[$v['id']] = $v['value'];
}
$this->app->server->setMessageHandler(function ($message) {
$WechatService = new WechatService;
$WechatContext = new WechatContext;
@ -50,7 +43,8 @@ class Wechat extends Frontend
$event = $message->Event;
$eventkey = $message->EventKey ? $message->EventKey : $message->Event;
$unknownmessage = isset($wechat_config['default.unknown.message']) ? $wechat_config['default.unknown.message'] : "对找到对应指令!";
$unknownmessage = WechatConfig::value('default.unknown.message');
$unknownmessage = $unknownmessage ? $unknownmessage : "对找到对应指令!";
switch ($message->MsgType)
{
@ -58,7 +52,9 @@ class Wechat extends Frontend
switch ($event)
{
case 'subscribe'://添加关注
return isset($wechat_config['default.subscribe.message']) ? $wechat_config['default.subscribe.message'] : "欢迎关注我们!";
$subscribemessage = WechatConfig::value('default.subscribe.message');
$subscribemessage = $subscribemessage ? $subscribemessage : "欢迎关注我们!";
return $subscribemessage;
case 'unsubscribe'://取消关注
return '';
case 'LOCATION'://获取地理位置
@ -158,8 +154,7 @@ class Wechat extends Frontend
public function notify()
{
Log::record(file_get_contents('php://input'), "notify");
$response = $this->app->payment->handleNotify(function($notify, $successful)
{
$response = $this->app->payment->handleNotify(function($notify, $successful) {
// 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
$orderinfo = Order::findByTransactionId($notify->transaction_id);
if ($orderinfo)

View File

@ -6,6 +6,7 @@ use app\common\model\Page;
use app\common\model\User;
use app\common\model\UserSignin;
use app\common\model\UserThird;
use app\common\model\WechatConfig;
use EasyWeChat\Message\News;
use EasyWeChat\Message\Transfer;
use fast\Date;
@ -73,7 +74,7 @@ class Wechat
case 'page':
break;
case 'service':
$service = configvalue('service');
$service = (array) json_decode(WechatConfig::value('service'), true);
list($begintime, $endtime) = explode('-', $service['onlinetime']);
$session = $obj->app->staff_session;
$staff = $obj->app->staff;
@ -107,8 +108,7 @@ class Wechat
else
{
$server = $obj->app->server;
$server->setMessageHandler(function($message)
{
$server->setMessageHandler(function($message) {
return new Transfer();
});
$response = $server->serve();
@ -154,7 +154,7 @@ class Wechat
}
else
{
$signdata = configvalue('signin');
$signdata = (array) json_decode(WechatConfig::value('signin'), TRUE);
$lastdata = $usersign->where('user_id', $user_id)->order('id', 'desc')->limit(1)->get();
$successions = $lastdata && $lastdata['createtime'] > Date::unixtime('day', -1) ? $lastdata['successions'] + 1 : 1;

View File

@ -55,6 +55,9 @@ body.is-dialog {
.form-group .bootstrap-tagsinput span.twitter-typeahead {
width: auto;
}
.content {
min-height: 500px;
}
#header {
background: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
@ -302,6 +305,23 @@ body.is-dialog {
width: 25px;
height: 25px;
}
.fieldlist dd {
display: block;
margin: 5px 0;
}
.fieldlist dd input {
display: inline-block;
width: 300px;
}
.fieldlist dd input:first-child {
width: 110px;
}
.fieldlist dd ins {
width: 110px;
display: inline-block;
text-decoration: none;
font-weight: bold;
}
#treeview .jstree-container-ul .jstree-node {
display: block;
clear: both;
@ -391,11 +411,14 @@ body.is-dialog {
text-align: left!important;
}
.bootstrap-table .fixed-table-toolbar .dropdown-menu {
overflow: visible;
overflow: auto;
}
.bootstrap-table table tbody tr:first-child td .bs-checkbox {
vertical-align: middle;
}
.bootstrap-table td.bs-checkbox {
vertical-align: middle;
}
.dropdown-submenu {
position: relative;
}

File diff suppressed because one or more lines are too long

View File

@ -67,6 +67,7 @@
float: left;
text-align: center;
width: 33.33%;
list-style: none;
}
.ui-sortable-placeholder{
background-color:#fff;
@ -140,6 +141,7 @@
.sub-menu-list li{
line-height: 44px;
margin: -1px -1px 0;
list-style: none;
}
.sub-menu-box .arrow {
position: absolute;

View File

@ -0,0 +1,93 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'general/config/index',
add_url: 'general/config/add',
edit_url: 'general/config/edit',
del_url: 'general/config/del',
multi_url: 'general/config/multi',
table: 'config',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{field: 'state', checkbox: true},
{field: 'id', title: __('Id')},
{field: 'name', title: __('Name')},
{field: 'intro', title: __('Intro')},
{field: 'group', title: __('Group')},
{field: 'type', title: __('Type')},
{field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
$("form.edit-form").data("validator-options", {
display: function (elem) {
return $(elem).closest('tr').find("td:first").text();
}
});
Form.api.bindevent($("form.edit-form"));
//不可见的元素不验证
$("form#add-form").data("validator-options", {ignore: ':hidden'});
Form.api.bindevent($("form#add-form"), null, function (ret) {
location.reload();
});
$(document).on("click", ".fieldlist .append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
var name = $(this).closest("dl").data("name");
$(this).closest("dl").attr("rel", rel);
$('<dd class="form-inline"><input type="text" name="' + name + '[field][' + rel + ']" class="form-control" value="" size="10" /> <input type="text" name="' + name + '[value][' + rel + ']" class="form-control" value="" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>').insertBefore($(this).parent());
});
$(document).on("click", ".fieldlist dd .btn-remove", function () {
$(this).parent().remove();
});
//拖拽排序
require(['dragsort'], function () {
//绑定拖动排序
$("dl.fieldlist").dragsort({
itemSelector: 'dd',
dragSelector: ".btn-dragsort",
dragEnd: function () {
},
placeHolderTemplate: "<dd></dd>"
});
});
//切换显示隐藏变量字典列表
$(document).on("change", "form#add-form select[name='row[type]']", function (e) {
$("#add-content-container").toggleClass("hide", ['select', 'selects', 'checkbox', 'radio'].indexOf($(this).val()) > -1 ? false : true);
});
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});

View File

@ -57,18 +57,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
},
api: {
bindevent: function () {
$(document).on("click", "#fieldlist .append", function () {
$(document).on("click", ".fieldlist .append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
$(this).closest("dl").attr("rel", rel);
$('<dd class="form-inline"><input type="text" name="field[' + rel + ']" class="form-control" id="field-' + rel + '" value="" size="10" /> <input type="text" name="value[' + rel + ']" class="form-control" id="value-' + rel + '" value="" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>').insertBefore($(this).parent());
});
$(document).on("click", "#fieldlist dd .btn-remove", function () {
$(document).on("click", ".fieldlist dd .btn-remove", function () {
$(this).parent().remove();
});
//拖拽排序
require(['dragsort'], function () {
//绑定拖动排序
$("dl#fieldlist").dragsort({
$("dl.fieldlist").dragsort({
itemSelector: 'dd',
dragSelector: ".btn-dragsort",
dragEnd: function () {

View File

@ -159,11 +159,14 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
$(".tab-addtabs").addClass("ios-iframe-fix");
}
if ($("ul.sidebar-menu li.active a").size() > 0) {
$("ul.sidebar-menu li.active a").trigger("click");
} else {
$("ul.sidebar-menu li a[url!='javascript:;']").trigger("click");
}
if (Config.referer) {
//刷新页面后跳到到刷新前的页面
Backend.api.addtabs(Config.referer);
} else {
$("ul.sidebar-menu li.active a").trigger("click");
}
/**

View File

@ -4,15 +4,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
index: function () {
// 初始化表格参数配置
Table.api.init({
search: true,
advancedSearch: false,
pagination: false,
extend: {
"index_url": "wechat/config/index",
"add_url": "wechat/config/add",
"edit_url": "wechat/config/edit",
"del_url": "wechat/config/del",
"multi_url": "wechat/config/multi",
index_url: 'wechat/config/index',
add_url: 'wechat/config/add',
edit_url: 'wechat/config/edit',
del_url: 'wechat/config/del',
multi_url: 'wechat/config/multi',
table: 'wechat_config',
}
});
@ -21,21 +19,23 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{field: 'state', checkbox: true, },
{field: 'id', title: 'ID'},
{field: 'state', checkbox: true},
{field: 'id', title: __('Id')},
{field: 'name', title: __('Name')},
{field: 'value', title: __('Value')},
{field: 'title', title: __('Title')},
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime},
{field: 'updatetime', title: __('Updatetime'), formatter: Table.api.formatter.datetime},
{field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);//当内容渲染完成后
Table.api.bindevent(table);
},
add: function () {
Controller.api.bindevent();
@ -46,6 +46,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
$(document).on('click', ".btn-jsoneditor", function () {
$("#c-value").toggle();
$(".fieldlist").toggleClass("hide");
$(".btn-insertlink").toggle();
$("input[name='row[mode]']").val($("#c-value").is(":visible") ? "textarea" : "json");
});
$(document).on('click', ".btn-insertlink", function () {
var textarea = $("textarea[name='row[value]']");
var cursorPos = textarea.prop('selectionStart');
@ -63,6 +69,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
});
});
$("input[name='row[type]']:checked").trigger("click");
$(document).on("click", ".fieldlist .append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
$(this).closest("dl").attr("rel", rel);
$('<dd><input type="text" name="field[' + rel + ']" class="form-control" id="field-' + rel + '" value="" size="10" /> <input type="text" name="value[' + rel + ']" class="form-control" id="value-' + rel + '" value="" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>').insertBefore($(this).parent());
});
$(document).on("click", ".fieldlist dd .btn-remove", function () {
$(this).parent().remove();
});
//拖拽排序
require(['dragsort'], function () {
//绑定拖动排序
$("dl.fieldlist").dragsort({
itemSelector: 'dd',
dragSelector: ".btn-dragsort",
dragEnd: function () {
},
placeHolderTemplate: "<dd></dd>"
});
});
}
}
};

View File

@ -7764,7 +7764,7 @@ define('table',['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap
// 添加按钮事件
$(toolbar).on('click', Table.config.addbtn, function () {
var ids = Table.api.selectedids(table);
Backend.api.open(options.extend.add_url + "/ids/" + ids.join(","), __('Add'));
Backend.api.open(options.extend.add_url + "/ids" + (ids.length > 0 ? '/' : '') + ids.join(","), __('Add'));
});
// 编辑按钮事件
$(toolbar).on('click', Table.config.editbtn, function () {
@ -7886,6 +7886,14 @@ define('table',['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap
image: function (value, row, index) {
return '<img class="img-rounded img-sm" src="' + Backend.api.cdnurl(value) + '" />';
},
images: function (value, row, index) {
var arr = value.split(',');
var html = [];
$.each(arr, function (i, value) {
html.push('<img class="img-rounded img-sm" src="' + Backend.api.cdnurl(value) + '" />');
});
return html.join(' ');
},
status: function (value, row, index, custom) {
//颜色状态数组,可使用red/yellow/aqua/blue/navy/teal/olive/lime/fuchsia/purple/maroon
var colorArr = {normal: 'success', hidden: 'grey', deleted: 'danger', locked: 'info'};
@ -7901,7 +7909,7 @@ define('table',['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap
return html;
},
url: function (value, row, index) {
return '<a href="' + value + '" target="_blank" class="label bg-green">' + value + '</a>';
return '<div class="input-group input-group-sm" style="width:250px;"><input type="text" class="form-control input-sm" value="' + value + '"><span class="input-group-btn input-group-sm"><a href="' + value + '" target="_blank" class="btn btn-default btn-sm"><i class="fa fa-link"></i></a></span></div>';
},
search: function (value, row, index) {
return '<a href="javascript:;" class="searchit" data-field="' + this.field + '" data-value="' + value + '">' + value + '</a>';
@ -10971,7 +10979,7 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
var $formitem = $(input).closest('.form-group'),
$msgbox = $formitem.find('span.msg-box');
if (!$msgbox.length) {
$msgbox = $('<span class="msg-box"></span>').insertAfter(input);
return [];
}
return $msgbox;
},
@ -11322,7 +11330,7 @@ $.fn.addtabs = function (options) {
//创建新TAB的title
title = $('<li role="presentation" id="tab_' + id + '"><a href="#' + id + '" node-id="' + opts.id + '" aria-controls="' + id + '" role="tab" data-toggle="tab">' + opts.title + '</a></li>');
//是否允许关闭
if (options.close) {
if (options.close && $("li", navobj).size() > 0) {
title.append(' <i class="close-tab fa fa-remove"></i>');
}
//创建新TAB的内容

View File

@ -81,7 +81,7 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
var $formitem = $(input).closest('.form-group'),
$msgbox = $formitem.find('span.msg-box');
if (!$msgbox.length) {
$msgbox = $('<span class="msg-box"></span>').insertAfter(input);
return [];
}
return $msgbox;
},

View File

@ -152,7 +152,7 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
// 添加按钮事件
$(toolbar).on('click', Table.config.addbtn, function () {
var ids = Table.api.selectedids(table);
Backend.api.open(options.extend.add_url + "/ids/" + ids.join(","), __('Add'));
Backend.api.open(options.extend.add_url + "/ids" + (ids.length > 0 ? '/' : '') + ids.join(","), __('Add'));
});
// 编辑按钮事件
$(toolbar).on('click', Table.config.editbtn, function () {
@ -274,6 +274,14 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
image: function (value, row, index) {
return '<img class="img-rounded img-sm" src="' + Backend.api.cdnurl(value) + '" />';
},
images: function (value, row, index) {
var arr = value.split(',');
var html = [];
$.each(arr, function (i, value) {
html.push('<img class="img-rounded img-sm" src="' + Backend.api.cdnurl(value) + '" />');
});
return html.join(' ');
},
status: function (value, row, index, custom) {
//颜色状态数组,可使用red/yellow/aqua/blue/navy/teal/olive/lime/fuchsia/purple/maroon
var colorArr = {normal: 'success', hidden: 'grey', deleted: 'danger', locked: 'info'};
@ -289,7 +297,7 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
return html;
},
url: function (value, row, index) {
return '<a href="' + value + '" target="_blank" class="label bg-green">' + value + '</a>';
return '<div class="input-group input-group-sm" style="width:250px;"><input type="text" class="form-control input-sm" value="' + value + '"><span class="input-group-btn input-group-sm"><a href="' + value + '" target="_blank" class="btn btn-default btn-sm"><i class="fa fa-link"></i></a></span></div>';
},
search: function (value, row, index) {
return '<a href="javascript:;" class="searchit" data-field="' + this.field + '" data-value="' + value + '">' + value + '</a>';

View File

@ -76,7 +76,9 @@ body.is-dialog {
width:auto;
}
}
.content {
min-height:500px;
}
#header {
background: #fff;
box-shadow: 0 2px 2px rgba(0,0,0,.05),0 1px 0 rgba(0,0,0,.05);
@ -353,6 +355,14 @@ body.is-dialog {
height:25px;
}
}
.fieldlist dd {
display:block;margin:5px 0;
input{display: inline-block;width:300px;}
input:first-child{width:110px;}
ins{width:110px;display: inline-block;text-decoration:none;font-weight: bold;}
}
#treeview {
.jstree-container-ul .jstree-node{
display:block;clear:both;
@ -433,12 +443,15 @@ body.is-dialog {
}
}
.bootstrap-table .fixed-table-toolbar .dropdown-menu{
overflow:visible;
overflow:auto;
}
.bootstrap-table table tbody tr:first-child td .bs-checkbox {
vertical-align: middle;
}
.bootstrap-table td.bs-checkbox {
vertical-align: middle;
}
.dropdown-submenu {
position: relative;
>.dropdown-menu {