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

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

@ -14,13 +14,24 @@ use think\Request;
*/ */
class {%controllerName%} extends Backend class {%controllerName%} extends Backend
{ {
/**
* {%modelName%}模型对象
*/
protected $model = null; protected $model = null;
public function _initialize() public function _initialize()
{ {
parent::_initialize(); parent::_initialize();
$this->model = model('{%modelName%}'); $this->model = model('{%modelName%}');
{%controllerAssignList%}
} }
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个方法
* 因此在当前控制器中可不用编写增删改查的代码,如果需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
{%controllerIndex%} {%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%} {%appendAttrList%}
]; ];
{%getEnumList%}
{%getAttrList%} {%getAttrList%}
{%setAttrList%} {%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 $this
->setName('menu') ->setName('menu')
->addOption('controller', 'c', Option::VALUE_REQUIRED, 'controller name,use \'all-controller\' when build all menu', null) ->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'); ->setDescription('Build auth menu from controller');
} }
@ -30,12 +31,45 @@ class Menu extends Command
{ {
$this->model = new AuthRule(); $this->model = new AuthRule();
$adminPath = dirname(__DIR__) . DS; $adminPath = dirname(__DIR__) . DS;
$moduleName = 'admin';
//控制器名 //控制器名
$controller = $input->getOption('controller') ?: ''; $controller = $input->getOption('controller') ?: '';
if (!$controller) if (!$controller)
{ {
throw new Exception("please input controller name"); 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') if ($controller != 'all-controller')
{ {

View File

@ -82,12 +82,12 @@ function build_checkboxs($name, $list = [], $selected = null)
* @param array $attr * @param array $attr
* @return string * @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 = Tree::instance();
$tree->init(Category::getCategoryArray($type), 'pid'); $tree->init(Category::getCategoryArray($type), 'pid');
$categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name'); $categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name');
$categorydata = [0 => __('None')]; $categorydata = $header ? $header : [];
foreach ($categorylist as $k => $v) foreach ($categorylist as $k => $v)
{ {
$categorydata[$v['id']] = $v['name']; $categorydata[$v['id']] = $v['name'];
@ -110,7 +110,7 @@ function build_toolbar($btns = NULL, $attr = [])
'refresh' => ['javascript:;', 'btn btn-primary btn-refresh', 'fa fa-refresh', ''], 'refresh' => ['javascript:;', 'btn btn-primary btn-refresh', 'fa fa-refresh', ''],
'add' => ['javascript:;', 'btn btn-success btn-add', 'fa fa-plus', __('Add')], 'add' => ['javascript:;', 'btn btn-success btn-add', 'fa fa-plus', __('Add')],
'edit' => ['javascript:;', 'btn btn-success btn-edit btn-disabled disabled', 'fa fa-pencil', __('Edit')], 'edit' => ['javascript:;', 'btn btn-success btn-edit btn-disabled disabled', 'fa fa-pencil', __('Edit')],
'delete' => ['javascript:;', 'btn btn-danger btn-del btn-disabled disabled', 'fa fa-trash', __('Delete')], 'delete' => ['javascript:;', 'btn btn-danger btn-del btn-disabled disabled', 'fa fa-trash', __('Delete')],
]; ];
$btnAttr = array_merge($btnAttr, $attr); $btnAttr = array_merge($btnAttr, $attr);
$html = []; $html = [];

View File

@ -33,7 +33,7 @@ class Index extends Backend
'auth/admin' => 12, 'auth/admin' => 12,
'auth/rule' => 4, 'auth/rule' => 4,
'general' => ['18', 'purple'], 'general' => ['18', 'purple'],
]); ], $this->view->site['fixedpage']);
$this->view->assign('menulist', $menulist); $this->view->assign('menulist', $menulist);
$this->view->assign('title', __('Home')); $this->view->assign('title', __('Home'));
return $this->view->fetch(); 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 * @icon fa fa-cog
* @remark 用于管理一些字典数据,通常以键值格式进行录入,保存的数据格式为JSON * @remark 用于管理一些字典数据,通常以键值格式进行录入,保存的数据格式为JSON
* @internal
*/ */
class Configvalue extends Backend class Configvalue extends Backend
{ {

View File

@ -1,127 +1,164 @@
<?php <?php
namespace app\admin\controller\wechat; namespace app\admin\controller\wechat;
use app\common\controller\Backend; 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 */
{ class Config extends Backend
{
protected $wechatcfg = NULL;
protected $obj = []; protected $model = null;
public function _initialize() public function _initialize()
{ {
parent::_initialize(); parent::_initialize();
$this->wechatcfg = Configvalue::get('wechat'); $this->model = model('WechatConfig');
$this->obj = $this->wechatcfg->content; }
}
/**
/** * 添加
* 查看 */
*/ public function add()
public function index() {
{ if ($this->request->isPost())
if ($this->request->isAjax()) {
{ $this->code = -1;
$configlist = isset($this->obj['config']) ? $this->obj['config'] : []; $params = $this->request->post("row/a");
$list = array(); if ($params)
foreach ($configlist as $row) {
{ foreach ($params as $k => &$v)
$list[] = $row; {
} $v = is_array($v) ? implode(',', $v) : $v;
$total = count($list); }
$result = array("total" => $total, "rows" => $list);
if ($params['mode'] == 'json')
return json($result); {
} //JSON字段
return $this->view->fetch(); $fieldarr = $valuearr = [];
} $field = $this->request->post('field/a');
$value = $this->request->post('value/a');
/** foreach ($field as $k => $v)
* 添加 {
*/ if ($v != '')
public function add() {
{ $fieldarr[] = $field[$k];
if ($this->request->isPost()) $valuearr[] = $value[$k];
{ }
$this->obj['config'][] = $this->request->post('row/a'); }
$this->wechatcfg->content = $this->obj; $params['value'] = json_encode(array_combine($fieldarr, $valuearr), JSON_UNESCAPED_UNICODE);
$this->wechatcfg->save(); }
$this->code = 1; unset($params['mode']);
return; try
} {
return $this->view->fetch(); //是否采用模型验证
} 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);
public function edit($ids = NULL) }
{ $result = $this->model->save($params);
$row = []; if ($result !== false)
foreach ($this->obj['config'] as $k => $v) {
{ $this->code = 1;
if ($v['id'] == $ids) }
{ else
$row = $v; {
break; $this->msg = $this->model->getError();
} }
} }
if (!$row) catch (\think\exception\PDOException $e)
$this->error(__('No Results were found')); {
if ($this->request->isPost()) $this->msg = $e->getMessage();
{ }
$params = $this->request->post('row/a'); }
$this->obj['config'][$k] = $params; else
$this->obj['config'] = array_values($this->obj['config']); {
$this->wechatcfg->content = $this->obj; $this->msg = __('Parameter %s can not be empty', '');
$this->wechatcfg->save(); }
$this->code = 1;
return; return;
} }
$this->view->assign("row", $row); return $this->view->fetch();
return $this->view->fetch(); }
}
/**
/** * 编辑
* 删除 */
*/ public function edit($ids = NULL)
public function del($ids = "") {
{ $row = $this->model->get($ids);
$this->code = -1; if (!$row)
if ($ids) $this->error(__('No Results were found'));
{ if ($this->request->isPost())
$ids = is_array($ids) ? $ids : explode(',', $ids); {
foreach ($this->obj['config'] as $k => $v) $this->code = -1;
{ $params = $this->request->post("row/a");
if (in_array($v['id'], $ids)) if ($params)
{ {
unset($this->obj['config'][$k]); foreach ($params as $k => &$v)
} {
} $v = is_array($v) ? implode(',', $v) : $v;
$this->wechatcfg->content = $this->obj; }
$this->wechatcfg->save();
$this->code = 1; if ($params['mode'] == 'json')
} {
//JSON字段
return; $fieldarr = $valuearr = [];
} $field = $this->request->post('field/a');
$value = $this->request->post('value/a');
/** foreach ($field as $k => $v)
* 批量更新 {
*/ if ($v != '')
public function multi($ids = "") {
{ $fieldarr[] = $field[$k];
$this->code = -1; $valuearr[] = $value[$k];
//不支持指操作 }
return; }
} $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();
}
}

View File

@ -22,7 +22,7 @@ class Menu extends Backend
public function _initialize() public function _initialize()
{ {
parent::_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']; $responselist[$v['eventkey']] = $v['title'];
} }
$this->view->assign('responselist', $responselist); $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(); return $this->view->fetch();
} }
@ -48,9 +48,7 @@ class Menu extends Backend
{ {
$menu = $this->request->post("menu"); $menu = $this->request->post("menu");
$menu = (array) json_decode($menu, TRUE); $menu = (array) json_decode($menu, TRUE);
$content = $this->wechatcfg->content; $this->wechatcfg->value = json_encode($menu, JSON_UNESCAPED_UNICODE);
$content['menu'] = $menu;
$this->wechatcfg->content = $content;
$this->wechatcfg->save(); $this->wechatcfg->save();
$this->code = 1; $this->code = 1;
return; return;
@ -66,7 +64,7 @@ class Menu extends Backend
try try
{ {
$ret = $app->menu->add($this->wechatcfg->content['menu']); $ret = $app->menu->add(json_decode($this->wechatcfg->value, TRUE));
if ($ret->errcode == 0) if ($ret->errcode == 0)
{ {
$this->code = 1; $this->code = 1;

View File

@ -86,7 +86,8 @@ return [
'Network error' => '网络错误!', 'Network error' => '网络错误!',
'Auth manager' => '权限管理', 'Auth manager' => '权限管理',
'General manager' => '常规管理', 'General manager' => '常规管理',
'Example manager' => '测试管理', 'Example manager' => '示例管理',
'Wechat manager' => '微信管理',
'Common search' => '普通搜索', 'Common search' => '普通搜索',
'Search %s' => '搜索 %s', 'Search %s' => '搜索 %s',
'%d second%s ago' => '%d秒前', '%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' => '宽度', 'Imageheight' => '宽度',
'Imagetype' => '图片类型', 'Imagetype' => '图片类型',
'Imageframes' => '图片帧数', 'Imageframes' => '图片帧数',
'Preview' => '预览',
'Filesize' => '文件大小', 'Filesize' => '文件大小',
'Mimetype' => 'mime类型', 'Mimetype' => 'Mime类型',
'Extparam' => '透传数据', 'Extparam' => '透传数据',
'Createtime' => '创建日期', 'Createtime' => '创建日期',
'Uploadtime' => '上传时间', '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数据 * @param array $params URL对应的badge数据
* @return string * @return string
*/ */
public function getSidebar($params = []) public function getSidebar($params = [], $fixedPage = 'dashboard')
{ {
$colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple']; $colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple'];
$colorNums = count($colorArr); $colorNums = count($colorArr);
@ -275,7 +275,7 @@ class Auth extends \fast\Auth
// 读取管理员当前拥有的权限节点 // 读取管理员当前拥有的权限节点
$userRule = $this->getRuleList(); $userRule = $this->getRuleList();
$select_id = 0; $select_id = 0;
$dashboard = '/' . $module . '/dashboard'; $activeUrl = '/' . $module . '/' . $fixedPage;
// 必须将结果集转换为数组 // 必须将结果集转换为数组
$ruleList = collection(model('AuthRule')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray(); $ruleList = collection(model('AuthRule')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
foreach ($ruleList as $k => &$v) foreach ($ruleList as $k => &$v)
@ -285,7 +285,7 @@ class Auth extends \fast\Auth
unset($ruleList[$k]); unset($ruleList[$k]);
continue; continue;
} }
$select_id = $v['name'] == $dashboard ? $v['id'] : $select_id; $select_id = $v['name'] == $activeUrl ? $v['id'] : $select_id;
$v['url'] = $v['name']; $v['url'] = $v['name'];
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : ''; $v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
} }

View File

@ -23,7 +23,7 @@ trait Backend
->order($sort, $order) ->order($sort, $order)
->limit($offset, $limit) ->limit($offset, $limit)
->select(); ->select();
$result = array("total" => $total, "rows" => $list); $result = array("total" => $total, "rows" => $list);
return json($result); return json($result);
@ -48,7 +48,14 @@ trait Backend
} }
try 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) if ($result !== false)
{ {
$this->code = 1; $this->code = 1;
@ -58,7 +65,7 @@ trait Backend
$this->msg = $this->model->getError(); $this->msg = $this->model->getError();
} }
} }
catch (think\Exception $e) catch (\think\exception\PDOException $e)
{ {
$this->msg = $e->getMessage(); $this->msg = $e->getMessage();
} }
@ -93,6 +100,13 @@ trait Backend
} }
try 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); $result = $row->save($params);
if ($result !== false) if ($result !== false)
{ {
@ -103,7 +117,7 @@ trait Backend
$this->msg = $row->getError(); $this->msg = $row->getError();
} }
} }
catch (think\Exception $e) catch (think\exception\PDOException $e)
{ {
$this->msg = $e->getMessage(); $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=""> <form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group"> <div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">ID:</label> <label for="name" class="control-label col-xs-12 col-sm-2">ID:</label>
@ -20,7 +14,7 @@
<div class="form-group"> <div class="form-group">
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label> <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<dl id="fieldlist" rel="1"> <dl class="fieldlist" rel="1">
<dd> <dd>
<ins>{:__('Key')}</ins> <ins>{:__('Key')}</ins>
<ins>{:__('Value')}</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=""> <form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group"> <div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">ID:</label> <label for="name" class="control-label col-xs-12 col-sm-2">ID:</label>
@ -20,7 +14,7 @@
<div class="form-group"> <div class="form-group">
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label> <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<dl id="fieldlist" rel="{$row.content|count}"> <dl class="fieldlist" rel="{$row.content|count}">
<dd> <dd>
<ins>{:__('Key')}</ins> <ins>{:__('Key')}</ins>
<ins>{:__('Value')}</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"> <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"> <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> </div>
<div class="form-group"> <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"> <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> </div>
<div class="form-group"> <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"> <div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="value" name="row[value]" data-rule="required"></textarea> <p>
<a href="javascript:;" class="btn-insertlink">{:__('Insert link')}</a> <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> </div>
<div class="form-group hidden layer-footer"> <div class="form-group hide layer-footer">
<div class="col-xs-2"></div> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</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"> <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"> <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> </div>
<div class="form-group"> <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"> <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> </div>
<div class="form-group"> <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"> <div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="value" name="row[value]" data-rule="required">{$row.value}</textarea> <p>
<a href="javascript:;" class="btn-insertlink">{:__('Insert link')}</a> <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> </div>
<div class="form-group hidden layer-footer"> <div class="form-group hide layer-footer">
<div class="col-xs-2"></div> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>

View File

@ -6,10 +6,16 @@
<div class="tab-pane fade active in" id="one"> <div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding"> <div class="widget-body no-padding">
<div id="toolbar" class="toolbar"> <div id="toolbar" class="toolbar">
{:build_toolbar()} {:build_toolbar()}
<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> </div>
<table id="table" class="table table-bordered table-hover" width="100%"> <table id="table" class="table table-striped table-bordered table-hover" width="100%">
</table> </table>
</div> </div>
</div> </div>

View File

@ -69,6 +69,16 @@ class Backend extends Controller
*/ */
protected $relationSearch = false; protected $relationSearch = false;
/**
* 是否开启Validate验证
*/
protected $modelValidate = false;
/**
* 是否开启模型场景验证
*/
protected $modelSceneValidate = false;
/** /**
* 引入后台控制器的traits * 引入后台控制器的traits
*/ */
@ -115,7 +125,7 @@ class Backend extends Controller
} }
} }
} }
// 非选项卡时重定向 // 非选项卡时重定向
if (!$this->request->isPost() && !IS_AJAX && !IS_ADDTABS && !IS_DIALOG && input("ref") == 'addtabs') if (!$this->request->isPost() && !IS_AJAX && !IS_ADDTABS && !IS_DIALOG && input("ref") == 'addtabs')
{ {
@ -140,9 +150,11 @@ class Backend extends Controller
// 语言检测 // 语言检测
$lang = Lang::detect(); $lang = Lang::detect();
$site = Config::get("site");
// 配置信息 // 配置信息
$config = [ $config = [
'site' => Config::get("site"), 'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),
'upload' => Configvalue::upload(), 'upload' => Configvalue::upload(),
'modulename' => $modulename, 'modulename' => $modulename,
'controllername' => $controllername, 'controllername' => $controllername,
@ -155,7 +167,7 @@ class Backend extends Controller
Lang::load(APP_PATH . $modulename . '/lang/' . $lang . '/' . str_replace('.', '/', $controllername) . '.php'); 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('config', $config);
$this->assign('admin', Session::get('admin')); $this->assign('admin', Session::get('admin'));
@ -182,16 +194,6 @@ class Backend extends Controller
$op = json_decode($op, TRUE); $op = json_decode($op, TRUE);
$filter = $filter ? $filter : []; $filter = $filter ? $filter : [];
$where = []; $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 = ''; $modelName = '';
if ($relationSearch) if ($relationSearch)
{ {
@ -207,6 +209,16 @@ class Backend extends Controller
$sort = $modelName . $sort; $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) foreach ($filter as $k => $v)
{ {
$sym = isset($op[$k]) ? $op[$k] : '='; $sym = isset($op[$k]) ? $op[$k] : '=';

View File

@ -25,11 +25,7 @@ class Category Extends Model
*/ */
public static function getTypeList() public static function getTypeList()
{ {
$typelist = [ $typelist = config('site', 'categorytype');
'default' => __('Default'),
'page' => __('Page'),
'article' => __('Article'),
];
return $typelist; 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 <?php
//站点配置 return array (
return [ 'name' => 'FastAdmin',
/** 'beian' => '',
* 站点名称 'cdnurl' => '',
*/ 'version' => '1.0.1',
'name' => 'FastAdmin', 'timezone' => 'Asia/Shanghai',
/** 'forbiddenip' => '',
* 备案号 'languages' =>
*/ array (
'beian' => '', 'backend' => 'zh-cn',
/** 'frontend' => 'zh-cn',
* CDN地址,建议使用upload中配置的cdnurl ),
*/ 'fixedpage' => 'dashboard',
'cdnurl' => '', 'categorytype' =>
/** array (
* 版本号 'default' => '默认',
*/ 'page' => '单页',
'version' => '1.0.1', 'article' => '文章',
/** 'test' => '测试',
* 时区 ),
*/ 'configgroup' =>
'timezone' => 'Asia/Shanghai', array (
/** 'basic' => '基础配置',
* 禁止访问的IP 'email' => '邮件配置',
*/ 'dictionary' => '字典配置',
'forbiddenip' => '', 'user' => '会员配置',
/** 'example' => '示例分组',
* 模块语言 ),
*/ );
'languages' => [
'backend' => 'zh-cn',
],
];

View File

@ -6,6 +6,7 @@ use app\common\controller\Frontend;
use app\common\model\WechatAutoreply; use app\common\model\WechatAutoreply;
use app\common\model\WechatContext; use app\common\model\WechatContext;
use app\common\model\WechatResponse; use app\common\model\WechatResponse;
use app\common\model\WechatConfig;
use EasyWeChat\Foundation\Application; use EasyWeChat\Foundation\Application;
use EasyWeChat\Payment\Order; use EasyWeChat\Payment\Order;
use fast\service\Wechat as WechatService; use fast\service\Wechat as WechatService;
@ -31,15 +32,7 @@ class Wechat extends Frontend
*/ */
public function api() public function api()
{ {
$this->app->server->setMessageHandler(function ($message) $this->app->server->setMessageHandler(function ($message) {
{
$content = configvalue('wechat');
//微信配置信息
$wechat_config = [];
foreach ($content['config'] as $k => $v)
{
$wechat_config[$v['id']] = $v['value'];
}
$WechatService = new WechatService; $WechatService = new WechatService;
$WechatContext = new WechatContext; $WechatContext = new WechatContext;
@ -50,7 +43,8 @@ class Wechat extends Frontend
$event = $message->Event; $event = $message->Event;
$eventkey = $message->EventKey ? $message->EventKey : $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) switch ($message->MsgType)
{ {
@ -58,7 +52,9 @@ class Wechat extends Frontend
switch ($event) switch ($event)
{ {
case 'subscribe'://添加关注 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'://取消关注 case 'unsubscribe'://取消关注
return ''; return '';
case 'LOCATION'://获取地理位置 case 'LOCATION'://获取地理位置
@ -149,7 +145,7 @@ class Wechat extends Frontend
*/ */
public function callback() public function callback()
{ {
} }
/** /**
@ -158,8 +154,7 @@ class Wechat extends Frontend
public function notify() public function notify()
{ {
Log::record(file_get_contents('php://input'), "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); $orderinfo = Order::findByTransactionId($notify->transaction_id);
if ($orderinfo) if ($orderinfo)

View File

@ -6,6 +6,7 @@ use app\common\model\Page;
use app\common\model\User; use app\common\model\User;
use app\common\model\UserSignin; use app\common\model\UserSignin;
use app\common\model\UserThird; use app\common\model\UserThird;
use app\common\model\WechatConfig;
use EasyWeChat\Message\News; use EasyWeChat\Message\News;
use EasyWeChat\Message\Transfer; use EasyWeChat\Message\Transfer;
use fast\Date; use fast\Date;
@ -19,7 +20,7 @@ class Wechat
public function __construct() public function __construct()
{ {
} }
public static function appConfig() public static function appConfig()
@ -73,7 +74,7 @@ class Wechat
case 'page': case 'page':
break; break;
case 'service': case 'service':
$service = configvalue('service'); $service = (array) json_decode(WechatConfig::value('service'), true);
list($begintime, $endtime) = explode('-', $service['onlinetime']); list($begintime, $endtime) = explode('-', $service['onlinetime']);
$session = $obj->app->staff_session; $session = $obj->app->staff_session;
$staff = $obj->app->staff; $staff = $obj->app->staff;
@ -107,8 +108,7 @@ class Wechat
else else
{ {
$server = $obj->app->server; $server = $obj->app->server;
$server->setMessageHandler(function($message) $server->setMessageHandler(function($message) {
{
return new Transfer(); return new Transfer();
}); });
$response = $server->serve(); $response = $server->serve();
@ -154,7 +154,7 @@ class Wechat
} }
else 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(); $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; $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 { .form-group .bootstrap-tagsinput span.twitter-typeahead {
width: auto; width: auto;
} }
.content {
min-height: 500px;
}
#header { #header {
background: #fff; background: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05); 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; width: 25px;
height: 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 { #treeview .jstree-container-ul .jstree-node {
display: block; display: block;
clear: both; clear: both;
@ -391,11 +411,14 @@ body.is-dialog {
text-align: left!important; text-align: left!important;
} }
.bootstrap-table .fixed-table-toolbar .dropdown-menu { .bootstrap-table .fixed-table-toolbar .dropdown-menu {
overflow: visible; overflow: auto;
} }
.bootstrap-table table tbody tr:first-child td .bs-checkbox { .bootstrap-table table tbody tr:first-child td .bs-checkbox {
vertical-align: middle; vertical-align: middle;
} }
.bootstrap-table td.bs-checkbox {
vertical-align: middle;
}
.dropdown-submenu { .dropdown-submenu {
position: relative; position: relative;
} }

File diff suppressed because one or more lines are too long

View File

@ -67,6 +67,7 @@
float: left; float: left;
text-align: center; text-align: center;
width: 33.33%; width: 33.33%;
list-style: none;
} }
.ui-sortable-placeholder{ .ui-sortable-placeholder{
background-color:#fff; background-color:#fff;
@ -140,6 +141,7 @@
.sub-menu-list li{ .sub-menu-list li{
line-height: 44px; line-height: 44px;
margin: -1px -1px 0; margin: -1px -1px 0;
list-style: none;
} }
.sub-menu-box .arrow { .sub-menu-box .arrow {
position: absolute; 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: { api: {
bindevent: function () { bindevent: function () {
$(document).on("click", "#fieldlist .append", function () { $(document).on("click", ".fieldlist .append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1; var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
$(this).closest("dl").attr("rel", rel); $(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()); $('<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(); $(this).parent().remove();
}); });
//拖拽排序 //拖拽排序
require(['dragsort'], function () { require(['dragsort'], function () {
//绑定拖动排序 //绑定拖动排序
$("dl#fieldlist").dragsort({ $("dl.fieldlist").dragsort({
itemSelector: 'dd', itemSelector: 'dd',
dragSelector: ".btn-dragsort", dragSelector: ".btn-dragsort",
dragEnd: function () { dragEnd: function () {

View File

@ -159,11 +159,14 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
$(".tab-addtabs").addClass("ios-iframe-fix"); $(".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) { if (Config.referer) {
//刷新页面后跳到到刷新前的页面 //刷新页面后跳到到刷新前的页面
Backend.api.addtabs(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 () { index: function () {
// 初始化表格参数配置 // 初始化表格参数配置
Table.api.init({ Table.api.init({
search: true,
advancedSearch: false,
pagination: false,
extend: { extend: {
"index_url": "wechat/config/index", index_url: 'wechat/config/index',
"add_url": "wechat/config/add", add_url: 'wechat/config/add',
"edit_url": "wechat/config/edit", edit_url: 'wechat/config/edit',
"del_url": "wechat/config/del", del_url: 'wechat/config/del',
"multi_url": "wechat/config/multi", multi_url: 'wechat/config/multi',
table: 'wechat_config',
} }
}); });
@ -21,21 +19,23 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
// 初始化表格 // 初始化表格
table.bootstrapTable({ table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url, url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id', sortName: 'id',
columns: [ columns: [
[ [
{field: 'state', checkbox: true, }, {field: 'state', checkbox: true},
{field: 'id', title: 'ID'}, {field: 'id', title: __('Id')},
{field: 'name', title: __('Name')}, {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} {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate}
] ]
] ]
}); });
// 为表格绑定事件 // 为表格绑定事件
Table.api.bindevent(table);//当内容渲染完成后 Table.api.bindevent(table);
}, },
add: function () { add: function () {
Controller.api.bindevent(); Controller.api.bindevent();
@ -46,6 +46,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
api: { api: {
bindevent: function () { bindevent: function () {
Form.api.bindevent($("form[role=form]")); 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 () { $(document).on('click', ".btn-insertlink", function () {
var textarea = $("textarea[name='row[value]']"); var textarea = $("textarea[name='row[value]']");
var cursorPos = textarea.prop('selectionStart'); var cursorPos = textarea.prop('selectionStart');
@ -63,6 +69,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}); });
}); });
$("input[name='row[type]']:checked").trigger("click"); $("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 () { $(toolbar).on('click', Table.config.addbtn, function () {
var ids = Table.api.selectedids(table); 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 () { $(toolbar).on('click', Table.config.editbtn, function () {
@ -7886,6 +7886,14 @@ define('table',['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap
image: function (value, row, index) { image: function (value, row, index) {
return '<img class="img-rounded img-sm" src="' + Backend.api.cdnurl(value) + '" />'; 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) { status: function (value, row, index, custom) {
//颜色状态数组,可使用red/yellow/aqua/blue/navy/teal/olive/lime/fuchsia/purple/maroon //颜色状态数组,可使用red/yellow/aqua/blue/navy/teal/olive/lime/fuchsia/purple/maroon
var colorArr = {normal: 'success', hidden: 'grey', deleted: 'danger', locked: 'info'}; var colorArr = {normal: 'success', hidden: 'grey', deleted: 'danger', locked: 'info'};
@ -7901,7 +7909,7 @@ define('table',['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap
return html; return html;
}, },
url: function (value, row, index) { 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) { search: function (value, row, index) {
return '<a href="javascript:;" class="searchit" data-field="' + this.field + '" data-value="' + value + '">' + value + '</a>'; 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'), var $formitem = $(input).closest('.form-group'),
$msgbox = $formitem.find('span.msg-box'); $msgbox = $formitem.find('span.msg-box');
if (!$msgbox.length) { if (!$msgbox.length) {
$msgbox = $('<span class="msg-box"></span>').insertAfter(input); return [];
} }
return $msgbox; return $msgbox;
}, },
@ -11322,7 +11330,7 @@ $.fn.addtabs = function (options) {
//创建新TAB的title //创建新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>'); 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>'); title.append(' <i class="close-tab fa fa-remove"></i>');
} }
//创建新TAB的内容 //创建新TAB的内容

View File

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

View File

@ -152,7 +152,7 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
// 添加按钮事件 // 添加按钮事件
$(toolbar).on('click', Table.config.addbtn, function () { $(toolbar).on('click', Table.config.addbtn, function () {
var ids = Table.api.selectedids(table); 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 () { $(toolbar).on('click', Table.config.editbtn, function () {
@ -274,6 +274,14 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
image: function (value, row, index) { image: function (value, row, index) {
return '<img class="img-rounded img-sm" src="' + Backend.api.cdnurl(value) + '" />'; 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) { status: function (value, row, index, custom) {
//颜色状态数组,可使用red/yellow/aqua/blue/navy/teal/olive/lime/fuchsia/purple/maroon //颜色状态数组,可使用red/yellow/aqua/blue/navy/teal/olive/lime/fuchsia/purple/maroon
var colorArr = {normal: 'success', hidden: 'grey', deleted: 'danger', locked: 'info'}; var colorArr = {normal: 'success', hidden: 'grey', deleted: 'danger', locked: 'info'};
@ -289,7 +297,7 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
return html; return html;
}, },
url: function (value, row, index) { 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) { search: function (value, row, index) {
return '<a href="javascript:;" class="searchit" data-field="' + this.field + '" data-value="' + value + '">' + value + '</a>'; 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; width:auto;
} }
} }
.content {
min-height:500px;
}
#header { #header {
background: #fff; background: #fff;
box-shadow: 0 2px 2px rgba(0,0,0,.05),0 1px 0 rgba(0,0,0,.05); box-shadow: 0 2px 2px rgba(0,0,0,.05),0 1px 0 rgba(0,0,0,.05);
@ -353,6 +355,14 @@ body.is-dialog {
height:25px; 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 { #treeview {
.jstree-container-ul .jstree-node{ .jstree-container-ul .jstree-node{
display:block;clear:both; display:block;clear:both;
@ -433,12 +443,15 @@ body.is-dialog {
} }
} }
.bootstrap-table .fixed-table-toolbar .dropdown-menu{ .bootstrap-table .fixed-table-toolbar .dropdown-menu{
overflow:visible; overflow:auto;
} }
.bootstrap-table table tbody tr:first-child td .bs-checkbox { .bootstrap-table table tbody tr:first-child td .bs-checkbox {
vertical-align: middle; vertical-align: middle;
} }
.bootstrap-table td.bs-checkbox {
vertical-align: middle;
}
.dropdown-submenu { .dropdown-submenu {
position: relative; position: relative;
>.dropdown-menu { >.dropdown-menu {