mirror of https://gitee.com/karson/fastadmin.git
新增命令行一键生成API文档功能
新增插件绑定二级域名功能 新增加载JS公用模块 新增命令行创建插件自动生成菜单功能 新增后台菜单Fast.api.refreshmenu 新增后台菜单在数据变更后自动刷新的功能 新增require.min.js压缩版 新增从Headers中读取授权token的功能 新增Form.events.daterangepicker时间区别事件 新增Form表单提示成功和失败的回调事件 新增Fast.api.getrowbyid和Fast.api.getrowbyindex方法 新增commonsearch的find_in_set类型搜索 新增Menu::export的方法 新增php think api一键生成API文档功能 新增php think min的压缩参数和调试功能 优化API模块生产环境下错误信息的显示 优化移动端显示移除顶部Logo一行 优化bower.json和composer.json的版本依赖 优化插件管理列表显示 优化后台控制区多作的选项卡数据 优化CRUD生成的复选框样式及文字 优化规则管理的列表显示 优化第三方前端资源,移除冗余资源 修复在启用域名部署下的BUG 修复API初始化接口的BUG 修复会员积分日志模型BUG 修复多语言切换不存在的BUG 修复Backend.php中multi操作不触发模型事件的BUGpull/48/head v1.0.0.20180308_beta
parent
5155d80295
commit
d863f93d10
8
.bowerrc
8
.bowerrc
|
|
@ -1,3 +1,9 @@
|
||||||
{
|
{
|
||||||
"directory" : "public/assets/libs"
|
"directory" : "public/assets/libs",
|
||||||
|
"ignoredDependencies": [
|
||||||
|
"file-saver",
|
||||||
|
"html2canvas",
|
||||||
|
"jspdf",
|
||||||
|
"jspdf-autotable"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -16,10 +16,12 @@ FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架。
|
||||||
* 基于`Bower`进行前端组件包管理
|
* 基于`Bower`进行前端组件包管理
|
||||||
* 数据库表一键生成`CRUD`,包括控制器、模型、视图、JS、语言包、菜单等
|
* 数据库表一键生成`CRUD`,包括控制器、模型、视图、JS、语言包、菜单等
|
||||||
* 一键压缩打包JS和CSS文件,一键CDN静态资源部署
|
* 一键压缩打包JS和CSS文件,一键CDN静态资源部署
|
||||||
|
* 一键生成API接口文档
|
||||||
* 强大的插件扩展功能,在线安装卸载升级插件
|
* 强大的插件扩展功能,在线安装卸载升级插件
|
||||||
* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
|
* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
|
||||||
|
* 二级域名部署支持,同时域名支持绑定到插件
|
||||||
* 多语言支持,服务端及客户端支持
|
* 多语言支持,服务端及客户端支持
|
||||||
* 强大的第三方插件支持(CMS、博客、文档生成)
|
* 强大的第三方模块支持(CMS、博客、文档生成)
|
||||||
* 整合第三方短信接口(阿里云、创蓝短信)
|
* 整合第三方短信接口(阿里云、创蓝短信)
|
||||||
* 无缝整合第三方云存储(七牛、阿里云OSS、又拍云)功能
|
* 无缝整合第三方云存储(七牛、阿里云OSS、又拍云)功能
|
||||||
* 第三方登录(QQ、微信、微博)整合
|
* 第三方登录(QQ、微信、微博)整合
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,17 @@
|
||||||
|
|
||||||
namespace app\admin\command;
|
namespace app\admin\command;
|
||||||
|
|
||||||
|
use app\common\library\Menu;
|
||||||
use think\addons\AddonException;
|
use think\addons\AddonException;
|
||||||
use think\addons\Service;
|
use think\addons\Service;
|
||||||
|
use think\Config;
|
||||||
use think\console\Command;
|
use think\console\Command;
|
||||||
use think\console\Input;
|
use think\console\Input;
|
||||||
use think\console\input\Option;
|
use think\console\input\Option;
|
||||||
use think\console\Output;
|
use think\console\Output;
|
||||||
use think\Db;
|
use think\Db;
|
||||||
use think\Exception;
|
use think\Exception;
|
||||||
|
use think\exception\PDOException;
|
||||||
|
|
||||||
class Addon extends Command
|
class Addon extends Command
|
||||||
{
|
{
|
||||||
|
|
@ -63,14 +66,43 @@ class Addon extends Command
|
||||||
rmdirs($addonDir);
|
rmdirs($addonDir);
|
||||||
}
|
}
|
||||||
mkdir($addonDir);
|
mkdir($addonDir);
|
||||||
|
mkdir($addonDir . DS . 'controller');
|
||||||
|
$menuList = Menu::export($name);
|
||||||
|
$createMenu = $this->getCreateMenu($menuList);
|
||||||
|
$prefix = Config::get('database.prefix');
|
||||||
|
$createTableSql = '';
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$result = Db::query("SHOW CREATE TABLE `" . $prefix . $name . "`;");
|
||||||
|
if (isset($result[0]) && isset($result[0]['Create Table']))
|
||||||
|
{
|
||||||
|
$createTableSql = $result[0]['Create Table'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (PDOException $e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'addon' => $name,
|
'addon' => $name,
|
||||||
'addonClassName' => ucfirst($name)
|
'addonClassName' => ucfirst($name),
|
||||||
|
'addonInstallMenu' => $createMenu ? "\$menu = " . var_export_short($createMenu, "\t") . ";\n\tMenu::create(\$menu);" : '',
|
||||||
|
'addonUninstallMenu' => $menuList ? 'Menu::delete("' . $name . '");' : '',
|
||||||
|
'addonEnableMenu' => $menuList ? 'Menu::enable("' . $name . '");' : '',
|
||||||
|
'addonDisableMenu' => $menuList ? 'Menu::disable("' . $name . '");' : '',
|
||||||
];
|
];
|
||||||
$this->writeToFile("addon", $data, $addonDir . ucfirst($name) . '.php');
|
$this->writeToFile("addon", $data, $addonDir . ucfirst($name) . '.php');
|
||||||
$this->writeToFile("config", $data, $addonDir . 'config.php');
|
$this->writeToFile("config", $data, $addonDir . 'config.php');
|
||||||
$this->writeToFile("info", $data, $addonDir . 'info.ini');
|
$this->writeToFile("info", $data, $addonDir . 'info.ini');
|
||||||
|
$this->writeToFile("controller", $data, $addonDir . 'controller' . DS . 'Index.php');
|
||||||
|
if ($createTableSql)
|
||||||
|
{
|
||||||
|
$createTableSql = str_replace("`" . $prefix, '`__PREFIX__', $createTableSql);
|
||||||
|
file_put_contents($addonDir . 'install.sql', $createTableSql);
|
||||||
|
}
|
||||||
|
|
||||||
$output->info("Create Successed!");
|
$output->info("Create Successed!");
|
||||||
break;
|
break;
|
||||||
case 'disable':
|
case 'disable':
|
||||||
|
|
@ -256,6 +288,37 @@ class Addon extends Command
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取创建菜单的数组
|
||||||
|
* @param array $menu
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getCreateMenu($menu)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
foreach ($menu as $k => & $v)
|
||||||
|
{
|
||||||
|
$arr = [
|
||||||
|
'name' => $v['name'],
|
||||||
|
'title' => $v['title'],
|
||||||
|
];
|
||||||
|
if ($v['icon'] != 'fa fa-circle-o')
|
||||||
|
{
|
||||||
|
$arr['icon'] = $v['icon'];
|
||||||
|
}
|
||||||
|
if ($v['ismenu'])
|
||||||
|
{
|
||||||
|
$arr['ismenu'] = $v['ismenu'];
|
||||||
|
}
|
||||||
|
if (isset($v['childlist']) && $v['childlist'])
|
||||||
|
{
|
||||||
|
$arr['sublist'] = $this->getCreateMenu($v['childlist']);
|
||||||
|
}
|
||||||
|
$result[] = $arr;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入到文件
|
* 写入到文件
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace addons\{%name%};
|
namespace addons\{%name%};
|
||||||
|
|
||||||
|
use app\common\library\Menu;
|
||||||
use think\Addons;
|
use think\Addons;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,6 +17,7 @@ class {%addonClassName%} extends Addons
|
||||||
*/
|
*/
|
||||||
public function install()
|
public function install()
|
||||||
{
|
{
|
||||||
|
{%addonInstallMenu%}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,6 +27,7 @@ class {%addonClassName%} extends Addons
|
||||||
*/
|
*/
|
||||||
public function uninstall()
|
public function uninstall()
|
||||||
{
|
{
|
||||||
|
{%addonUninstallMenu%}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,6 +37,7 @@ class {%addonClassName%} extends Addons
|
||||||
*/
|
*/
|
||||||
public function enable()
|
public function enable()
|
||||||
{
|
{
|
||||||
|
{%addonEnableMenu%}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,6 +47,7 @@ class {%addonClassName%} extends Addons
|
||||||
*/
|
*/
|
||||||
public function disable()
|
public function disable()
|
||||||
{
|
{
|
||||||
|
{%addonDisableMenu%}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace addons\{%addon%}\controller;
|
||||||
|
|
||||||
|
use think\addons\Controller;
|
||||||
|
|
||||||
|
class Index extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$this->error("当前插件暂无前台页面");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
name = {%name%}
|
name = {%name%}
|
||||||
title = 插件名称
|
title = 插件名称({%name%})
|
||||||
intro = FastAdmin插件
|
intro = FastAdmin插件
|
||||||
author = yourname
|
author = yourname
|
||||||
website = http://www.fastadmin.net
|
website = http://www.fastadmin.net
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\command;
|
||||||
|
|
||||||
|
use app\admin\command\Api\library\Builder;
|
||||||
|
use think\Config;
|
||||||
|
use think\console\Command;
|
||||||
|
use think\console\Input;
|
||||||
|
use think\console\input\Option;
|
||||||
|
use think\console\Output;
|
||||||
|
use think\Exception;
|
||||||
|
|
||||||
|
class Api extends Command
|
||||||
|
{
|
||||||
|
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$site = Config::get('site');
|
||||||
|
$this
|
||||||
|
->setName('api')
|
||||||
|
->addOption('url', 'u', Option::VALUE_OPTIONAL, 'default api url', '')
|
||||||
|
->addOption('module', 'm', Option::VALUE_OPTIONAL, 'module name(admin/index/api)', 'api')
|
||||||
|
->addOption('output', 'o', Option::VALUE_OPTIONAL, 'output index file name', 'api.html')
|
||||||
|
->addOption('template', 'e', Option::VALUE_OPTIONAL, '', 'index.html')
|
||||||
|
->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override general file', false)
|
||||||
|
->addOption('title', 't', Option::VALUE_OPTIONAL, 'document title', $site['name'])
|
||||||
|
->addOption('author', 'a', Option::VALUE_OPTIONAL, 'document author', $site['name'])
|
||||||
|
->addOption('class', 'c', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'extend class', null)
|
||||||
|
->addOption('language', 'l', Option::VALUE_OPTIONAL, 'language', 'zh-cn')
|
||||||
|
->setDescription('Compress js and css file');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(Input $input, Output $output)
|
||||||
|
{
|
||||||
|
$apiDir = __DIR__ . DS . 'Api' . DS;
|
||||||
|
|
||||||
|
$force = $input->getOption('force');
|
||||||
|
$url = $input->getOption('url');
|
||||||
|
$language = $input->getOption('language');
|
||||||
|
$langFile = $apiDir . 'lang' . DS . $language . '.php';
|
||||||
|
if (!is_file($langFile))
|
||||||
|
{
|
||||||
|
throw new Exception('language file not found');
|
||||||
|
}
|
||||||
|
$lang = include $langFile;
|
||||||
|
// 目标目录
|
||||||
|
$output_dir = ROOT_PATH . 'public' . DS;
|
||||||
|
$output_file = $output_dir . $input->getOption('output');
|
||||||
|
if (is_file($output_file) && !$force)
|
||||||
|
{
|
||||||
|
throw new Exception("api index file already exists!\nIf you need to rebuild again, use the parameter --force=true ");
|
||||||
|
}
|
||||||
|
// 模板文件
|
||||||
|
$template_dir = $apiDir . 'template' . DS;
|
||||||
|
$template_file = $template_dir . $input->getOption('template');
|
||||||
|
if (!is_file($template_file))
|
||||||
|
{
|
||||||
|
throw new Exception('template file not found');
|
||||||
|
}
|
||||||
|
// 额外的类
|
||||||
|
$classes = $input->getOption('class');
|
||||||
|
// 标题
|
||||||
|
$title = $input->getOption('title');
|
||||||
|
// 作者
|
||||||
|
$author = $input->getOption('author');
|
||||||
|
// 模块
|
||||||
|
$module = $input->getOption('module');
|
||||||
|
|
||||||
|
$moduleDir = APP_PATH . $module . DS;
|
||||||
|
if (!is_dir($moduleDir))
|
||||||
|
{
|
||||||
|
throw new Exception('module not found');
|
||||||
|
}
|
||||||
|
$controllerDir = $moduleDir . Config::get('url_controller_layer') . DS;
|
||||||
|
$files = new \RecursiveIteratorIterator(
|
||||||
|
new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($files as $name => $file)
|
||||||
|
{
|
||||||
|
if (!$file->isDir())
|
||||||
|
{
|
||||||
|
$filePath = $file->getRealPath();
|
||||||
|
$classes[] = $this->get_class_from_file($filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = [
|
||||||
|
'title' => $title,
|
||||||
|
'author' => $author,
|
||||||
|
'description' => '',
|
||||||
|
'apiurl' => $url,
|
||||||
|
];
|
||||||
|
$builder = new Builder($classes);
|
||||||
|
$content = $builder->render($template_file, ['config' => $config, 'lang' => $lang]);
|
||||||
|
|
||||||
|
if (!file_put_contents($output_file, $content))
|
||||||
|
{
|
||||||
|
throw new Exception('Cannot save the content to ' . $output_file);
|
||||||
|
}
|
||||||
|
$output->info("Build Successed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get full qualified class name
|
||||||
|
*
|
||||||
|
* @param string $path_to_file
|
||||||
|
* @author JBYRNE http://jarretbyrne.com/2015/06/197/
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_class_from_file($path_to_file)
|
||||||
|
{
|
||||||
|
//Grab the contents of the file
|
||||||
|
$contents = file_get_contents($path_to_file);
|
||||||
|
|
||||||
|
//Start with a blank namespace and class
|
||||||
|
$namespace = $class = "";
|
||||||
|
|
||||||
|
//Set helper values to know that we have found the namespace/class token and need to collect the string values after them
|
||||||
|
$getting_namespace = $getting_class = false;
|
||||||
|
|
||||||
|
//Go through each token and evaluate it as necessary
|
||||||
|
foreach (token_get_all($contents) as $token)
|
||||||
|
{
|
||||||
|
|
||||||
|
//If this token is the namespace declaring, then flag that the next tokens will be the namespace name
|
||||||
|
if (is_array($token) && $token[0] == T_NAMESPACE)
|
||||||
|
{
|
||||||
|
$getting_namespace = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If this token is the class declaring, then flag that the next tokens will be the class name
|
||||||
|
if (is_array($token) && $token[0] == T_CLASS)
|
||||||
|
{
|
||||||
|
$getting_class = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//While we're grabbing the namespace name...
|
||||||
|
if ($getting_namespace === true)
|
||||||
|
{
|
||||||
|
|
||||||
|
//If the token is a string or the namespace separator...
|
||||||
|
if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR]))
|
||||||
|
{
|
||||||
|
|
||||||
|
//Append the token's value to the name of the namespace
|
||||||
|
$namespace .= $token[1];
|
||||||
|
}
|
||||||
|
else if ($token === ';')
|
||||||
|
{
|
||||||
|
|
||||||
|
//If the token is the semicolon, then we're done with the namespace declaration
|
||||||
|
$getting_namespace = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//While we're grabbing the class name...
|
||||||
|
if ($getting_class === true)
|
||||||
|
{
|
||||||
|
|
||||||
|
//If the token is a string, it's the name of the class
|
||||||
|
if (is_array($token) && $token[0] == T_STRING)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Store the token's value as the class name
|
||||||
|
$class = $token[1];
|
||||||
|
|
||||||
|
//Got what we need, stope here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Build the fully-qualified class name and return it
|
||||||
|
return $namespace ? $namespace . '\\' . $class : $class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'Info' => '基础信息',
|
||||||
|
'Sandbox' => '在线测试',
|
||||||
|
'Sampleoutput' => '返回示例',
|
||||||
|
'Headers' => 'Headers',
|
||||||
|
'Parameters' => '参数',
|
||||||
|
'Body' => '正文',
|
||||||
|
'Name' => '名称',
|
||||||
|
'Type' => '类型',
|
||||||
|
'Required' => '必选',
|
||||||
|
'Description' => '描述',
|
||||||
|
'Send' => '提交',
|
||||||
|
'Tokentips' => 'Token在会员注册或登录后都会返回,WEB端同时存在于Cookie中',
|
||||||
|
'Apiurltips' => 'API接口URL',
|
||||||
|
'Savetips' => '点击保存后Token和Api url都将保存在本地Localstorage中',
|
||||||
|
'ReturnHeaders' => '响应头',
|
||||||
|
'ReturnParameters' => '返回参数',
|
||||||
|
'Response' => '响应输出',
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\command\Api\library;
|
||||||
|
|
||||||
|
use think\Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @website https://github.com/calinrada/php-apidoc
|
||||||
|
* @author Calin Rada <rada.calin@gmail.com>
|
||||||
|
* @author Karson <karsonzhang@163.com>
|
||||||
|
*/
|
||||||
|
class Builder
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var \think\View
|
||||||
|
*/
|
||||||
|
public $view = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse classes
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $classes = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param array $classes
|
||||||
|
*/
|
||||||
|
public function __construct($classes = [])
|
||||||
|
{
|
||||||
|
$this->classes = array_merge($this->classes, $classes);
|
||||||
|
$this->view = \think\View::instance(Config::get('template'), Config::get('view_replace_str'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function extractAnnotations()
|
||||||
|
{
|
||||||
|
$st_output = [];
|
||||||
|
foreach ($this->classes as $class)
|
||||||
|
{
|
||||||
|
$st_output[] = Extractor::getAllClassAnnotations($class);
|
||||||
|
}
|
||||||
|
return end($st_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateHeadersTemplate($docs)
|
||||||
|
{
|
||||||
|
if (!isset($docs['ApiHeaders']))
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$headerslist = array();
|
||||||
|
foreach ($docs['ApiHeaders'] as $params)
|
||||||
|
{
|
||||||
|
$tr = array(
|
||||||
|
'name' => $params['name'],
|
||||||
|
'type' => $params['type'],
|
||||||
|
'sample' => isset($params['sample']) ? $params['sample'] : '',
|
||||||
|
'required' => isset($params['required']) ? $params['required'] : false,
|
||||||
|
'description' => isset($params['description']) ? $params['description'] : '',
|
||||||
|
);
|
||||||
|
$headerslist[] = $tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $headerslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateParamsTemplate($docs)
|
||||||
|
{
|
||||||
|
if (!isset($docs['ApiParams']))
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$paramslist = array();
|
||||||
|
foreach ($docs['ApiParams'] as $params)
|
||||||
|
{
|
||||||
|
$tr = array(
|
||||||
|
'name' => $params['name'],
|
||||||
|
'type' => isset($params['type']) ? $params['type'] : 'string',
|
||||||
|
'sample' => isset($params['sample']) ? $params['sample'] : '',
|
||||||
|
'required' => isset($params['required']) ? $params['required'] : true,
|
||||||
|
'description' => isset($params['description']) ? $params['description'] : '',
|
||||||
|
);
|
||||||
|
$paramslist[] = $tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $paramslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateReturnHeadersTemplate($docs)
|
||||||
|
{
|
||||||
|
if (!isset($docs['ApiReturnHeaders']))
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$headerslist = array();
|
||||||
|
foreach ($docs['ApiReturnHeaders'] as $params)
|
||||||
|
{
|
||||||
|
$tr = array(
|
||||||
|
'name' => $params['name'],
|
||||||
|
'type' => 'string',
|
||||||
|
'sample' => isset($params['sample']) ? $params['sample'] : '',
|
||||||
|
'required' => isset($params['required']) && $params['required'] ? 'Yes' : 'No',
|
||||||
|
'description' => isset($params['description']) ? $params['description'] : '',
|
||||||
|
);
|
||||||
|
$headerslist[] = $tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $headerslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateReturnParamsTemplate($st_params)
|
||||||
|
{
|
||||||
|
if (!isset($st_params['ApiReturnParams']))
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$paramslist = array();
|
||||||
|
foreach ($st_params['ApiReturnParams'] as $params)
|
||||||
|
{
|
||||||
|
$tr = array(
|
||||||
|
'name' => $params['name'],
|
||||||
|
'type' => isset($params['type']) ? $params['type'] : 'string',
|
||||||
|
'sample' => isset($params['sample']) ? $params['sample'] : '',
|
||||||
|
'description' => isset($params['description']) ? $params['description'] : '',
|
||||||
|
);
|
||||||
|
$paramslist[] = $tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $paramslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateBadgeForMethod($data)
|
||||||
|
{
|
||||||
|
$method = strtoupper(is_array($data['ApiMethod'][0]) ? $data['ApiMethod'][0]['data'] : $data['ApiMethod'][0]);
|
||||||
|
$labes = array(
|
||||||
|
'POST' => 'label-primary',
|
||||||
|
'GET' => 'label-success',
|
||||||
|
'PUT' => 'label-warning',
|
||||||
|
'DELETE' => 'label-danger',
|
||||||
|
'PATCH' => 'label-default',
|
||||||
|
'OPTIONS' => 'label-info'
|
||||||
|
);
|
||||||
|
|
||||||
|
return isset($labes[$method]) ? $labes[$method] : $labes['GET'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parse()
|
||||||
|
{
|
||||||
|
$annotations = $this->extractAnnotations();
|
||||||
|
|
||||||
|
$counter = 0;
|
||||||
|
$section = null;
|
||||||
|
$docslist = [];
|
||||||
|
foreach ($annotations as $class => $methods)
|
||||||
|
{
|
||||||
|
foreach ($methods as $name => $docs)
|
||||||
|
{
|
||||||
|
if (isset($docs['ApiSector'][0]))
|
||||||
|
{
|
||||||
|
$section = is_array($docs['ApiSector'][0]) ? $docs['ApiSector'][0]['data'] : $docs['ApiSector'][0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$section = $class;
|
||||||
|
}
|
||||||
|
if (0 === count($docs))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$docslist[$section][] = [
|
||||||
|
'id' => $counter,
|
||||||
|
'method' => is_array($docs['ApiMethod'][0]) ? $docs['ApiMethod'][0]['data'] : $docs['ApiMethod'][0],
|
||||||
|
'method_label' => $this->generateBadgeForMethod($docs),
|
||||||
|
'section' => $section,
|
||||||
|
'route' => is_array($docs['ApiRoute'][0]) ? $docs['ApiRoute'][0]['data'] : $docs['ApiRoute'][0],
|
||||||
|
'summary' => is_array($docs['ApiSummary'][0]) ? $docs['ApiSummary'][0]['data'] : $docs['ApiSummary'][0],
|
||||||
|
'body' => isset($docs['ApiBody'][0]) ? is_array($docs['ApiBody'][0]) ? $docs['ApiBody'][0]['data'] : $docs['ApiBody'][0] : '',
|
||||||
|
'headerslist' => $this->generateHeadersTemplate($docs),
|
||||||
|
'paramslist' => $this->generateParamsTemplate($docs),
|
||||||
|
'returnheaderslist' => $this->generateReturnHeadersTemplate($docs),
|
||||||
|
'returnparamslist' => $this->generateReturnParamsTemplate($docs),
|
||||||
|
'return' => isset($docs['ApiReturn']) ? is_array($docs['ApiReturn'][0]) ? $docs['ApiReturn'][0]['data'] : $docs['ApiReturn'][0] : '',
|
||||||
|
];
|
||||||
|
$counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $docslist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getView()
|
||||||
|
{
|
||||||
|
return $this->view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染
|
||||||
|
* @param string $template
|
||||||
|
* @param array $vars
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render($template, $vars = [])
|
||||||
|
{
|
||||||
|
$docslist = $this->parse();
|
||||||
|
|
||||||
|
return $this->view->display(file_get_contents($template), array_merge($vars, ['docslist' => $docslist]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,549 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\command\Api\library;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class imported from https://github.com/eriknyk/Annotations
|
||||||
|
* @author Erik Amaru Ortiz https://github.com/eriknyk
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/bsd-license.php The BSD License
|
||||||
|
* @author Calin Rada <rada.calin@gmail.com>
|
||||||
|
*/
|
||||||
|
class Extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static array to store already parsed annotations
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $annotationCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that annotations should has strict behavior, 'false' by default
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $strict = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the default namespace for Objects instance, usually used on methods like getMethodAnnotationsObjects()
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $defaultNamespace = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets strict variable to true/false
|
||||||
|
* @param bool $value boolean value to indicate that annotations to has strict behavior
|
||||||
|
*/
|
||||||
|
public function setStrict($value)
|
||||||
|
{
|
||||||
|
$this->strict = (bool) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets default namespace to use in object instantiation
|
||||||
|
* @param string $namespace default namespace
|
||||||
|
*/
|
||||||
|
public function setDefaultNamespace($namespace)
|
||||||
|
{
|
||||||
|
$this->defaultNamespace = $namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets default namespace used in object instantiation
|
||||||
|
* @return string $namespace default namespace
|
||||||
|
*/
|
||||||
|
public function getDefaultAnnotationNamespace()
|
||||||
|
{
|
||||||
|
return $this->defaultNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all anotations with pattern @SomeAnnotation() from a given class
|
||||||
|
*
|
||||||
|
* @param string $className class name to get annotations
|
||||||
|
* @return array self::$annotationCache all annotated elements
|
||||||
|
*/
|
||||||
|
public static function getClassAnnotations($className)
|
||||||
|
{
|
||||||
|
if (!isset(self::$annotationCache[$className]))
|
||||||
|
{
|
||||||
|
$class = new \ReflectionClass($className);
|
||||||
|
self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment());
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$annotationCache[$className];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getAllClassAnnotations($className)
|
||||||
|
{
|
||||||
|
$class = new \ReflectionClass($className);
|
||||||
|
|
||||||
|
foreach ($class->getMethods() as $object)
|
||||||
|
{
|
||||||
|
self::$annotationCache['annotations'][$className][$object->name] = self::getMethodAnnotations($className, $object->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$annotationCache['annotations'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all anotations with pattern @SomeAnnotation() from a determinated method of a given class
|
||||||
|
*
|
||||||
|
* @param string $className class name
|
||||||
|
* @param string $methodName method name to get annotations
|
||||||
|
* @return array self::$annotationCache all annotated elements of a method given
|
||||||
|
*/
|
||||||
|
public static function getMethodAnnotations($className, $methodName)
|
||||||
|
{
|
||||||
|
if (!isset(self::$annotationCache[$className . '::' . $methodName]))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$method = new \ReflectionMethod($className, $methodName);
|
||||||
|
$class = new \ReflectionClass($className);
|
||||||
|
if (!$method->isPublic() || $method->isConstructor())
|
||||||
|
{
|
||||||
|
$annotations = array();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$annotations = self::consolidateAnnotations($method, $class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\ReflectionException $e)
|
||||||
|
{
|
||||||
|
$annotations = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$annotationCache[$className . '::' . $methodName] = $annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$annotationCache[$className . '::' . $methodName];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all anotations with pattern @SomeAnnotation() from a determinated method of a given class
|
||||||
|
* and instance its abcAnnotation class
|
||||||
|
*
|
||||||
|
* @param string $className class name
|
||||||
|
* @param string $methodName method name to get annotations
|
||||||
|
* @return array self::$annotationCache all annotated objects of a method given
|
||||||
|
*/
|
||||||
|
public function getMethodAnnotationsObjects($className, $methodName)
|
||||||
|
{
|
||||||
|
$annotations = $this->getMethodAnnotations($className, $methodName);
|
||||||
|
$objects = array();
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
foreach ($annotations as $annotationClass => $listParams)
|
||||||
|
{
|
||||||
|
$annotationClass = ucfirst($annotationClass);
|
||||||
|
$class = $this->defaultNamespace . $annotationClass . 'Annotation';
|
||||||
|
|
||||||
|
// verify is the annotation class exists, depending if Annotations::strict is true
|
||||||
|
// if not, just skip the annotation instance creation.
|
||||||
|
if (!class_exists($class))
|
||||||
|
{
|
||||||
|
if ($this->strict)
|
||||||
|
{
|
||||||
|
throw new Exception(sprintf('Runtime Error: Annotation Class Not Found: %s', $class));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// silent skip & continue
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($objects[$annotationClass]))
|
||||||
|
{
|
||||||
|
$objects[$annotationClass] = new $class();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($listParams as $params)
|
||||||
|
{
|
||||||
|
if (is_array($params))
|
||||||
|
{
|
||||||
|
foreach ($params as $key => $value)
|
||||||
|
{
|
||||||
|
$objects[$annotationClass]->set($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$objects[$annotationClass]->set($i++, $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function consolidateAnnotations($method, $class)
|
||||||
|
{
|
||||||
|
$dockblockClass = $class->getDocComment();
|
||||||
|
$docblockMethod = $method->getDocComment();
|
||||||
|
$methodName = $method->getName();
|
||||||
|
|
||||||
|
$methodAnnotations = self::parseAnnotations($docblockMethod);
|
||||||
|
$classAnnotations = self::parseAnnotations($dockblockClass);
|
||||||
|
if (isset($methodAnnotations['ApiInternal']) || $methodName == '_initialize' || $methodName == '_empty')
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$properties = $class->getDefaultProperties();
|
||||||
|
$noNeedLogin = isset($properties['noNeedLogin']) ? is_array($properties['noNeedLogin']) ? $properties['noNeedLogin'] : [$properties['noNeedLogin']] : [];
|
||||||
|
$noNeedRight = isset($properties['noNeedRight']) ? is_array($properties['noNeedRight']) ? $properties['noNeedRight'] : [$properties['noNeedRight']] : [];
|
||||||
|
|
||||||
|
preg_match_all("/\*[\s]+(.*)(\\r\\n|\\r|\\n)/U", str_replace('/**', '', $docblockMethod), $methodArr);
|
||||||
|
preg_match_all("/\*[\s]+(.*)(\\r\\n|\\r|\\n)/U", str_replace('/**', '', $dockblockClass), $classArr);
|
||||||
|
|
||||||
|
$methodTitle = isset($methodArr[1]) && isset($methodArr[1][0]) ? $methodArr[1][0] : '';
|
||||||
|
$classTitle = isset($classArr[1]) && isset($classArr[1][0]) ? $classArr[1][0] : '';
|
||||||
|
|
||||||
|
if (!isset($methodAnnotations['ApiMethod']))
|
||||||
|
{
|
||||||
|
$methodAnnotations['ApiMethod'] = ['get'];
|
||||||
|
}
|
||||||
|
if (!isset($methodAnnotations['ApiSummary']))
|
||||||
|
{
|
||||||
|
$methodAnnotations['ApiSummary'] = [$methodTitle];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($methodAnnotations)
|
||||||
|
{
|
||||||
|
foreach ($classAnnotations as $name => $valueClass)
|
||||||
|
{
|
||||||
|
if (count($valueClass) !== 1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($name === 'ApiRoute')
|
||||||
|
{
|
||||||
|
if (isset($methodAnnotations[$name]))
|
||||||
|
{
|
||||||
|
$methodAnnotations[$name] = [rtrim($valueClass[0], '/') . $methodAnnotations[$name][0]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$methodAnnotations[$name] = [rtrim($valueClass[0], '/') . '/' . $method->getName()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($name === 'ApiSector')
|
||||||
|
{
|
||||||
|
$methodAnnotations[$name] = $valueClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($methodAnnotations['ApiTitle']))
|
||||||
|
{
|
||||||
|
$methodAnnotations['ApiTitle'] = [$methodTitle];
|
||||||
|
}
|
||||||
|
if (!isset($methodAnnotations['ApiRoute']))
|
||||||
|
{
|
||||||
|
$urlArr = [];
|
||||||
|
$className = $class->getName();
|
||||||
|
|
||||||
|
list($prefix, $suffix) = explode('\\' . \think\Config::get('url_controller_layer') . '\\', $className);
|
||||||
|
$prefixArr = explode('\\', $prefix);
|
||||||
|
$suffixArr = explode('\\', $suffix);
|
||||||
|
if ($prefixArr[0] == \think\Config::get('app_namespace'))
|
||||||
|
{
|
||||||
|
$prefixArr[0] = '';
|
||||||
|
}
|
||||||
|
$urlArr = array_merge($urlArr, $prefixArr);
|
||||||
|
$urlArr[] = implode('.', array_map(function($item) {
|
||||||
|
return \think\Loader::parseName($item);
|
||||||
|
}, $suffixArr));
|
||||||
|
$urlArr[] = $method->getName();
|
||||||
|
$methodAnnotations['ApiRoute'] = [implode('/', $urlArr)];
|
||||||
|
}
|
||||||
|
if (!isset($methodAnnotations['ApiSector']))
|
||||||
|
{
|
||||||
|
$methodAnnotations['ApiSector'] = isset($classAnnotations['ApiSector']) ? $classAnnotations['ApiSector'] : [$classTitle];
|
||||||
|
}
|
||||||
|
if (!isset($methodAnnotations['ApiParams']))
|
||||||
|
{
|
||||||
|
$params = self::parseCustomAnnotations($docblockMethod, 'param');
|
||||||
|
foreach ($params as $k => $v)
|
||||||
|
{
|
||||||
|
$arr = explode(' ', preg_replace("/[\s]+/", " ", $v));
|
||||||
|
$methodAnnotations['ApiParams'][] = [
|
||||||
|
'name' => isset($arr[1]) ? str_replace('$', '', $arr[1]) : '',
|
||||||
|
'nullable' => false,
|
||||||
|
'type' => isset($arr[0]) ? $arr[0] : 'string',
|
||||||
|
'description' => isset($arr[2]) ? $arr[2] : ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$methodAnnotations['ApiPermissionLogin'] = [!in_array('*', $noNeedLogin) && !in_array($methodName, $noNeedLogin)];
|
||||||
|
$methodAnnotations['ApiPermissionRight'] = [!in_array('*', $noNeedRight) && !in_array($methodName, $noNeedRight)];
|
||||||
|
return $methodAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse annotations
|
||||||
|
*
|
||||||
|
* @param string $docblock
|
||||||
|
* @param string $name
|
||||||
|
* @return array parsed annotations params
|
||||||
|
*/
|
||||||
|
private static function parseCustomAnnotations($docblock, $name = 'param')
|
||||||
|
{
|
||||||
|
$annotations = array();
|
||||||
|
|
||||||
|
$docblock = substr($docblock, 3, -2);
|
||||||
|
if (preg_match_all('/@' . $name . '(?:\s*(?:\(\s*)?(.*?)(?:\s*\))?)??\s*(?:\n|\*\/)/', $docblock, $matches))
|
||||||
|
{
|
||||||
|
foreach ($matches[1] as $k => $v)
|
||||||
|
{
|
||||||
|
$annotations[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse annotations
|
||||||
|
*
|
||||||
|
* @param string $docblock
|
||||||
|
* @return array parsed annotations params
|
||||||
|
*/
|
||||||
|
private static function parseAnnotations($docblock)
|
||||||
|
{
|
||||||
|
$annotations = array();
|
||||||
|
|
||||||
|
// Strip away the docblock header and footer to ease parsing of one line annotations
|
||||||
|
$docblock = substr($docblock, 3, -2);
|
||||||
|
if (preg_match_all('/@(?<name>[A-Za-z_-]+)[\s\t]*\((?<args>(?:(?!\)).)*)\)\r?/s', $docblock, $matches))
|
||||||
|
{
|
||||||
|
$numMatches = count($matches[0]);
|
||||||
|
|
||||||
|
for ($i = 0; $i < $numMatches; ++$i)
|
||||||
|
{
|
||||||
|
// annotations has arguments
|
||||||
|
if (isset($matches['args'][$i]))
|
||||||
|
{
|
||||||
|
$argsParts = trim($matches['args'][$i]);
|
||||||
|
$name = $matches['name'][$i];
|
||||||
|
$value = self::parseArgs($argsParts);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$value = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$annotations[$name][] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse individual annotation arguments
|
||||||
|
*
|
||||||
|
* @param string $content arguments string
|
||||||
|
* @return array annotated arguments
|
||||||
|
*/
|
||||||
|
private static function parseArgs($content)
|
||||||
|
{
|
||||||
|
// Replace initial stars
|
||||||
|
$content = preg_replace('/^\s*\*/m', '', $content);
|
||||||
|
|
||||||
|
$data = array();
|
||||||
|
$len = strlen($content);
|
||||||
|
$i = 0;
|
||||||
|
$var = '';
|
||||||
|
$val = '';
|
||||||
|
$level = 1;
|
||||||
|
|
||||||
|
$prevDelimiter = '';
|
||||||
|
$nextDelimiter = '';
|
||||||
|
$nextToken = '';
|
||||||
|
$composing = false;
|
||||||
|
$type = 'plain';
|
||||||
|
$delimiter = null;
|
||||||
|
$quoted = false;
|
||||||
|
$tokens = array('"', '"', '{', '}', ',', '=');
|
||||||
|
|
||||||
|
while ($i <= $len)
|
||||||
|
{
|
||||||
|
$prev_c = substr($content, $i - 1, 1);
|
||||||
|
$c = substr($content, $i++, 1);
|
||||||
|
|
||||||
|
if ($c === '"' && $prev_c !== "\\")
|
||||||
|
{
|
||||||
|
$delimiter = $c;
|
||||||
|
//open delimiter
|
||||||
|
if (!$composing && empty($prevDelimiter) && empty($nextDelimiter))
|
||||||
|
{
|
||||||
|
$prevDelimiter = $nextDelimiter = $delimiter;
|
||||||
|
$val = '';
|
||||||
|
$composing = true;
|
||||||
|
$quoted = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// close delimiter
|
||||||
|
if ($c !== $nextDelimiter)
|
||||||
|
{
|
||||||
|
throw new Exception(sprintf(
|
||||||
|
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// validating syntax
|
||||||
|
if ($i < $len)
|
||||||
|
{
|
||||||
|
if (',' !== substr($content, $i, 1) && '\\' !== $prev_c)
|
||||||
|
{
|
||||||
|
throw new Exception(sprintf(
|
||||||
|
"Parse Error: missing comma separator near: ...%s<--", substr($content, ($i - 10), $i)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$prevDelimiter = $nextDelimiter = '';
|
||||||
|
$composing = false;
|
||||||
|
$delimiter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (!$composing && in_array($c, $tokens))
|
||||||
|
{
|
||||||
|
switch ($c)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
$prevDelimiter = $nextDelimiter = '';
|
||||||
|
$level = 2;
|
||||||
|
$composing = false;
|
||||||
|
$type = 'assoc';
|
||||||
|
$quoted = false;
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
$level = 3;
|
||||||
|
|
||||||
|
// If composing flag is true yet,
|
||||||
|
// it means that the string was not enclosed, so it is parsing error.
|
||||||
|
if ($composing === true && !empty($prevDelimiter) && !empty($nextDelimiter))
|
||||||
|
{
|
||||||
|
throw new Exception(sprintf(
|
||||||
|
"Parse Error: enclosing error -> expected: [%s], given: [%s]", $nextDelimiter, $c
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$prevDelimiter = $nextDelimiter = '';
|
||||||
|
break;
|
||||||
|
case '{':
|
||||||
|
$subc = '';
|
||||||
|
$subComposing = true;
|
||||||
|
|
||||||
|
while ($i <= $len)
|
||||||
|
{
|
||||||
|
$c = substr($content, $i++, 1);
|
||||||
|
|
||||||
|
if (isset($delimiter) && $c === $delimiter)
|
||||||
|
{
|
||||||
|
throw new Exception(sprintf(
|
||||||
|
"Parse Error: Composite variable is not enclosed correctly."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($c === '}')
|
||||||
|
{
|
||||||
|
$subComposing = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$subc .= $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the string is composing yet means that the structure of var. never was enclosed with '}'
|
||||||
|
if ($subComposing)
|
||||||
|
{
|
||||||
|
throw new Exception(sprintf(
|
||||||
|
"Parse Error: Composite variable is not enclosed correctly. near: ...%s'", $subc
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$val = self::parseArgs($subc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($level == 1)
|
||||||
|
{
|
||||||
|
$var .= $c;
|
||||||
|
}
|
||||||
|
elseif ($level == 2)
|
||||||
|
{
|
||||||
|
$val .= $c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($level === 3 || $i === $len)
|
||||||
|
{
|
||||||
|
if ($type == 'plain' && $i === $len)
|
||||||
|
{
|
||||||
|
$data = self::castValue($var);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$data[trim($var)] = self::castValue($val, !$quoted);
|
||||||
|
}
|
||||||
|
|
||||||
|
$level = 1;
|
||||||
|
$var = $val = '';
|
||||||
|
$composing = false;
|
||||||
|
$quoted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try determinate the original type variable of a string
|
||||||
|
*
|
||||||
|
* @param string $val string containing possibles variables that can be cast to bool or int
|
||||||
|
* @param boolean $trim indicate if the value passed should be trimmed after to try cast
|
||||||
|
* @return mixed returns the value converted to original type if was possible
|
||||||
|
*/
|
||||||
|
private static function castValue($val, $trim = false)
|
||||||
|
{
|
||||||
|
if (is_array($val))
|
||||||
|
{
|
||||||
|
foreach ($val as $key => $value)
|
||||||
|
{
|
||||||
|
$val[$key] = self::castValue($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (is_string($val))
|
||||||
|
{
|
||||||
|
if ($trim)
|
||||||
|
{
|
||||||
|
$val = trim($val);
|
||||||
|
}
|
||||||
|
$val = stripslashes($val);
|
||||||
|
$tmp = strtolower($val);
|
||||||
|
|
||||||
|
if ($tmp === 'false' || $tmp === 'true')
|
||||||
|
{
|
||||||
|
$val = $tmp === 'true';
|
||||||
|
}
|
||||||
|
elseif (is_numeric($val))
|
||||||
|
{
|
||||||
|
return $val + 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,460 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="{$config.author}">
|
||||||
|
<title>{$config.title}</title>
|
||||||
|
<link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<style type="text/css">
|
||||||
|
body { padding-top: 70px; margin-bottom: 15px; }
|
||||||
|
.tab-pane { padding-top: 10px; }
|
||||||
|
.mt0 { margin-top: 0px; }
|
||||||
|
.footer { font-size: 12px; color: #666; }
|
||||||
|
.label { display: inline-block; min-width: 65px; padding: 0.3em 0.6em 0.3em; }
|
||||||
|
.string { color: green; }
|
||||||
|
.number { color: darkorange; }
|
||||||
|
.boolean { color: blue; }
|
||||||
|
.null { color: magenta; }
|
||||||
|
.key { color: red; }
|
||||||
|
.popover { max-width: 400px; max-height: 400px; overflow-y: auto;}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Fixed navbar -->
|
||||||
|
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="http://www.fastadmin.net" target="_blank">{$config.title}</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-collapse collapse">
|
||||||
|
<form class="navbar-form navbar-right">
|
||||||
|
<div class="form-group">
|
||||||
|
Token:
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control input-sm" data-toggle="tooltip" title="{$lang.Tokentips}" placeholder="token" id="token" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
Apiurl:
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input id="apiUrl" type="text" class="form-control input-sm" data-toggle="tooltip" title="{$lang.Apiurltips}" placeholder="https://api.mydomain.com" value="{$config.apiurl}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="button" class="btn btn-success btn-sm" data-toggle="tooltip" title="{$lang.Savetips}" id="save_data">
|
||||||
|
<span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="panel-group" id="accordion">
|
||||||
|
{foreach name="docslist" id="docs"}
|
||||||
|
<h2>{$key}</h2>
|
||||||
|
<hr>
|
||||||
|
{foreach name="docs" id="api" }
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4 class="panel-title">
|
||||||
|
<span class="label {$api.method_label}">{$api.method|strtoupper}</span> <a data-toggle="collapse" data-parent="#accordion{$api.id}" href="#collapseOne{$api.id}"> {$api.route}</a>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div id="collapseOne{$api.id}" class="panel-collapse collapse">
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
<!-- Nav tabs -->
|
||||||
|
<ul class="nav nav-tabs" id="doctab{$api.id}">
|
||||||
|
<li class="active"><a href="#info{$api.id}" data-toggle="tab">{$lang.Info}</a></li>
|
||||||
|
<li><a href="#sandbox{$api.id}" data-toggle="tab">{$lang.Sandbox}</a></li>
|
||||||
|
<li><a href="#sample{$api.id}" data-toggle="tab">{$lang.Sampleoutput}</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- Tab panes -->
|
||||||
|
<div class="tab-content">
|
||||||
|
|
||||||
|
<div class="tab-pane active" id="info{$api.id}">
|
||||||
|
<div class="well">
|
||||||
|
{$api.summary}
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.Headers}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{if $api.headerslist}
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{$lang.Name}</th>
|
||||||
|
<th>{$lang.Type}</th>
|
||||||
|
<th>{$lang.Required}</th>
|
||||||
|
<th>{$lang.Description}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{foreach name="api['headerslist']" id="header"}
|
||||||
|
<tr>
|
||||||
|
<td>{$header.name}</td>
|
||||||
|
<td>{$header.type}</td>
|
||||||
|
<td>{$header.required?'是':'否'}</td>
|
||||||
|
<td>{$header.description}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{else /}
|
||||||
|
无
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.Parameters}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{if $api.paramslist}
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{$lang.Name}</th>
|
||||||
|
<th>{$lang.Type}</th>
|
||||||
|
<th>{$lang.Required}</th>
|
||||||
|
<th>{$lang.Description}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{foreach name="api['paramslist']" id="param"}
|
||||||
|
<tr>
|
||||||
|
<td>{$param.name}</td>
|
||||||
|
<td>{$param.type}</td>
|
||||||
|
<td>{:$param.required?'是':'否'}</td>
|
||||||
|
<td>{$param.description}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{else /}
|
||||||
|
无
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.Body}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{$api.body|default='无'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- #info -->
|
||||||
|
|
||||||
|
<div class="tab-pane" id="sandbox{$api.id}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
{if $api.headerslist}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.Headers}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="headers">
|
||||||
|
{foreach name="api['headerslist']" id="param"}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label" for="{$param.name}">{$param.name}</label>
|
||||||
|
<input type="{$param.type}" class="form-control input-sm" id="{$param.name}" {if $param.required}required{/if} placeholder="{$param.description} - Ex: {$param.sample}" name="{$param.name}">
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.Parameters}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form enctype="application/x-www-form-urlencoded" role="form" action="{$api.route}" method="{$api.method}" name="form{$api.id}" id="form{$api.id}">
|
||||||
|
{if $api.paramslist}
|
||||||
|
{foreach name="api['paramslist']" id="param"}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label" for="{$param.name}">{$param.name}</label>
|
||||||
|
<input type="{$param.type}" class="form-control input-sm" id="{$param.name}" {if $param.required}required{/if} placeholder="{$param.description}{if $param.sample} - 例: {$param.sample}{/if}" name="{$param.name}">
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
{else /}
|
||||||
|
<div class="form-group">
|
||||||
|
无
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-success send" rel="{$api.id}">{$lang.Send}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.Response}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12" style="overflow-x:auto">
|
||||||
|
<pre id="response_headers{$api.id}"></pre>
|
||||||
|
<pre id="response{$api.id}"></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>{$lang.ReturnParameters}</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{if $api.returnparamslist}
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{$lang.Name}</th>
|
||||||
|
<th>{$lang.Type}</th>
|
||||||
|
<th>{$lang.Description}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{foreach name="api['returnparamslist']" id="param"}
|
||||||
|
<tr>
|
||||||
|
<td>{$param.name}</td>
|
||||||
|
<td>{$param.type}</td>
|
||||||
|
<td>{$param.description}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{else /}
|
||||||
|
无
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- #sandbox -->
|
||||||
|
|
||||||
|
<div class="tab-pane" id="sample{$api.id}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<pre id="sample_response{$api.id}">{$api.return|default='无'}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- #sample -->
|
||||||
|
|
||||||
|
</div><!-- .tab-content -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/foreach}
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="row mt0 footer">
|
||||||
|
<div class="col-md-6" align="left">
|
||||||
|
Generated on {:date('Y-m-d H:i:s')}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6" align="right">
|
||||||
|
<a href="http://www.fastadmin.net" target="_blank">FastAdmin</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div> <!-- /container -->
|
||||||
|
|
||||||
|
<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
|
||||||
|
<script src="https://cdn.bootcss.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function syntaxHighlight(json) {
|
||||||
|
if (typeof json != 'string') {
|
||||||
|
json = JSON.stringify(json, undefined, 2);
|
||||||
|
}
|
||||||
|
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
|
||||||
|
var cls = 'number';
|
||||||
|
if (/^"/.test(match)) {
|
||||||
|
if (/:$/.test(match)) {
|
||||||
|
cls = 'key';
|
||||||
|
} else {
|
||||||
|
cls = 'string';
|
||||||
|
}
|
||||||
|
} else if (/true|false/.test(match)) {
|
||||||
|
cls = 'boolean';
|
||||||
|
} else if (/null/.test(match)) {
|
||||||
|
cls = 'null';
|
||||||
|
}
|
||||||
|
return '<span class="' + cls + '">' + match + '</span>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareStr(str) {
|
||||||
|
try {
|
||||||
|
return syntaxHighlight(JSON.stringify(JSON.parse(str.replace(/'/g, '"')), null, 2));
|
||||||
|
} catch (e) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var storage = (function () {
|
||||||
|
var uid = new Date;
|
||||||
|
var storage;
|
||||||
|
var result;
|
||||||
|
try {
|
||||||
|
(storage = window.localStorage).setItem(uid, uid);
|
||||||
|
result = storage.getItem(uid) == uid;
|
||||||
|
storage.removeItem(uid);
|
||||||
|
return result && storage;
|
||||||
|
} catch (exception) {
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
$.fn.serializeObject = function ()
|
||||||
|
{
|
||||||
|
var o = {};
|
||||||
|
var a = this.serializeArray();
|
||||||
|
$.each(a, function () {
|
||||||
|
if (!this.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (o[this.name] !== undefined) {
|
||||||
|
if (!o[this.name].push) {
|
||||||
|
o[this.name] = [o[this.name]];
|
||||||
|
}
|
||||||
|
o[this.name].push(this.value || '');
|
||||||
|
} else {
|
||||||
|
o[this.name] = this.value || '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
if (storage) {
|
||||||
|
$('#token').val(storage.getItem('token'));
|
||||||
|
$('#apiUrl').val(storage.getItem('apiUrl'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$('[data-toggle="tooltip"]').tooltip({
|
||||||
|
placement: 'bottom'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('code[id^=response]').hide();
|
||||||
|
|
||||||
|
$.each($('pre[id^=sample_response],pre[id^=sample_post_body]'), function () {
|
||||||
|
if ($(this).html() == 'NA') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var str = prepareStr($(this).html());
|
||||||
|
$(this).html(str);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("[data-toggle=popover]").popover({placement: 'right'});
|
||||||
|
|
||||||
|
$('[data-toggle=popover]').on('shown.bs.popover', function () {
|
||||||
|
var $sample = $(this).parent().find(".popover-content"),
|
||||||
|
str = $(this).data('content');
|
||||||
|
if (typeof str == "undefined" || str === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var str = prepareStr(str);
|
||||||
|
$sample.html('<pre>' + str + '</pre>');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '#save_data', function (e) {
|
||||||
|
if (storage) {
|
||||||
|
storage.setItem('token', $('#token').val());
|
||||||
|
storage.setItem('apiUrl', $('#apiUrl').val());
|
||||||
|
} else {
|
||||||
|
alert('Your browser does not support local storage');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('click', '.send', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var form = $(this).closest('form');
|
||||||
|
//added /g to get all the matched params instead of only first
|
||||||
|
var matchedParamsInRoute = $(form).attr('action').match(/[^{]+(?=\})/g);
|
||||||
|
var theId = $(this).attr('rel');
|
||||||
|
//keep a copy of action attribute in order to modify the copy
|
||||||
|
//instead of the initial attribute
|
||||||
|
var url = $(form).attr('action');
|
||||||
|
|
||||||
|
var serializedData = new FormData();
|
||||||
|
|
||||||
|
$(form).find('input').each(function (i, input) {
|
||||||
|
if ($(input).attr('type') == 'file') {
|
||||||
|
serializedData.append($(input).attr('name'), $(input)[0].files[0]);
|
||||||
|
} else {
|
||||||
|
serializedData.append($(input).attr('name'), $(input).val())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var index, key, value;
|
||||||
|
|
||||||
|
if (matchedParamsInRoute) {
|
||||||
|
for (index = 0; index < matchedParamsInRoute.length; ++index) {
|
||||||
|
try {
|
||||||
|
key = matchedParamsInRoute[index];
|
||||||
|
value = serializedData[key];
|
||||||
|
if (typeof value == "undefined")
|
||||||
|
value = "";
|
||||||
|
url = url.replace("{" + key + "}", value);
|
||||||
|
delete serializedData[key];
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var headers = {};
|
||||||
|
|
||||||
|
var token = $('#token').val();
|
||||||
|
if (token.length > 0) {
|
||||||
|
headers[token] = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#sandbox" + theId + " .headers input[type=text]").each(function () {
|
||||||
|
val = $(this).val();
|
||||||
|
if (val.length > 0) {
|
||||||
|
headers[$(this).prop('name')] = val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: $('#apiUrl').val() + url,
|
||||||
|
data: $(form).attr('method') == 'get' ? $(form).serialize() : serializedData,
|
||||||
|
type: $(form).attr('method') + '',
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: false,
|
||||||
|
processData: false,
|
||||||
|
headers: headers,
|
||||||
|
success: function (data, textStatus, xhr) {
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
var str = JSON.stringify(data, null, 2);
|
||||||
|
$('#response' + theId).html(syntaxHighlight(str));
|
||||||
|
} else {
|
||||||
|
$('#response' + theId).html(data || '');
|
||||||
|
}
|
||||||
|
$('#response_headers' + theId).html('HTTP ' + xhr.status + ' ' + xhr.statusText + '<br/><br/>' + xhr.getAllResponseHeaders());
|
||||||
|
$('#response' + theId).show();
|
||||||
|
},
|
||||||
|
error: function (xhr, textStatus, error) {
|
||||||
|
try {
|
||||||
|
var str = JSON.stringify($.parseJSON(xhr.responseText), null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
var str = xhr.responseText;
|
||||||
|
}
|
||||||
|
$('#response_headers' + theId).html('HTTP ' + xhr.status + ' ' + xhr.statusText + '<br/><br/>' + xhr.getAllResponseHeaders());
|
||||||
|
$('#response' + theId).html(syntaxHighlight(str));
|
||||||
|
$('#response' + theId).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -580,8 +580,8 @@ class Crud extends Command
|
||||||
}
|
}
|
||||||
$formAddElement = $formEditElement = Form::hidden($fieldName, $no, array_merge(['checked' => ''], $attrArr));
|
$formAddElement = $formEditElement = Form::hidden($fieldName, $no, array_merge(['checked' => ''], $attrArr));
|
||||||
$attrArr['id'] = $fieldName . "-switch";
|
$attrArr['id'] = $fieldName . "-switch";
|
||||||
$formAddElement .= sprintf(Form::label("{$attrArr['id']}", "%s abcdefg"), Form::checkbox($fieldName, $yes, $defaultValue === $yes, $attrArr));
|
$formAddElement .= sprintf(Form::label("{$attrArr['id']}", "%s {:__('Yes')}", ['class'=>'control-label']), Form::checkbox($fieldName, $yes, $defaultValue === $yes, $attrArr));
|
||||||
$formEditElement .= sprintf(Form::label("{$attrArr['id']}", "%s abcdefg"), Form::checkbox($fieldName, $yes, 0, $attrArr));
|
$formEditElement .= sprintf(Form::label("{$attrArr['id']}", "%s {:__('Yes')}", ['class'=>'control-label']), Form::checkbox($fieldName, $yes, 0, $attrArr));
|
||||||
$formEditElement = str_replace('type="checkbox"', 'type="checkbox" {in name="' . "\$row.{$field}" . '" value="' . $yes . '"}checked{/in}', $formEditElement);
|
$formEditElement = str_replace('type="checkbox"', 'type="checkbox" {in name="' . "\$row.{$field}" . '" value="' . $yes . '"}checked{/in}', $formEditElement);
|
||||||
}
|
}
|
||||||
else if ($inputType == 'citypicker')
|
else if ($inputType == 'citypicker')
|
||||||
|
|
@ -963,6 +963,7 @@ EOD;
|
||||||
if ($content || !Lang::has($field))
|
if ($content || !Lang::has($field))
|
||||||
{
|
{
|
||||||
$itemArr = [];
|
$itemArr = [];
|
||||||
|
$content = str_replace(',', ',', $content);
|
||||||
if (stripos($content, ':') !== false && stripos($content, ',') && stripos($content, '=') !== false)
|
if (stripos($content, ':') !== false && stripos($content, ',') && stripos($content, '=') !== false)
|
||||||
{
|
{
|
||||||
list($fieldLang, $item) = explode(':', $content);
|
list($fieldLang, $item) = explode(':', $content);
|
||||||
|
|
@ -997,6 +998,7 @@ EOD;
|
||||||
/**
|
/**
|
||||||
* 读取数据和语言数组列表
|
* 读取数据和语言数组列表
|
||||||
* @param array $arr
|
* @param array $arr
|
||||||
|
* @param boolean $withTpl
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getLangArray($arr, $withTpl = TRUE)
|
protected function getLangArray($arr, $withTpl = TRUE)
|
||||||
|
|
@ -1035,6 +1037,7 @@ EOD;
|
||||||
protected function getItemArray($item, $field, $comment)
|
protected function getItemArray($item, $field, $comment)
|
||||||
{
|
{
|
||||||
$itemArr = [];
|
$itemArr = [];
|
||||||
|
$comment = str_replace(',', ',', $comment);
|
||||||
if (stripos($comment, ':') !== false && stripos($comment, ',') && stripos($comment, '=') !== false)
|
if (stripos($comment, ':') !== false && stripos($comment, ',') && stripos($comment, '=') !== false)
|
||||||
{
|
{
|
||||||
list($fieldLang, $item) = explode(':', $comment);
|
list($fieldLang, $item) = explode(':', $comment);
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,8 @@ class Install extends Command
|
||||||
// 写入数据库配置
|
// 写入数据库配置
|
||||||
file_put_contents($dbConfigFile, $config);
|
file_put_contents($dbConfigFile, $config);
|
||||||
|
|
||||||
|
\think\Cache::rm('__menu__');
|
||||||
|
|
||||||
$output->info("Install Successed!");
|
$output->info("Install Successed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
官网: http://www.fastadmin.net
|
官网: http://www.fastadmin.net
|
||||||
演示: http://demo.fastadmin.net
|
演示: http://demo.fastadmin.net
|
||||||
|
|
||||||
Date: 2017年09月15日
|
Date: 2018年03月07日
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
@ -396,6 +396,9 @@ BEGIN;
|
||||||
INSERT INTO `fa_test` VALUES (1, 0, 12, '12,13', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '<p>我是测试内容</p>', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '描述', '广西壮族自治区/百色市/平果县', 0.00, 0, '2017-07-10', '2017-07-10 18:24:45', 2017, '18:24:45', 1499682285, 1499682526, 1499682526, 0, 1, 'normal', '1');
|
INSERT INTO `fa_test` VALUES (1, 0, 12, '12,13', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '<p>我是测试内容</p>', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '描述', '广西壮族自治区/百色市/平果县', 0.00, 0, '2017-07-10', '2017-07-10 18:24:45', 2017, '18:24:45', 1499682285, 1499682526, 1499682526, 0, 1, 'normal', '1');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_user
|
||||||
|
-- ----------------------------
|
||||||
DROP TABLE IF EXISTS `fa_user`;
|
DROP TABLE IF EXISTS `fa_user`;
|
||||||
CREATE TABLE `fa_user` (
|
CREATE TABLE `fa_user` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||||
|
|
@ -431,10 +434,16 @@ CREATE TABLE `fa_user` (
|
||||||
KEY `mobile` (`mobile`)
|
KEY `mobile` (`mobile`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='会员表';
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='会员表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of fa_user
|
||||||
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO `fa_user` VALUES (1, 1, 'admin', 'admin', 'c13f62012fd6a8fdf06b3452a94430e5', 'rpR6Bv', 'admin@163.com', '13888888888', '/assets/img/avatar.png', 0, 0, '2017-04-15', '', 0, 1, 1, 1516170492, 1516171614, '127.0.0.1', 0, '127.0.0.1', 1491461418, 0, 1516171614, '', 'normal','');
|
INSERT INTO `fa_user` VALUES (1, 1, 'admin', 'admin', 'c13f62012fd6a8fdf06b3452a94430e5', 'rpR6Bv', 'admin@163.com', '13888888888', '/assets/img/avatar.png', 0, 0, '2017-04-15', '', 0, 1, 1, 1516170492, 1516171614, '127.0.0.1', 0, '127.0.0.1', 1491461418, 0, 1516171614, '', 'normal','');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_user_group
|
||||||
|
-- ----------------------------
|
||||||
DROP TABLE IF EXISTS `fa_user_group`;
|
DROP TABLE IF EXISTS `fa_user_group`;
|
||||||
CREATE TABLE `fa_user_group` (
|
CREATE TABLE `fa_user_group` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
|
@ -446,10 +455,16 @@ CREATE TABLE `fa_user_group` (
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='会员组表';
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='会员组表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of fa_user_group
|
||||||
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO `fa_user_group` VALUES (1, '默认组', '1,2,3,4,5,6,7,8,9,10,11,12', 1515386468, 1516168298, 'normal');
|
INSERT INTO `fa_user_group` VALUES (1, '默认组', '1,2,3,4,5,6,7,8,9,10,11,12', 1515386468, 1516168298, 'normal');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_user_rule
|
||||||
|
-- ----------------------------
|
||||||
DROP TABLE IF EXISTS `fa_user_rule`;
|
DROP TABLE IF EXISTS `fa_user_rule`;
|
||||||
CREATE TABLE `fa_user_rule` (
|
CREATE TABLE `fa_user_rule` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
|
@ -465,6 +480,9 @@ CREATE TABLE `fa_user_rule` (
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='会员规则表';
|
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COMMENT='会员规则表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of fa_user_rule
|
||||||
|
-- ----------------------------
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO `fa_user_rule` VALUES (1, 0, 'index', '前台', '', 1, 1516168079, 1516168079, 1, 'normal');
|
INSERT INTO `fa_user_rule` VALUES (1, 0, 'index', '前台', '', 1, 1516168079, 1516168079, 1, 'normal');
|
||||||
INSERT INTO `fa_user_rule` VALUES (2, 0, 'api', 'API接口', '', 1, 1516168062, 1516168062, 2, 'normal');
|
INSERT INTO `fa_user_rule` VALUES (2, 0, 'api', 'API接口', '', 1, 1516168062, 1516168062, 2, 'normal');
|
||||||
|
|
@ -480,6 +498,9 @@ INSERT INTO `fa_user_rule` VALUES (11, 4, 'api/user/index', '会员中心', '',
|
||||||
INSERT INTO `fa_user_rule` VALUES (12, 4, 'api/user/profile', '个人资料', '', 0, 1516015012, 1516015012, 3, 'normal');
|
INSERT INTO `fa_user_rule` VALUES (12, 4, 'api/user/profile', '个人资料', '', 0, 1516015012, 1516015012, 3, 'normal');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_user_score_log
|
||||||
|
-- ----------------------------
|
||||||
DROP TABLE IF EXISTS `fa_user_score_log`;
|
DROP TABLE IF EXISTS `fa_user_score_log`;
|
||||||
CREATE TABLE `fa_user_score_log` (
|
CREATE TABLE `fa_user_score_log` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
|
@ -492,6 +513,9 @@ CREATE TABLE `fa_user_score_log` (
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='会员积分变动表';
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='会员积分变动表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_user_token
|
||||||
|
-- ----------------------------
|
||||||
DROP TABLE IF EXISTS `fa_user_token`;
|
DROP TABLE IF EXISTS `fa_user_token`;
|
||||||
CREATE TABLE `fa_user_token` (
|
CREATE TABLE `fa_user_token` (
|
||||||
`token` varchar(50) NOT NULL COMMENT 'Token',
|
`token` varchar(50) NOT NULL COMMENT 'Token',
|
||||||
|
|
@ -501,4 +525,30 @@ CREATE TABLE `fa_user_token` (
|
||||||
PRIMARY KEY (`token`)
|
PRIMARY KEY (`token`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员Token表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员Token表';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_version
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `fa_version`;
|
||||||
|
CREATE TABLE `fa_version` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||||
|
`oldversion` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '旧版本号',
|
||||||
|
`newversion` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '新版本号',
|
||||||
|
`packagesize` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '包大小',
|
||||||
|
`content` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '升级内容',
|
||||||
|
`downloadurl` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '下载地址',
|
||||||
|
`enforce` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '强制更新',
|
||||||
|
`createtime` int(10) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||||
|
`updatetime` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||||
|
`weigh` int(10) NOT NULL DEFAULT 0 COMMENT '权重',
|
||||||
|
`status` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '状态',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '版本表' ROW_FORMAT = Compact;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for fa_version
|
||||||
|
-- ----------------------------
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO `fa_version` (`id`, `oldversion`, `newversion`, `packagesize`, `content`, `downloadurl`, `enforce`, `createtime`, `updatetime`, `weigh`, `status`) VALUES
|
||||||
|
(1, '1.1.1,2', '1.2.1', '20M', '更新内容', 'http://www.fastadmin.net/download.html', 1, 1520425318, 0, 0, 'normal');
|
||||||
|
COMMIT;
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ class Menu extends Command
|
||||||
{
|
{
|
||||||
throw new Exception("There is no menu to delete");
|
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: ");
|
$output->info("Are you sure you want to delete all those menu? Type 'yes' to continue: ");
|
||||||
$line = fgets(STDIN);
|
$line = fgets(STDIN);
|
||||||
if (trim($line) != 'yes')
|
if (trim($line) != 'yes')
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class Min extends Command
|
||||||
->setName('min')
|
->setName('min')
|
||||||
->addOption('module', 'm', Option::VALUE_REQUIRED, 'module name(frontend or backend),use \'all\' when build all modules', null)
|
->addOption('module', 'm', Option::VALUE_REQUIRED, 'module name(frontend or backend),use \'all\' when build all modules', null)
|
||||||
->addOption('resource', 'r', Option::VALUE_REQUIRED, 'resource name(js or css),use \'all\' when build all resources', null)
|
->addOption('resource', 'r', Option::VALUE_REQUIRED, 'resource name(js or css),use \'all\' when build all resources', null)
|
||||||
|
->addOption('optimize', 'o', Option::VALUE_OPTIONAL, 'optimize type(uglify|closure|none)', 'none')
|
||||||
->setDescription('Compress js and css file');
|
->setDescription('Compress js and css file');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,6 +35,7 @@ class Min extends Command
|
||||||
{
|
{
|
||||||
$module = $input->getOption('module') ?: '';
|
$module = $input->getOption('module') ?: '';
|
||||||
$resource = $input->getOption('resource') ?: '';
|
$resource = $input->getOption('resource') ?: '';
|
||||||
|
$optimize = $input->getOption('optimize') ?: 'none';
|
||||||
|
|
||||||
if (!$module || !in_array($module, ['frontend', 'backend', 'all']))
|
if (!$module || !in_array($module, ['frontend', 'backend', 'all']))
|
||||||
{
|
{
|
||||||
|
|
@ -89,6 +91,7 @@ class Min extends Command
|
||||||
'cssBaseUrl' => $this->options['cssBaseUrl'],
|
'cssBaseUrl' => $this->options['cssBaseUrl'],
|
||||||
'jsBasePath' => str_replace(DS, '/', ROOT_PATH . $this->options['jsBaseUrl']),
|
'jsBasePath' => str_replace(DS, '/', ROOT_PATH . $this->options['jsBaseUrl']),
|
||||||
'cssBasePath' => str_replace(DS, '/', ROOT_PATH . $this->options['cssBaseUrl']),
|
'cssBasePath' => str_replace(DS, '/', ROOT_PATH . $this->options['cssBaseUrl']),
|
||||||
|
'optimize' => $optimize,
|
||||||
'ds' => DS,
|
'ds' => DS,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -117,11 +120,19 @@ class Min extends Command
|
||||||
$output->info("Compress " . $data["{$res}BaseName"] . ".{$res}");
|
$output->info("Compress " . $data["{$res}BaseName"] . ".{$res}");
|
||||||
|
|
||||||
// 执行压缩
|
// 执行压缩
|
||||||
echo exec("{$nodeExec} \"{$minPath}r.js\" -o \"{$tempFile}\" >> \"{$minPath}node.log\"");
|
$command = "{$nodeExec} \"{$minPath}r.js\" -o \"{$tempFile}\" >> \"{$minPath}node.log\"";
|
||||||
|
if ($output->isDebug())
|
||||||
|
{
|
||||||
|
$output->warning($command);
|
||||||
|
}
|
||||||
|
echo exec($command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$output->isDebug())
|
||||||
|
{
|
||||||
@unlink($tempFile);
|
@unlink($tempFile);
|
||||||
|
}
|
||||||
|
|
||||||
$output->info("Build Successed!");
|
$output->info("Build Successed!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
({
|
({
|
||||||
cssIn: "{%cssBasePath%}{%cssBaseName%}.css",
|
cssIn: "{%cssBasePath%}{%cssBaseName%}.css",
|
||||||
out: "{%cssBasePath%}{%cssBaseName%}.min.css",
|
out: "{%cssBasePath%}{%cssBaseName%}.min.css",
|
||||||
optimizeCss: "default"
|
optimizeCss: "default",
|
||||||
|
optimize: "{%optimize%}"
|
||||||
})
|
})
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
{%config%}
|
{%config%}
|
||||||
,
|
,
|
||||||
optimizeCss: "standard",
|
optimizeCss: "standard",
|
||||||
optimize: "none", //可使用uglify|closure|none
|
optimize: "{%optimize%}", //可使用uglify|closure|none
|
||||||
|
preserveLicenseComments: false,
|
||||||
removeCombined: false,
|
removeCombined: false,
|
||||||
baseUrl: "{%jsBasePath%}", //JS文件所在的基础目录
|
baseUrl: "{%jsBasePath%}", //JS文件所在的基础目录
|
||||||
name: "{%jsBaseName%}", //来源文件,不包含后缀
|
name: "{%jsBaseName%}", //来源文件,不包含后缀
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace app\admin\controller;
|
||||||
use app\common\controller\Backend;
|
use app\common\controller\Backend;
|
||||||
use think\addons\AddonException;
|
use think\addons\AddonException;
|
||||||
use think\addons\Service;
|
use think\addons\Service;
|
||||||
|
use think\Cache;
|
||||||
use think\Config;
|
use think\Config;
|
||||||
use think\Exception;
|
use think\Exception;
|
||||||
|
|
||||||
|
|
@ -190,6 +191,7 @@ class Addon extends Backend
|
||||||
$action = $action == 'enable' ? $action : 'disable';
|
$action = $action == 'enable' ? $action : 'disable';
|
||||||
//调用启用、禁用的方法
|
//调用启用、禁用的方法
|
||||||
Service::$action($name, $force);
|
Service::$action($name, $force);
|
||||||
|
Cache::rm('__menu__');
|
||||||
$this->success(__('Operate successful'));
|
$this->success(__('Operate successful'));
|
||||||
}
|
}
|
||||||
catch (AddonException $e)
|
catch (AddonException $e)
|
||||||
|
|
@ -314,6 +316,7 @@ class Addon extends Backend
|
||||||
];
|
];
|
||||||
//调用更新的方法
|
//调用更新的方法
|
||||||
Service::upgrade($name, $extend);
|
Service::upgrade($name, $extend);
|
||||||
|
Cache::rm('__menu__');
|
||||||
$this->success(__('Operate successful'));
|
$this->success(__('Operate successful'));
|
||||||
}
|
}
|
||||||
catch (AddonException $e)
|
catch (AddonException $e)
|
||||||
|
|
@ -370,7 +373,10 @@ class Addon extends Backend
|
||||||
$list[] = $v;
|
$list[] = $v;
|
||||||
}
|
}
|
||||||
$total = count($list);
|
$total = count($list);
|
||||||
|
if ($limit)
|
||||||
|
{
|
||||||
$list = array_slice($list, $offset, $limit);
|
$list = array_slice($list, $offset, $limit);
|
||||||
|
}
|
||||||
$result = array("total" => $total, "rows" => $list);
|
$result = array("total" => $total, "rows" => $list);
|
||||||
|
|
||||||
$callback = $this->request->get('callback') ? "jsonp" : "json";
|
$callback = $this->request->get('callback') ? "jsonp" : "json";
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,21 @@ class Index extends Backend
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
//
|
//左侧菜单
|
||||||
$menulist = $this->auth->getSidebar([
|
$menulist = $this->auth->getSidebar([
|
||||||
'dashboard' => 'hot',
|
'dashboard' => 'hot',
|
||||||
'addon' => ['new', 'red', 'badge'],
|
'addon' => ['new', 'red', 'badge'],
|
||||||
'auth/rule' => 'side',
|
'auth/rule' => __('Menu'),
|
||||||
'general' => ['new', 'purple'],
|
'general' => ['new', 'purple'],
|
||||||
], $this->view->site['fixedpage']);
|
], $this->view->site['fixedpage']);
|
||||||
|
$action = $this->request->request('action');
|
||||||
|
if ($this->request->isPost())
|
||||||
|
{
|
||||||
|
if ($action == 'refreshmenu')
|
||||||
|
{
|
||||||
|
$this->success('', null, ['menulist' => $menulist]);
|
||||||
|
}
|
||||||
|
}
|
||||||
$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();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,6 @@ return [
|
||||||
'Menu tips' => '规则任意,不可重复,仅做层级显示,无需匹配控制器和方法',
|
'Menu tips' => '规则任意,不可重复,仅做层级显示,无需匹配控制器和方法',
|
||||||
'Node tips' => '控制器/方法名',
|
'Node tips' => '控制器/方法名',
|
||||||
'The non-menu rule must have parent' => '非菜单规则节点必须有父级',
|
'The non-menu rule must have parent' => '非菜单规则节点必须有父级',
|
||||||
'If not necessary, use the command line to build rule' => '非必要情况下请直接使用命令行php think menu来生成',
|
'If not necessary, use the command line to build rule' => '非必要情况下请直接使用命令行<a href="http://doc.fastadmin.net/docs/command.html#一键生成菜单" target="_blank">php think menu</a>来生成',
|
||||||
'Name only supports letters, numbers, underscore and slash' => 'URL规则只能是小写字母、数字、下划线和/组成',
|
'Name only supports letters, numbers, underscore and slash' => 'URL规则只能是小写字母、数字、下划线和/组成',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ return [
|
||||||
'Avatar' => '头像',
|
'Avatar' => '头像',
|
||||||
'Level' => '等级',
|
'Level' => '等级',
|
||||||
'Gender' => '性别',
|
'Gender' => '性别',
|
||||||
|
'Male' => '男',
|
||||||
|
'FeMale' => '女',
|
||||||
'Birthday' => '生日',
|
'Birthday' => '生日',
|
||||||
'Bio' => '格言',
|
'Bio' => '格言',
|
||||||
'Score' => '积分',
|
'Score' => '积分',
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ class Auth extends \fast\Auth
|
||||||
$groupIds[] = $v['id'];
|
$groupIds[] = $v['id'];
|
||||||
}
|
}
|
||||||
// 取出所有分组
|
// 取出所有分组
|
||||||
$groupList = model('AuthGroup')->all(['status' => 'normal']);
|
$groupList = \app\admin\model\AuthGroup::where(['status' => 'normal'])->select();
|
||||||
$objList = [];
|
$objList = [];
|
||||||
foreach ($groups as $K => $v)
|
foreach ($groups as $K => $v)
|
||||||
{
|
{
|
||||||
|
|
@ -310,8 +310,8 @@ class Auth extends \fast\Auth
|
||||||
if (!$this->isSuperAdmin())
|
if (!$this->isSuperAdmin())
|
||||||
{
|
{
|
||||||
$groupIds = $this->getChildrenGroupIds(false);
|
$groupIds = $this->getChildrenGroupIds(false);
|
||||||
$authGroupList = model('AuthGroupAccess')
|
$authGroupList = \app\admin\model\AuthGroupAccess::
|
||||||
->field('uid,group_id')
|
field('uid,group_id')
|
||||||
->where('group_id', 'in', $groupIds)
|
->where('group_id', 'in', $groupIds)
|
||||||
->select();
|
->select();
|
||||||
|
|
||||||
|
|
@ -407,7 +407,7 @@ class Auth extends \fast\Auth
|
||||||
$select_id = 0;
|
$select_id = 0;
|
||||||
$pinyin = new \Overtrue\Pinyin\Pinyin('Overtrue\Pinyin\MemoryFileDictLoader');
|
$pinyin = new \Overtrue\Pinyin\Pinyin('Overtrue\Pinyin\MemoryFileDictLoader');
|
||||||
// 必须将结果集转换为数组
|
// 必须将结果集转换为数组
|
||||||
$ruleList = collection(model('AuthRule')->where('status', 'normal')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
|
$ruleList = collection(\app\admin\model\AuthRule::where('status', 'normal')->where('ismenu', 1)->order('weigh', 'desc')->cache("__menu__")->select())->toArray();
|
||||||
foreach ($ruleList as $k => &$v)
|
foreach ($ruleList as $k => &$v)
|
||||||
{
|
{
|
||||||
if (!in_array($v['name'], $userRule))
|
if (!in_array($v['name'], $userRule))
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,8 @@ trait Backend
|
||||||
{
|
{
|
||||||
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
||||||
}
|
}
|
||||||
$count = $this->model->where($this->model->getPk(), 'in', $ids)->update($values);
|
$this->model->where($this->model->getPk(), 'in', $ids);
|
||||||
|
$count = $this->model->allowField(true)->isUpdate(true)->save($values);
|
||||||
if ($count)
|
if ($count)
|
||||||
{
|
{
|
||||||
$this->success();
|
$this->success();
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace app\admin\model;
|
namespace app\admin\model;
|
||||||
|
|
||||||
|
use think\Cache;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
||||||
class AuthRule extends Model
|
class AuthRule extends Model
|
||||||
|
|
@ -13,8 +14,16 @@ class AuthRule extends Model
|
||||||
protected $createTime = 'createtime';
|
protected $createTime = 'createtime';
|
||||||
protected $updateTime = 'updatetime';
|
protected $updateTime = 'updatetime';
|
||||||
|
|
||||||
|
protected static function init()
|
||||||
|
{
|
||||||
|
self::afterWrite(function ($row) {
|
||||||
|
Cache::rm('__menu__');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public function getTitleAttr($value, $data)
|
public function getTitleAttr($value, $data)
|
||||||
{
|
{
|
||||||
return __($value);
|
return __($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@
|
||||||
.payimg .alipaycode {position:absolute;left:265px;top:442px;}
|
.payimg .alipaycode {position:absolute;left:265px;top:442px;}
|
||||||
.payimg .wechatcode {position:absolute;left:660px;top:442px;}
|
.payimg .wechatcode {position:absolute;left:660px;top:442px;}
|
||||||
.thumbnail img{width:100%;}
|
.thumbnail img{width:100%;}
|
||||||
|
.fixed-table-toolbar .pull-right.search {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
.status-disabled .noimage {
|
||||||
|
background:#d2d6de;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<div id="warmtips" class="alert alert-dismissable alert-danger hide">
|
<div id="warmtips" class="alert alert-dismissable alert-danger hide">
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
|
|
@ -158,10 +164,10 @@
|
||||||
</table>
|
</table>
|
||||||
</script>
|
</script>
|
||||||
<script id="itemtpl" type="text/html">
|
<script id="itemtpl" type="text/html">
|
||||||
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 mt-4">
|
|
||||||
<% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %>
|
<% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %>
|
||||||
<% var label = labelarr[item.id % 5]; %>
|
<% var label = labelarr[item.id % 5]; %>
|
||||||
<% var addon = typeof addons[item.name]!= 'undefined' ? addons[item.name] : null; %>
|
<% var addon = typeof addons[item.name]!= 'undefined' ? addons[item.name] : null; %>
|
||||||
|
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 mt-4 status-<%=addon ? (addon.state==1?'enabled':'disabled') : 'uninstalled'%>">
|
||||||
<div class="thumbnail addon">
|
<div class="thumbnail addon">
|
||||||
<%if(addon){%>
|
<%if(addon){%>
|
||||||
<span>
|
<span>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
<label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
|
<label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
|
||||||
<div class="col-xs-12 col-sm-8">
|
<div class="col-xs-12 col-sm-8">
|
||||||
<div class="input-group input-groupp-md">
|
<div class="input-group input-groupp-md">
|
||||||
<input type="text" class="form-control" id="icon" name="row[icon]" value="fa fa-dot" />
|
<input type="text" class="form-control" id="icon" name="row[icon]" value="fa fa-circle-o" />
|
||||||
<a href="javascript:;" class="btn-search-icon input-group-addon">{:__('Search icon')}</a>
|
<a href="javascript:;" class="btn-search-icon input-group-addon">{:__('Search icon')}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
<style>
|
||||||
|
.bootstrap-table tr td .text-muted {color:#888;}
|
||||||
|
</style>
|
||||||
<div class="panel panel-default panel-intro">
|
<div class="panel panel-default panel-intro">
|
||||||
{:build_heading()}
|
{:build_heading()}
|
||||||
|
|
||||||
|
|
@ -6,7 +9,17 @@
|
||||||
<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()}
|
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
|
||||||
|
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('auth/rule/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
|
||||||
|
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('auth/rule/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
|
||||||
|
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('auth/rule/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
|
||||||
|
<div class="dropdown btn-group {:$auth->check('auth/rule/multi')?'':'hide'}">
|
||||||
|
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
||||||
|
<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>
|
||||||
<a href="javascript:;" class="btn btn-danger btn-toggle-all"><i class="fa fa-plus"></i> {:__('Toggle all')}</a>
|
<a href="javascript:;" class="btn btn-danger btn-toggle-all"><i class="fa fa-plus"></i> {:__('Toggle all')}</a>
|
||||||
</div>
|
</div>
|
||||||
<table id="table" class="table table-bordered table-hover"
|
<table id="table" class="table table-bordered table-hover"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="panel panel-default panel-intro">
|
<div class="panel panel-default panel-intro">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
{:build_heading()}
|
{:build_heading(null,FALSE)}
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li class="active"><a href="#all" data-toggle="tab">{:__('All')}</a></li>
|
<li class="active"><a href="#all" data-toggle="tab">{:__('All')}</a></li>
|
||||||
{foreach name="typeList" item="vo"}
|
{foreach name="typeList" item="vo"}
|
||||||
|
|
|
||||||
|
|
@ -43,147 +43,15 @@
|
||||||
<li><a href="javascript:;" data-skin="skin-yellow-light" class="clearfix full-opacity-hover"><div><span style="display:block; width: 20%; float: left; height: 7px;" class="bg-yellow-active"></span><span class="bg-yellow" style="display:block; width: 80%; float: left; height: 7px;"></span></div><div><span style="display:block; width: 20%; float: left; height: 20px; background: #f9fafc;"></span><span style="display:block; width: 80%; float: left; height: 20px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin" style="font-size: 12px;">Yellow Light</p></li>
|
<li><a href="javascript:;" data-skin="skin-yellow-light" class="clearfix full-opacity-hover"><div><span style="display:block; width: 20%; float: left; height: 7px;" class="bg-yellow-active"></span><span class="bg-yellow" style="display:block; width: 80%; float: left; height: 7px;"></span></div><div><span style="display:block; width: 20%; float: left; height: 20px; background: #f9fafc;"></span><span style="display:block; width: 80%; float: left; height: 20px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin" style="font-size: 12px;">Yellow Light</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane" id="control-sidebar-home-tab">
|
|
||||||
<h3 class="control-sidebar-heading">{:__('Recent Activity')}</h3>
|
|
||||||
<ul class="control-sidebar-menu">
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<i class="menu-icon fa fa-birthday-cake bg-red"></i>
|
|
||||||
|
|
||||||
<div class="menu-info">
|
|
||||||
<h4 class="control-sidebar-subheading">Langdon's Birthday</h4>
|
|
||||||
|
|
||||||
<p>Will be 23 on April 24th</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<i class="menu-icon fa fa-user bg-yellow"></i>
|
|
||||||
|
|
||||||
<div class="menu-info">
|
|
||||||
<h4 class="control-sidebar-subheading">Frodo Updated His Profile</h4>
|
|
||||||
|
|
||||||
<p>New phone +1(800)555-1234</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<i class="menu-icon fa fa-envelope-o bg-light-blue"></i>
|
|
||||||
|
|
||||||
<div class="menu-info">
|
|
||||||
<h4 class="control-sidebar-subheading">Nora Joined Mailing List</h4>
|
|
||||||
|
|
||||||
<p>nora@example.com</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<i class="menu-icon fa fa-file-code-o bg-green"></i>
|
|
||||||
|
|
||||||
<div class="menu-info">
|
|
||||||
<h4 class="control-sidebar-subheading">Cron Job 254 Executed</h4>
|
|
||||||
|
|
||||||
<p>Execution time 5 seconds</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<!-- /.control-sidebar-menu -->
|
|
||||||
|
|
||||||
<h3 class="control-sidebar-heading">{:__('Tasks Progress')}</h3>
|
|
||||||
<ul class="control-sidebar-menu">
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<h4 class="control-sidebar-subheading">
|
|
||||||
Custom Template Design
|
|
||||||
<span class="label label-danger pull-right">70%</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="progress progress-xxs">
|
|
||||||
<div class="progress-bar progress-bar-danger" style="width: 70%"></div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<h4 class="control-sidebar-subheading">
|
|
||||||
Update Resume
|
|
||||||
<span class="label label-success pull-right">95%</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="progress progress-xxs">
|
|
||||||
<div class="progress-bar progress-bar-success" style="width: 95%"></div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<h4 class="control-sidebar-subheading">
|
|
||||||
Laravel Integration
|
|
||||||
<span class="label label-warning pull-right">50%</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="progress progress-xxs">
|
|
||||||
<div class="progress-bar progress-bar-warning" style="width: 50%"></div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="javascript:void(0)">
|
|
||||||
<h4 class="control-sidebar-subheading">
|
|
||||||
Back End Framework
|
|
||||||
<span class="label label-primary pull-right">68%</span>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div class="progress progress-xxs">
|
|
||||||
<div class="progress-bar progress-bar-primary" style="width: 68%"></div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<!-- /.control-sidebar-menu -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<!-- /.tab-pane -->
|
<!-- /.tab-pane -->
|
||||||
<!-- Stats tab content -->
|
<!-- Home tab content -->
|
||||||
<div class="tab-pane" id="control-sidebar-stats-tab">Stats Tab Content</div>
|
<div class="tab-pane" id="control-sidebar-home-tab">
|
||||||
|
<h4 class="control-sidebar-heading">{:__('Home')}</h4>
|
||||||
|
</div>
|
||||||
<!-- /.tab-pane -->
|
<!-- /.tab-pane -->
|
||||||
<!-- Settings tab content -->
|
<!-- Settings tab content -->
|
||||||
<div class="tab-pane" id="control-sidebar-settings-tab">
|
<div class="tab-pane" id="control-sidebar-settings-tab">
|
||||||
<form method="post">
|
<h4 class="control-sidebar-heading">{:__('Setting')}</h4>
|
||||||
<h3 class="control-sidebar-heading">General Settings</h3>
|
|
||||||
|
|
||||||
<!-- /.form-group -->
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-sidebar-subheading">
|
|
||||||
Allow mail redirect
|
|
||||||
<input type="checkbox" class="pull-right" checked>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Other sets of options are available
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<!-- /.form-group -->
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-sidebar-subheading">
|
|
||||||
Expose author name in posts
|
|
||||||
<input type="checkbox" class="pull-right" checked>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Allow the user to show his name in blog posts
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<!-- /.form-group -->
|
|
||||||
|
|
||||||
<!-- /.form-group -->
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.tab-pane -->
|
<!-- /.tab-pane -->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<a href="javascript:;" class="logo">
|
<a href="javascript:;" class="logo hidden-xs">
|
||||||
<!-- 迷你模式下Logo的大小为50X50 -->
|
<!-- 迷你模式下Logo的大小为50X50 -->
|
||||||
<span class="logo-mini">{$site.name|mb_substr=0,4,'utf-8'|mb_strtoupper='utf-8'}</span>
|
<span class="logo-mini">{$site.name|mb_substr=0,4,'utf-8'|mb_strtoupper='utf-8'}</span>
|
||||||
<!-- 普通模式下Logo -->
|
<!-- 普通模式下Logo -->
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@
|
||||||
<!--如果想始终显示子菜单,则给ul加上show-submenu类即可-->
|
<!--如果想始终显示子菜单,则给ul加上show-submenu类即可-->
|
||||||
<ul class="sidebar-menu">
|
<ul class="sidebar-menu">
|
||||||
{$menulist}
|
{$menulist}
|
||||||
<li class="header">{:__('Links')}</li>
|
<li class="header" data-rel="external">{:__('Links')}</li>
|
||||||
<li><a href="http://doc.fastadmin.net" target="_blank"><i class="fa fa-list text-red"></i> <span>{:__('Docs')}</span></a></li>
|
<li data-rel="external"><a href="http://doc.fastadmin.net" target="_blank"><i class="fa fa-list text-red"></i> <span>{:__('Docs')}</span></a></li>
|
||||||
<li><a href="http://forum.fastadmin.net" target="_blank"><i class="fa fa-comment text-yellow"></i> <span>{:__('Forum')}</span></a></li>
|
<li data-rel="external"><a href="http://forum.fastadmin.net" target="_blank"><i class="fa fa-comment text-yellow"></i> <span>{:__('Forum')}</span></a></li>
|
||||||
<li><a href="https://jq.qq.com/?_wv=1027&k=487PNBb" target="_blank"><i class="fa fa-qq text-aqua"></i> <span>{:__('QQ qun')}</span></a></li>
|
<li data-rel="external"><a href="https://jq.qq.com/?_wv=1027&k=487PNBb" target="_blank"><i class="fa fa-qq text-aqua"></i> <span>{:__('QQ qun')}</span></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<!-- /.sidebar -->
|
<!-- /.sidebar -->
|
||||||
|
|
@ -1 +1 @@
|
||||||
<script src="__CDN__/assets/js/require.js" data-main="__CDN__/assets/js/require-backend{$Think.config.app_debug?'':'.min'}.js?v={$site.version}"></script>
|
<script src="__CDN__/assets/js/require{$Think.config.app_debug?'':'.min'}.js" data-main="__CDN__/assets/js/require-backend{$Think.config.app_debug?'':'.min'}.js?v={$site.version}"></script>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="tab-pane fade active in" id="one">
|
<div class="tab-pane fade active in" id="one">
|
||||||
<div class="widget-body no-padding">
|
<div class="widget-body no-padding">
|
||||||
<div id="toolbar" class="toolbar">
|
<div id="toolbar" class="toolbar">
|
||||||
{:build_toolbar()}
|
{:build_toolbar('refresh,add,edit,del')}
|
||||||
<div class="dropdown btn-group {:$auth->check('user/rule/multi')?'':'hide'}">
|
<div class="dropdown btn-group {:$auth->check('user/rule/multi')?'':'hide'}">
|
||||||
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
||||||
<ul class="dropdown-menu text-left" role="menu">
|
<ul class="dropdown-menu text-left" role="menu">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
//配置文件
|
//配置文件
|
||||||
return [
|
return [
|
||||||
|
'exception_handle' => '\\app\\api\\library\\ExceptionHandle',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace app\api\controller;
|
namespace app\api\controller;
|
||||||
|
|
||||||
use app\api\model\Area;
|
|
||||||
use app\common\controller\Api;
|
use app\common\controller\Api;
|
||||||
use fast\Version;
|
use app\common\model\Area;
|
||||||
|
use app\common\model\Version;
|
||||||
use fast\Random;
|
use fast\Random;
|
||||||
use think\Config;
|
use think\Config;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\api\library;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use think\exception\Handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义API模块的错误显示
|
||||||
|
*/
|
||||||
|
class ExceptionHandle extends Handle
|
||||||
|
{
|
||||||
|
|
||||||
|
public function render(Exception $e)
|
||||||
|
{
|
||||||
|
// 在生产环境下返回code信息
|
||||||
|
if (!\think\Config::get('app_debug'))
|
||||||
|
{
|
||||||
|
$statuscode = $code = 500;
|
||||||
|
$msg = 'An error occurred';
|
||||||
|
// 验证异常
|
||||||
|
if ($e instanceof \think\exception\ValidateException)
|
||||||
|
{
|
||||||
|
$code = 0;
|
||||||
|
$statuscode = 200;
|
||||||
|
$msg = $e->getError();
|
||||||
|
}
|
||||||
|
// Http异常
|
||||||
|
if ($e instanceof \think\exception\HttpException)
|
||||||
|
{
|
||||||
|
$statuscode = $code = $e->getStatusCode();
|
||||||
|
}
|
||||||
|
return json(['code' => $code, 'msg' => $msg, 'time' => time(), 'data' => null], $statuscode);
|
||||||
|
}
|
||||||
|
|
||||||
|
//其它此交由系统处理
|
||||||
|
return parent::render($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -16,4 +16,5 @@ return [
|
||||||
'app\admin\command\Install',
|
'app\admin\command\Install',
|
||||||
'app\admin\command\Min',
|
'app\admin\command\Min',
|
||||||
'app\admin\command\Addon',
|
'app\admin\command\Addon',
|
||||||
|
'app\admin\command\Api',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ if (!function_exists('__'))
|
||||||
array_shift($vars);
|
array_shift($vars);
|
||||||
$lang = '';
|
$lang = '';
|
||||||
}
|
}
|
||||||
return think\Lang::get($name, $vars, $lang);
|
return \think\Lang::get($name, $vars, $lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ if (!function_exists('cdnurl'))
|
||||||
*/
|
*/
|
||||||
function cdnurl($url)
|
function cdnurl($url)
|
||||||
{
|
{
|
||||||
return preg_match("/^https?:\/\/(.*)/i", $url) ? $url : think\Config::get('upload.cdnurl') . $url;
|
return preg_match("/^https?:\/\/(.*)/i", $url) ? $url : \think\Config::get('upload.cdnurl') . $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +208,6 @@ if (!function_exists('mb_ucfirst'))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!function_exists('addtion'))
|
if (!function_exists('addtion'))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -300,3 +299,37 @@ if (!function_exists('addtion'))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!function_exists('var_export_short'))
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回打印数组结构
|
||||||
|
* @param string $var 数组
|
||||||
|
* @param string $indent 缩进字符
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function var_export_short($var, $indent = "")
|
||||||
|
{
|
||||||
|
switch (gettype($var))
|
||||||
|
{
|
||||||
|
case "string":
|
||||||
|
return '"' . addcslashes($var, "\\\$\"\r\n\t\v\f") . '"';
|
||||||
|
case "array":
|
||||||
|
$indexed = array_keys($var) === range(0, count($var) - 1);
|
||||||
|
$r = [];
|
||||||
|
foreach ($var as $key => $value)
|
||||||
|
{
|
||||||
|
$r[] = "$indent "
|
||||||
|
. ($indexed ? "" : var_export_short($key) . " => ")
|
||||||
|
. var_export_short($value, "$indent ");
|
||||||
|
}
|
||||||
|
return "[\n" . implode(",\n", $r) . "\n" . $indent . "]";
|
||||||
|
case "boolean":
|
||||||
|
return $var ? "TRUE" : "FALSE";
|
||||||
|
default:
|
||||||
|
return var_export($var, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -52,6 +52,11 @@ class Common
|
||||||
{
|
{
|
||||||
Config::set('app_trace', false);
|
Config::set('app_trace', false);
|
||||||
}
|
}
|
||||||
|
// 切换多语言
|
||||||
|
if (Config::get('lang_switch_on') && $request->get('lang'))
|
||||||
|
{
|
||||||
|
\think\Cookie::set('think_var', $request->get('lang'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addonBegin(&$request)
|
public function addonBegin(&$request)
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ class Api
|
||||||
$actionname = strtolower($this->request->action());
|
$actionname = strtolower($this->request->action());
|
||||||
|
|
||||||
// token
|
// token
|
||||||
$token = $this->request->request('token') ?: $this->request->cookie('token');
|
$token = $this->request->server('HTTP_TOKEN', $this->request->request('token', \think\Cookie::get('token')));
|
||||||
|
|
||||||
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||||
// 设置当前请求的URI
|
// 设置当前请求的URI
|
||||||
|
|
@ -104,7 +104,7 @@ class Api
|
||||||
//检测是否登录
|
//检测是否登录
|
||||||
if (!$this->auth->isLogin())
|
if (!$this->auth->isLogin())
|
||||||
{
|
{
|
||||||
$this->error(__('Please login first'));
|
$this->error(__('Please login first'), null, 401);
|
||||||
}
|
}
|
||||||
// 判断是否需要验证权限
|
// 判断是否需要验证权限
|
||||||
if (!$this->auth->match($this->noNeedRight))
|
if (!$this->auth->match($this->noNeedRight))
|
||||||
|
|
@ -112,7 +112,7 @@ class Api
|
||||||
// 判断控制器和方法判断是否有对应权限
|
// 判断控制器和方法判断是否有对应权限
|
||||||
if (!$this->auth->check($path))
|
if (!$this->auth->check($path))
|
||||||
{
|
{
|
||||||
$this->error(__('You have no permission'));
|
$this->error(__('You have no permission'), null, 403);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -141,38 +141,40 @@ class Api
|
||||||
* 操作成功返回的数据
|
* 操作成功返回的数据
|
||||||
* @param string $msg 提示信息
|
* @param string $msg 提示信息
|
||||||
* @param mixed $data 要返回的数据
|
* @param mixed $data 要返回的数据
|
||||||
|
* @param int $code 错误码,默认为1
|
||||||
* @param string $type 输出类型
|
* @param string $type 输出类型
|
||||||
* @param array $header 发送的 Header 信息
|
* @param array $header 发送的 Header 信息
|
||||||
*/
|
*/
|
||||||
protected function success($msg = '', $data = '', $type = 'json', array $header = [])
|
protected function success($msg = '', $data = null, $code = 1, $type = 'json', array $header = [])
|
||||||
{
|
{
|
||||||
$this->result($data, 1, $msg, $type, $header);
|
$this->result($msg, $data, $code, $type, $header);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作失败返回的数据
|
* 操作失败返回的数据
|
||||||
* @param string $msg 提示信息
|
* @param string $msg 提示信息
|
||||||
* @param mixed $data 要返回的数据
|
* @param mixed $data 要返回的数据
|
||||||
|
* @param int $code 错误码,默认为0
|
||||||
* @param string $type 输出类型
|
* @param string $type 输出类型
|
||||||
* @param array $header 发送的 Header 信息
|
* @param array $header 发送的 Header 信息
|
||||||
*/
|
*/
|
||||||
protected function error($msg = '', $data = '', $type = 'json', array $header = [])
|
protected function error($msg = '', $data = null, $code = 0, $type = 'json', array $header = [])
|
||||||
{
|
{
|
||||||
$this->result($data, 0, $msg, $type, $header);
|
$this->result($msg, $data, $code, $type, $header);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 返回封装后的 API 数据到客户端
|
* 返回封装后的 API 数据到客户端
|
||||||
* @access protected
|
* @access protected
|
||||||
|
* @param mixed $msg 提示信息
|
||||||
* @param mixed $data 要返回的数据
|
* @param mixed $data 要返回的数据
|
||||||
* @param int $code 返回的 code
|
* @param int $code 返回的 code
|
||||||
* @param mixed $msg 提示信息
|
|
||||||
* @param string $type 返回数据格式
|
* @param string $type 返回数据格式
|
||||||
* @param array $header 发送的 Header 信息
|
* @param array $header 发送的 Header 信息
|
||||||
* @return void
|
* @return void
|
||||||
* @throws HttpResponseException
|
* @throws HttpResponseException
|
||||||
*/
|
*/
|
||||||
protected function result($data, $code = 0, $msg = '', $type = '', array $header = [])
|
protected function result($msg, $data = null, $code = 0, $type = 'json', array $header = [])
|
||||||
{
|
{
|
||||||
$result = [
|
$result = [
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
|
|
@ -181,19 +183,20 @@ class Api
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
];
|
];
|
||||||
$type = $type ?: $this->getResponseType();
|
$type = $type ?: $this->getResponseType();
|
||||||
$response = Response::create($result, $type)->header($header);
|
if (isset($header['statuscode']))
|
||||||
|
{
|
||||||
|
$code = $header['statuscode'];
|
||||||
|
unset($header['statuscode']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$code = $code >= 1000 ? 200 : $code;
|
||||||
|
}
|
||||||
|
$response = Response::create($result, $type, $code)->header($header);
|
||||||
|
|
||||||
throw new HttpResponseException($response);
|
throw new HttpResponseException($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 未找到请求的接口
|
|
||||||
*/
|
|
||||||
public function _empty()
|
|
||||||
{
|
|
||||||
return $this->error('Api not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前置操作
|
* 前置操作
|
||||||
* @access protected
|
* @access protected
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ class Backend extends Controller
|
||||||
$url = preg_replace_callback("/([\?|&]+)ref=addtabs(&?)/i", function($matches) {
|
$url = preg_replace_callback("/([\?|&]+)ref=addtabs(&?)/i", function($matches) {
|
||||||
return $matches[2] == '&' ? $matches[1] : '';
|
return $matches[2] == '&' ? $matches[1] : '';
|
||||||
}, $this->request->url());
|
}, $this->request->url());
|
||||||
|
$url = url($url, '', false);
|
||||||
$this->redirect('index/index', [], 302, ['referer' => $url]);
|
$this->redirect('index/index', [], 302, ['referer' => $url]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
@ -290,6 +291,10 @@ class Backend extends Controller
|
||||||
case '<=':
|
case '<=':
|
||||||
$where[] = [$k, $sym, intval($v)];
|
$where[] = [$k, $sym, intval($v)];
|
||||||
break;
|
break;
|
||||||
|
case 'FINDIN':
|
||||||
|
case 'FIND_IN_SET':
|
||||||
|
$where[] = "FIND_IN_SET('{$v}', `{$k}`)";
|
||||||
|
break;
|
||||||
case 'IN':
|
case 'IN':
|
||||||
case 'IN(...)':
|
case 'IN(...)':
|
||||||
case 'NOT IN':
|
case 'NOT IN':
|
||||||
|
|
@ -401,21 +406,21 @@ class Backend extends Controller
|
||||||
//搜索关键词,客户端输入以空格分开,这里接收为数组
|
//搜索关键词,客户端输入以空格分开,这里接收为数组
|
||||||
$word = (array) $this->request->request("q_word/a");
|
$word = (array) $this->request->request("q_word/a");
|
||||||
//当前页
|
//当前页
|
||||||
$page = $this->request->request("page");
|
$page = $this->request->request("pageNumber");
|
||||||
//分页大小
|
//分页大小
|
||||||
$pagesize = $this->request->request("per_page");
|
$pagesize = $this->request->request("pageSize");
|
||||||
//搜索条件
|
//搜索条件
|
||||||
$andor = $this->request->request("and_or");
|
$andor = $this->request->request("andOr");
|
||||||
//排序方式
|
//排序方式
|
||||||
$orderby = (array) $this->request->request("order_by/a");
|
$orderby = (array) $this->request->request("orderBy/a");
|
||||||
//显示的字段
|
//显示的字段
|
||||||
$field = $this->request->request("field");
|
$field = $this->request->request("showField");
|
||||||
//主键
|
//主键
|
||||||
$primarykey = $this->request->request("pkey_name");
|
$primarykey = $this->request->request("keyField");
|
||||||
//主键值
|
//主键值
|
||||||
$primaryvalue = $this->request->request("pkey_value");
|
$primaryvalue = $this->request->request("keyValue");
|
||||||
//搜索字段
|
//搜索字段
|
||||||
$searchfield = (array) $this->request->request("search_field/a");
|
$searchfield = (array) $this->request->request("searchField/a");
|
||||||
//自定义搜索条件
|
//自定义搜索条件
|
||||||
$custom = (array) $this->request->request("custom/a");
|
$custom = (array) $this->request->request("custom/a");
|
||||||
$order = [];
|
$order = [];
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,7 @@ class Frontend extends Controller
|
||||||
$actionname = strtolower($this->request->action());
|
$actionname = strtolower($this->request->action());
|
||||||
|
|
||||||
// token
|
// token
|
||||||
$token = $this->request->request('token');
|
$token = $this->request->server('HTTP_TOKEN', $this->request->request('token', \think\Cookie::get('token')));
|
||||||
$token = $token ? $token : \think\Cookie::get('token');
|
|
||||||
|
|
||||||
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||||
// 设置当前请求的URI
|
// 设置当前请求的URI
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,97 @@ return [
|
||||||
'addon controller %s not found' => '插件控制器未找到',
|
'addon controller %s not found' => '插件控制器未找到',
|
||||||
'addon action %s not found' => '插件控制器方法未找到',
|
'addon action %s not found' => '插件控制器方法未找到',
|
||||||
'addon can not be empty' => '插件不能为空',
|
'addon can not be empty' => '插件不能为空',
|
||||||
|
'Keep login' => '保持会话',
|
||||||
|
'Forgot password' => '忘记密码?',
|
||||||
|
'Sign in' => '登入',
|
||||||
|
'Username' => '用户名',
|
||||||
|
'User id' => '会员ID',
|
||||||
|
'Username' => '用户名',
|
||||||
|
'Nickname' => '昵称',
|
||||||
|
'Password' => '密码',
|
||||||
|
'Sign up' => '注 册',
|
||||||
|
'Sign in' => '登 录',
|
||||||
|
'Sign out' => '注 销',
|
||||||
|
'Guest' => '游客',
|
||||||
|
'Welcome' => '%s,你好!',
|
||||||
|
'Add' => '添加',
|
||||||
|
'Edit' => '编辑',
|
||||||
|
'Delete' => '删除',
|
||||||
|
'Move' => '移动',
|
||||||
|
'Name' => '名称',
|
||||||
|
'Status' => '状态',
|
||||||
|
'Weigh' => '权重',
|
||||||
|
'Operate' => '操作',
|
||||||
|
'Warning' => '温馨提示',
|
||||||
|
'Default' => '默认',
|
||||||
|
'Article' => '文章',
|
||||||
|
'Page' => '单页',
|
||||||
|
'OK' => '确定',
|
||||||
|
'Cancel' => '取消',
|
||||||
|
'Loading' => '加载中',
|
||||||
|
'More' => '更多',
|
||||||
|
'Normal' => '正常',
|
||||||
|
'Hidden' => '隐藏',
|
||||||
|
'Submit' => '提交',
|
||||||
|
'Reset' => '重置',
|
||||||
|
'Execute' => '执行',
|
||||||
|
'Close' => '关闭',
|
||||||
|
'Search' => '搜索',
|
||||||
|
'Refresh' => '刷新',
|
||||||
|
'First' => '首页',
|
||||||
|
'Previous' => '上一页',
|
||||||
|
'Next' => '下一页',
|
||||||
|
'Last' => '末页',
|
||||||
|
'None' => '无',
|
||||||
|
'Home' => '主页',
|
||||||
|
'Online' => '在线',
|
||||||
|
'Logout' => '注销',
|
||||||
|
'Profile' => '个人资料',
|
||||||
|
'Index' => '首页',
|
||||||
|
'Hot' => '热门',
|
||||||
|
'Recommend' => '推荐',
|
||||||
|
'Dashboard' => '控制台',
|
||||||
|
'Code' => '编号',
|
||||||
|
'Message' => '内容',
|
||||||
|
'Line' => '行号',
|
||||||
|
'File' => '文件',
|
||||||
|
'Menu' => '菜单',
|
||||||
|
'Name' => '名称',
|
||||||
|
'Weigh' => '权重',
|
||||||
|
'Type' => '类型',
|
||||||
|
'Title' => '标题',
|
||||||
|
'Content' => '内容',
|
||||||
|
'Status' => '状态',
|
||||||
|
'Operate' => '操作',
|
||||||
|
'Append' => '追加',
|
||||||
|
'Memo' => '备注',
|
||||||
|
'Parent' => '父级',
|
||||||
|
'Params' => '参数',
|
||||||
|
'Permission' => '权限',
|
||||||
|
'Begin time' => '开始时间',
|
||||||
|
'End time' => '结束时间',
|
||||||
|
'Create time' => '创建时间',
|
||||||
|
'Flag' => '标志',
|
||||||
|
'Home' => '首页',
|
||||||
|
'Store' => '插件市场',
|
||||||
|
'Services' => '服务',
|
||||||
|
'Download' => '下载',
|
||||||
|
'Demo' => '演示',
|
||||||
|
'Donation' => '捐赠',
|
||||||
|
'Forum' => '社区',
|
||||||
|
'Docs' => '文档',
|
||||||
|
'Please login first' => '请登录后再操作',
|
||||||
|
'Send verification code' => '发送验证码',
|
||||||
|
'Redirect now' => '立即跳转',
|
||||||
|
'Operation completed' => '操作成功!',
|
||||||
|
'Operation failed' => '操作失败!',
|
||||||
|
'Unknown data format' => '未知的数据格式!',
|
||||||
|
'Network error' => '网络错误!',
|
||||||
|
'Advanced search' => '高级搜索',
|
||||||
|
'Invalid parameters' => '未知参数',
|
||||||
|
'No results were found' => '记录未找到',
|
||||||
|
'Parameter %s can not be empty' => '参数%s不能为空',
|
||||||
|
'You have no permission' => '你没有权限访问',
|
||||||
|
'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中',
|
||||||
|
'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转',
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,28 @@ class Menu
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出指定名称的菜单规则
|
||||||
|
* @param string $name
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function export($name)
|
||||||
|
{
|
||||||
|
$ids = self::getAuthRuleIdsByName($name);
|
||||||
|
if (!$ids)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$menuList = [];
|
||||||
|
$menu = AuthRule::getByName($name);
|
||||||
|
if ($menu)
|
||||||
|
{
|
||||||
|
$ruleList = collection(AuthRule::where('id', 'in', $ids)->select())->toArray();
|
||||||
|
$menuList = Tree::instance()->init($ruleList)->getTreeArray($menu['id']);
|
||||||
|
}
|
||||||
|
return $menuList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据名称获取规则IDS
|
* 根据名称获取规则IDS
|
||||||
* @param string $name
|
* @param string $name
|
||||||
|
|
@ -112,7 +134,7 @@ class Menu
|
||||||
if ($menu)
|
if ($menu)
|
||||||
{
|
{
|
||||||
// 必须将结果集转换为数组
|
// 必须将结果集转换为数组
|
||||||
$ruleList = collection(model('AuthRule')->order('weigh', 'desc')->field('id,pid,name')->select())->toArray();
|
$ruleList = collection(AuthRule::order('weigh', 'desc')->field('id,pid,name')->select())->toArray();
|
||||||
// 构造菜单数据
|
// 构造菜单数据
|
||||||
$ids = Tree::instance()->init($ruleList)->getChildrenIds($menu['id'], true);
|
$ids = Tree::instance()->init($ruleList)->getChildrenIds($menu['id'], true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace app\api\model;
|
namespace app\common\model;
|
||||||
|
|
||||||
use think\Cache;
|
use think\Cache;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
@ -11,7 +11,7 @@ class ScoreLog Extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
// 表名
|
// 表名
|
||||||
protected $name = 'score_log';
|
protected $name = 'user_score_log';
|
||||||
// 开启自动写入时间戳字段
|
// 开启自动写入时间戳字段
|
||||||
protected $autoWriteTimestamp = 'int';
|
protected $autoWriteTimestamp = 'int';
|
||||||
// 定义时间戳字段名
|
// 定义时间戳字段名
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\common\model;
|
||||||
|
|
||||||
|
use think\Model;
|
||||||
|
|
||||||
|
class Version extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
// 开启自动写入时间戳字段
|
||||||
|
protected $autoWriteTimestamp = 'int';
|
||||||
|
// 定义时间戳字段名
|
||||||
|
protected $createTime = 'createtime';
|
||||||
|
protected $updateTime = 'updatetime';
|
||||||
|
// 定义字段类型
|
||||||
|
protected $type = [
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测版本号
|
||||||
|
*
|
||||||
|
* @param string $version 客户端版本号
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function check($version)
|
||||||
|
{
|
||||||
|
$versionlist = self::where('status', 'normal')->cache('__version__')->order('weigh desc,id desc')->select();
|
||||||
|
foreach ($versionlist as $k => $v)
|
||||||
|
{
|
||||||
|
// 版本正常且新版本号不等于验证的版本号且找到匹配的旧版本
|
||||||
|
if ($v['status'] == 'normal' && $v['newversion'] !== $version && \fast\Version::check($version, $v['oldversion']))
|
||||||
|
{
|
||||||
|
$updateversion = $v;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($updateversion))
|
||||||
|
{
|
||||||
|
$search = ['{version}', '{newversion}', '{downloadurl}', '{url}', '{packagesize}'];
|
||||||
|
$replace = [$version, $updateversion['newversion'], $updateversion['downloadurl'], $updateversion['downloadurl'], $updateversion['packagesize']];
|
||||||
|
$upgradetext = str_replace($search, $replace, $updateversion['content']);
|
||||||
|
return [
|
||||||
|
"enforce" => $updateversion['enforce'],
|
||||||
|
"version" => $version,
|
||||||
|
"newversion" => $updateversion['newversion'],
|
||||||
|
"downloadurl" => $updateversion['downloadurl'],
|
||||||
|
"packagesize" => $updateversion['packagesize'],
|
||||||
|
"upgradetext" => $upgradetext
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -253,7 +253,7 @@ return [
|
||||||
//自动检测更新
|
//自动检测更新
|
||||||
'checkupdate' => false,
|
'checkupdate' => false,
|
||||||
//版本号
|
//版本号
|
||||||
'version' => '1.0.0.20180227_beta',
|
'version' => '1.0.0.20180308_beta',
|
||||||
'api_url' => 'http://api.fastadmin.net',
|
'api_url' => 'http://api.fastadmin.net',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ return [
|
||||||
'Forum' => '社区',
|
'Forum' => '社区',
|
||||||
'Docs' => '文档',
|
'Docs' => '文档',
|
||||||
'Please login first' => '请登录后再操作',
|
'Please login first' => '请登录后再操作',
|
||||||
'Send verification code' => '发磅验证码',
|
'Send verification code' => '发送验证码',
|
||||||
'Redirect now' => '立即跳转',
|
'Redirect now' => '立即跳转',
|
||||||
'Operation completed' => '操作成功!',
|
'Operation completed' => '操作成功!',
|
||||||
'Operation failed' => '操作失败!',
|
'Operation failed' => '操作失败!',
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<script src="__CDN__/assets/js/require.js" data-main="__CDN__/assets/js/require-frontend{$Think.config.app_debug?'':'.min'}.js?v={$site.version}"></script>
|
<script src="__CDN__/assets/js/require{$Think.config.app_debug?'':'.min'}.js" data-main="__CDN__/assets/js/require-frontend{$Think.config.app_debug?'':'.min'}.js?v={$site.version}"></script>
|
||||||
|
|
@ -174,11 +174,9 @@
|
||||||
$("#mainNav").toggleClass("affix", $(window).height() - $(window).scrollTop() <= 50);
|
$("#mainNav").toggleClass("affix", $(window).height() - $(window).scrollTop() <= 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//发送版本统计信息
|
//发送版本统计信息
|
||||||
try {
|
try {
|
||||||
var installed = localStorage.getItem("installed");
|
var installed = localStorage.getItem("installed");
|
||||||
console.log(installed);
|
|
||||||
if (!installed) {
|
if (!installed) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{$Think.config.fastadmin.api_url}/statistics/installed",
|
url: "{$Think.config.fastadmin.api_url}/statistics/installed",
|
||||||
|
|
|
||||||
24
bower.json
24
bower.json
|
|
@ -8,37 +8,31 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jquery": "^2.1.4",
|
"jquery": "^2.1.4",
|
||||||
"bootstrap": "^3.3.7",
|
"bootstrap": "^3.3.7",
|
||||||
"font-awesome": "fontawesome#^4.6.1",
|
"font-awesome": "^4.6.1",
|
||||||
"bootstrap-table": "^1.11.0",
|
"bootstrap-table": "^1.11.0",
|
||||||
"layer": "*",
|
"layer": "^3.0",
|
||||||
"jstree": "^3.3.2",
|
"jstree": "^3.3.2",
|
||||||
"summernote": "^0.8.2",
|
|
||||||
"jquery-pjax": "^1.9.6",
|
|
||||||
"moment": "^2.15.2",
|
"moment": "^2.15.2",
|
||||||
"plupload": "^2.2.0",
|
"plupload": "^2.2.0",
|
||||||
"toastr": "^2.1.3",
|
"toastr": "^2.1.3",
|
||||||
"devbridge-autocomplete": "^1.2.26",
|
"jcrop": "^2.0.4",
|
||||||
"jcrop": "jcrop#^2.0.4",
|
|
||||||
"jquery-qrcode": "*",
|
|
||||||
"eonasdan-bootstrap-datetimepicker": "^4.17.43",
|
"eonasdan-bootstrap-datetimepicker": "^4.17.43",
|
||||||
"bootstrap-select": "^1.11.2",
|
"bootstrap-select": "^1.11.2",
|
||||||
"require-css": "^0.1.8",
|
"require-css": "^0.1.8",
|
||||||
"less": "^2.7.1",
|
"less": "^2.7.1",
|
||||||
"tableExport.jquery.plugin": "^1.9.0",
|
"tableExport.jquery.plugin": "^1.9.0",
|
||||||
"jquery-slimscroll": "slimscroll#^1.3.8",
|
"jquery-slimscroll": "^1.3.8",
|
||||||
"jquery.cookie": "^1.4.1",
|
"jquery.cookie": "^1.4.1",
|
||||||
"Sortable": "^1.5.0",
|
"Sortable": "^1.5.0",
|
||||||
"nice-validator": "^1.1.1",
|
"nice-validator": "^1.1.1",
|
||||||
"art-template": "^3.0.1",
|
"art-template": "^3.0.1",
|
||||||
"requirejs-plugins": "^1.0.3",
|
"requirejs-plugins": "^1.0.3",
|
||||||
"bootstrap-daterangepicker": "^2.1.25",
|
"bootstrap-daterangepicker": "^2.1.25",
|
||||||
"city-picker":"^1.1.0"
|
"city-picker": "^1.1.0",
|
||||||
},
|
"fastadmin-cxselect": "~1.4.0",
|
||||||
"devDependencies": {
|
"fastadmin-dragsort": "~1.0.0",
|
||||||
"dragsort": "https://github.com/karsonzhang/dragsort.git",
|
"fastadmin-addtabs": "~1.0.0",
|
||||||
"jquery-addtabs": "https://github.com/karsonzhang/jquery-addtabs.git",
|
"fastadmin-selectpage": "~1.0.0"
|
||||||
"jquery-cxselect": "https://github.com/karsonzhang/cxSelect.git",
|
|
||||||
"selectpage": "https://github.com/karsonzhang/selectpage.git"
|
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"jspdf": "1.1.239 || 1.3.2"
|
"jspdf": "1.1.239 || 1.3.2"
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "karson",
|
"name": "Karson",
|
||||||
"email": "karsonzhang@163.com"
|
"email": "karsonzhang@163.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
"topthink/think-captcha": "^1.0",
|
"topthink/think-captcha": "^1.0",
|
||||||
"mtdowling/cron-expression": "^1.2",
|
"mtdowling/cron-expression": "^1.2",
|
||||||
"phpmailer/phpmailer": "^5.2",
|
"phpmailer/phpmailer": "^5.2",
|
||||||
"karsonzhang/fastadmin-addons": "dev-master",
|
"karsonzhang/fastadmin-addons": "~1.1.0",
|
||||||
"overtrue/pinyin": "~3.0",
|
"overtrue/pinyin": "~3.0",
|
||||||
"phpoffice/phpexcel": "^1.8"
|
"phpoffice/phpexcel": "^1.8"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,7 +9,7 @@
|
||||||
@import url("../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css");
|
@import url("../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css");
|
||||||
@import url("../libs/bootstrap-daterangepicker/daterangepicker.css");
|
@import url("../libs/bootstrap-daterangepicker/daterangepicker.css");
|
||||||
@import url("../libs/nice-validator/dist/jquery.validator.css");
|
@import url("../libs/nice-validator/dist/jquery.validator.css");
|
||||||
@import url("../libs/selectpage/selectpage.css");
|
@import url("../libs/fastadmin-selectpage/selectpage.css");
|
||||||
body {
|
body {
|
||||||
background: #f1f4f6;
|
background: #f1f4f6;
|
||||||
}
|
}
|
||||||
|
|
@ -44,9 +44,6 @@ body.is-dialog {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
.note-dialog .modal {
|
|
||||||
z-index: 1060;
|
|
||||||
}
|
|
||||||
.bootstrap-dialog .modal-dialog {
|
.bootstrap-dialog .modal-dialog {
|
||||||
/*width: 70%;*/
|
/*width: 70%;*/
|
||||||
max-width: 885px;
|
max-width: 885px;
|
||||||
|
|
@ -645,13 +642,16 @@ form.form-horizontal .control-label {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.layui-layer-fast .layui-layer-btn a {
|
.layui-layer-fast .layui-layer-btn a {
|
||||||
background-color: #95a5a6!important;
|
background-color: #95a5a6;
|
||||||
border-color: #95a5a6!important;
|
border-color: #95a5a6;
|
||||||
color: #fff!important;
|
color: #fff!important;
|
||||||
|
height: 31px;
|
||||||
|
margin-top: 0;
|
||||||
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
.layui-layer-fast .layui-layer-btn .layui-layer-btn0 {
|
.layui-layer-fast .layui-layer-btn .layui-layer-btn0 {
|
||||||
background-color: #18bc9c!important;
|
background-color: #18bc9c;
|
||||||
border-color: #18bc9c!important;
|
border-color: #18bc9c;
|
||||||
}
|
}
|
||||||
.layui-layer-fast .layui-layer-footer {
|
.layui-layer-fast .layui-layer-footer {
|
||||||
padding: 8px 20px;
|
padding: 8px 20px;
|
||||||
|
|
@ -731,6 +731,14 @@ form.form-horizontal .control-label {
|
||||||
.n-bootstrap .input-group > .n-right {
|
.n-bootstrap .input-group > .n-right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
@media (min-width: 564px) {
|
||||||
|
body.is-dialog .daterangepicker {
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
body.is-dialog .daterangepicker .ranges ul {
|
||||||
|
width: 130px;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*手机版样式*/
|
/*手机版样式*/
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.nav-addtabs {
|
.nav-addtabs {
|
||||||
|
|
@ -739,6 +747,10 @@ form.form-horizontal .control-label {
|
||||||
.fixed-table-toolbar .columns-right.btn-group {
|
.fixed-table-toolbar .columns-right.btn-group {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.fixed .content-wrapper,
|
||||||
|
.fixed .right-side {
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*平板样式*/
|
/*平板样式*/
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -41,14 +41,6 @@ body {
|
||||||
-moz-box-shadow: none;
|
-moz-box-shadow: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
.layui-layer-fast {
|
|
||||||
-webkit-animation-fill-mode: both;
|
|
||||||
animation-fill-mode: both;
|
|
||||||
-webkit-animation-duration: .3s;
|
|
||||||
animation-duration: .3s;
|
|
||||||
-webkit-animation-name: layer-bounceIn;
|
|
||||||
animation-name: layer-bounceIn;
|
|
||||||
}
|
|
||||||
/*修复nice-validator和summernote的编辑框冲突*/
|
/*修复nice-validator和summernote的编辑框冲突*/
|
||||||
.nice-validator .note-editor .note-editing-area .note-editable {
|
.nice-validator .note-editor .note-editing-area .note-editable {
|
||||||
display: inherit;
|
display: inherit;
|
||||||
|
|
@ -317,6 +309,8 @@ footer.footer {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
background: #555;
|
background: #555;
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
}
|
}
|
||||||
footer.footer ul {
|
footer.footer ul {
|
||||||
margin: 60px 0 30px 0;
|
margin: 60px 0 30px 0;
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,3 @@
|
||||||
|
define(['backend'], function (Backend) {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -99,6 +99,9 @@ define(['fast', 'moment'], function (Fast, Moment) {
|
||||||
url = url.replace(/\{ids\}/g, ids);
|
url = url.replace(/\{ids\}/g, ids);
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
|
},
|
||||||
|
refreshmenu: function () {
|
||||||
|
top.window.$(".sidebar-menu").trigger("refresh");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
init: function () {
|
init: function () {
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
commonSearch: false,
|
commonSearch: false,
|
||||||
searchFormVisible: false,
|
searchFormVisible: false,
|
||||||
pageSize: 12,
|
pageSize: 12,
|
||||||
|
pagination: false,
|
||||||
queryParams: function (params) {
|
queryParams: function (params) {
|
||||||
var filter = params.filter ? JSON.parse(params.filter) : {};
|
var filter = params.filter ? JSON.parse(params.filter) : {};
|
||||||
var op = params.op ? JSON.parse(params.op) : {};
|
var op = params.op ? JSON.parse(params.op) : {};
|
||||||
|
|
@ -111,11 +112,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
$(".btn-switch,.btn-userinfo").addClass("disabled");
|
$(".btn-switch,.btn-userinfo").addClass("disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 离线安装
|
||||||
require(['upload'], function (Upload) {
|
require(['upload'], function (Upload) {
|
||||||
Upload.api.plupload("#plupload-addon", function (data, ret) {
|
Upload.api.plupload("#plupload-addon", function (data, ret) {
|
||||||
Config['addons'][data.addon.name] = data.addon;
|
Config['addons'][data.addon.name] = data.addon;
|
||||||
$('.btn-refresh').trigger('click');
|
|
||||||
Toastr.success(ret.msg);
|
Toastr.success(ret.msg);
|
||||||
|
operate(data.addon.name, 'enable', false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -128,12 +130,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 切换URL
|
// 切换URL
|
||||||
$(document).on("click", ".btn-switch", function () {
|
$(document).on("click", ".btn-switch", function () {
|
||||||
$(".btn-switch").removeClass("active");
|
$(".btn-switch").removeClass("active");
|
||||||
$(this).addClass("active");
|
$(this).addClass("active");
|
||||||
table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1});
|
table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 会员信息
|
// 会员信息
|
||||||
$(document).on("click", ".btn-userinfo", function () {
|
$(document).on("click", ".btn-userinfo", function () {
|
||||||
var userinfo = Controller.api.userinfo.get();
|
var userinfo = Controller.api.userinfo.get();
|
||||||
|
|
@ -195,15 +199,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 点击安装
|
var install = function (name, version, force) {
|
||||||
$(document).on("click", ".btn-install", function () {
|
|
||||||
var that = this;
|
|
||||||
var name = $(this).closest(".operate").data("name");
|
|
||||||
var version = $(this).data("version");
|
|
||||||
var userinfo = Controller.api.userinfo.get();
|
var userinfo = Controller.api.userinfo.get();
|
||||||
var uid = userinfo ? userinfo.id : 0;
|
var uid = userinfo ? userinfo.id : 0;
|
||||||
var token = userinfo ? userinfo.token : '';
|
var token = userinfo ? userinfo.token : '';
|
||||||
var install = function (name, force) {
|
|
||||||
Fast.api.ajax({
|
Fast.api.ajax({
|
||||||
url: 'addon/install',
|
url: 'addon/install',
|
||||||
data: {name: name, force: force ? 1 : 0, uid: uid, token: token, version: version, faversion: Config.fastadmin.version}
|
data: {name: name, force: force ? 1 : 0, uid: uid, token: token, version: version, faversion: Config.fastadmin.version}
|
||||||
|
|
@ -229,6 +228,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('.btn-refresh').trigger('click');
|
$('.btn-refresh').trigger('click');
|
||||||
|
Fast.api.refreshmenu();
|
||||||
}, function (data, ret) {
|
}, function (data, ret) {
|
||||||
//如果是需要购买的插件则弹出二维码提示
|
//如果是需要购买的插件则弹出二维码提示
|
||||||
if (ret && ret.code === -1) {
|
if (ret && ret.code === -1) {
|
||||||
|
|
@ -280,26 +280,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if ($(that).data("type") !== 'free') {
|
|
||||||
if (parseInt(uid) === 0) {
|
|
||||||
return Layer.alert(__('Not login tips'), {
|
|
||||||
title: __('Warning'),
|
|
||||||
btn: [__('Login now'), __('Continue install')],
|
|
||||||
yes: function (index, layero) {
|
|
||||||
$(".btn-userinfo").trigger("click");
|
|
||||||
},
|
|
||||||
btn2: function () {
|
|
||||||
install(name, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
install(name, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
//点击卸载
|
|
||||||
$(document).on("click", ".btn-uninstall", function () {
|
|
||||||
var name = $(this).closest(".operate").data("name");
|
|
||||||
var uninstall = function (name, force) {
|
var uninstall = function (name, force) {
|
||||||
Fast.api.ajax({
|
Fast.api.ajax({
|
||||||
url: 'addon/uninstall',
|
url: 'addon/uninstall',
|
||||||
|
|
@ -308,6 +289,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
delete Config['addons'][name];
|
delete Config['addons'][name];
|
||||||
Layer.closeAll();
|
Layer.closeAll();
|
||||||
$('.btn-refresh').trigger('click');
|
$('.btn-refresh').trigger('click');
|
||||||
|
Fast.api.refreshmenu();
|
||||||
}, function (data, ret) {
|
}, function (data, ret) {
|
||||||
if (ret && ret.code === -3) {
|
if (ret && ret.code === -3) {
|
||||||
//插件目录发现影响全局的文件
|
//插件目录发现影响全局的文件
|
||||||
|
|
@ -331,21 +313,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Layer.confirm(__('Uninstall tips'), function () {
|
|
||||||
uninstall(name, false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//点击配置
|
|
||||||
$(document).on("click", ".btn-config", function () {
|
|
||||||
var name = $(this).closest(".operate").data("name");
|
|
||||||
Fast.api.open("addon/config?name=" + name, __('Setting'));
|
|
||||||
});
|
|
||||||
|
|
||||||
//点击启用/禁用
|
|
||||||
$(document).on("click", ".btn-enable,.btn-disable", function () {
|
|
||||||
var name = $(this).closest(".operate").data("name");
|
|
||||||
var action = $(this).data("action");
|
|
||||||
var operate = function (name, action, force) {
|
var operate = function (name, action, force) {
|
||||||
Fast.api.ajax({
|
Fast.api.ajax({
|
||||||
url: 'addon/state',
|
url: 'addon/state',
|
||||||
|
|
@ -355,6 +323,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
addon.state = action === 'enable' ? 1 : 0;
|
addon.state = action === 'enable' ? 1 : 0;
|
||||||
Layer.closeAll();
|
Layer.closeAll();
|
||||||
$('.btn-refresh').trigger('click');
|
$('.btn-refresh').trigger('click');
|
||||||
|
Fast.api.refreshmenu();
|
||||||
}, function (data, ret) {
|
}, function (data, ret) {
|
||||||
if (ret && ret.code === -3) {
|
if (ret && ret.code === -3) {
|
||||||
//插件目录发现影响全局的文件
|
//插件目录发现影响全局的文件
|
||||||
|
|
@ -378,6 +347,69 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var upgrade = function (name, version) {
|
||||||
|
var userinfo = Controller.api.userinfo.get();
|
||||||
|
var uid = userinfo ? userinfo.id : 0;
|
||||||
|
var token = userinfo ? userinfo.token : '';
|
||||||
|
Fast.api.ajax({
|
||||||
|
url: 'addon/upgrade',
|
||||||
|
data: {name: name, uid: uid, token: token, version: version, faversion: Config.fastadmin.version}
|
||||||
|
}, function (data, ret) {
|
||||||
|
Config['addons'][name].version = version;
|
||||||
|
Layer.closeAll();
|
||||||
|
$('.btn-refresh').trigger('click');
|
||||||
|
Fast.api.refreshmenu();
|
||||||
|
}, function (data, ret) {
|
||||||
|
Layer.alert(ret.msg);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击安装
|
||||||
|
$(document).on("click", ".btn-install", function () {
|
||||||
|
var that = this;
|
||||||
|
var name = $(this).closest(".operate").data("name");
|
||||||
|
var version = $(this).data("version");
|
||||||
|
|
||||||
|
var userinfo = Controller.api.userinfo.get();
|
||||||
|
var uid = userinfo ? userinfo.id : 0;
|
||||||
|
|
||||||
|
if ($(that).data("type") !== 'free') {
|
||||||
|
if (parseInt(uid) === 0) {
|
||||||
|
return Layer.alert(__('Not login tips'), {
|
||||||
|
title: __('Warning'),
|
||||||
|
btn: [__('Login now'), __('Continue install')],
|
||||||
|
yes: function (index, layero) {
|
||||||
|
$(".btn-userinfo").trigger("click");
|
||||||
|
},
|
||||||
|
btn2: function () {
|
||||||
|
install(name, version, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
install(name, version, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击卸载
|
||||||
|
$(document).on("click", ".btn-uninstall", function () {
|
||||||
|
var name = $(this).closest(".operate").data("name");
|
||||||
|
Layer.confirm(__('Uninstall tips'), function () {
|
||||||
|
uninstall(name, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击配置
|
||||||
|
$(document).on("click", ".btn-config", function () {
|
||||||
|
var name = $(this).closest(".operate").data("name");
|
||||||
|
Fast.api.open("addon/config?name=" + name, __('Setting'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击启用/禁用
|
||||||
|
$(document).on("click", ".btn-enable,.btn-disable", function () {
|
||||||
|
var name = $(this).closest(".operate").data("name");
|
||||||
|
var action = $(this).data("action");
|
||||||
operate(name, action, false);
|
operate(name, action, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -389,24 +421,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
}
|
}
|
||||||
var name = $(this).closest(".operate").data("name");
|
var name = $(this).closest(".operate").data("name");
|
||||||
var version = $(this).data("version");
|
var version = $(this).data("version");
|
||||||
var userinfo = Controller.api.userinfo.get();
|
|
||||||
var uid = userinfo ? userinfo.id : 0;
|
|
||||||
var token = userinfo ? userinfo.token : '';
|
|
||||||
var upgrade = function (name) {
|
|
||||||
Fast.api.ajax({
|
|
||||||
url: 'addon/upgrade',
|
|
||||||
data: {name: name, uid: uid, token: token, version: version, faversion: Config.fastadmin.version}
|
|
||||||
}, function (data, ret) {
|
|
||||||
Config['addons'][name].version = version;
|
|
||||||
Layer.closeAll();
|
|
||||||
$('.btn-refresh').trigger('click');
|
|
||||||
}, function (data, ret) {
|
|
||||||
Layer.alert(ret.msg);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Layer.confirm(__('Upgrade tips'), function () {
|
Layer.confirm(__('Upgrade tips'), function () {
|
||||||
upgrade(name);
|
upgrade(name, version);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
});
|
});
|
||||||
|
|
||||||
// 为表格绑定事件
|
// 为表格绑定事件
|
||||||
Table.api.bindevent(table);//当内容渲染完成后
|
Table.api.bindevent(table);
|
||||||
|
|
||||||
//默认隐藏所有子节点
|
//当内容渲染完成后
|
||||||
table.on('post-body.bs.table', function (e, settings, json, xhr) {
|
table.on('post-body.bs.table', function (e, settings, json, xhr) {
|
||||||
|
//默认隐藏所有子节点
|
||||||
//$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide();
|
//$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide();
|
||||||
$(".btn-node-sub.disabled").closest("tr").hide();
|
$(".btn-node-sub.disabled").closest("tr").hide();
|
||||||
|
|
||||||
|
|
@ -57,8 +58,15 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
$(this).data("shown", !status);
|
$(this).data("shown", !status);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
$(".btn-change[data-id],.btn-delone,.btn-dragsort").data("success", function (data, ret) {
|
||||||
|
Fast.api.refreshmenu();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
//批量删除后的回调
|
||||||
|
$(".toolbar > .btn-del,.toolbar .btn-more~ul>li>a").data("success", function (e) {
|
||||||
|
Fast.api.refreshmenu();
|
||||||
|
});
|
||||||
//展开隐藏一级
|
//展开隐藏一级
|
||||||
$(document.body).on("click", ".btn-toggle", function (e) {
|
$(document.body).on("click", ".btn-toggle", function (e) {
|
||||||
$("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();
|
$("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();
|
||||||
|
|
@ -88,21 +96,21 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
api: {
|
api: {
|
||||||
formatter: {
|
formatter: {
|
||||||
title: function (value, row, index) {
|
title: function (value, row, index) {
|
||||||
return !row.ismenu ? "<span class='text-muted'>" + value + "</span>" : value;
|
return !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||||
},
|
},
|
||||||
name: function (value, row, index) {
|
name: function (value, row, index) {
|
||||||
return !row.ismenu ? "<span class='text-muted'>" + value + "</span>" : value;
|
return !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||||
},
|
},
|
||||||
menu: function (value, row, index) {
|
menu: function (value, row, index) {
|
||||||
return "<a href='javascript:;' class='btn btn-" + (value ? "info" : "default") + " btn-xs btn-change' data-id='"
|
return "<a href='javascript:;' class='btn btn-" + (value ? "info" : "default") + " btn-xs btn-change' data-id='"
|
||||||
+ row.id + "' data-params='ismenu=" + (value ? 0 : 1) + "'>" + (value ? __('Yes') : __('No')) + "</a>";
|
+ row.id + "' data-params='ismenu=" + (value ? 0 : 1) + "'>" + (value ? __('Yes') : __('No')) + "</a>";
|
||||||
},
|
},
|
||||||
icon: function (value, row, index) {
|
icon: function (value, row, index) {
|
||||||
return '<i class="' + value + '"></i>';
|
return '<span class="' + (!row.ismenu || row.status == 'hidden' ? 'text-muted' : '') + '"><i class="' + value + '"></i></span>';
|
||||||
},
|
},
|
||||||
subnode: function (value, row, index) {
|
subnode: function (value, row, index) {
|
||||||
return '<a href="javascript:;" data-id="' + row['id'] + '" data-pid="' + row['pid'] + '" class="btn btn-xs '
|
return '<a href="javascript:;" data-id="' + row.id + '" data-pid="' + row.pid + '" class="btn btn-xs '
|
||||||
+ (row['haschild'] == 1 ? 'btn-success' : 'btn-default disabled') + ' btn-node-sub"><i class="fa fa-sitemap"></i></a>';
|
+ (row.haschild == 1 || row.ismenu == 1 ? 'btn-success' : 'btn-default disabled') + ' btn-node-sub"><i class="fa fa-sitemap"></i></a>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
bindevent: function () {
|
bindevent: function () {
|
||||||
|
|
@ -113,7 +121,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
||||||
$("input[name='row[ismenu]']:checked").trigger("click");
|
$("input[name='row[ismenu]']:checked").trigger("click");
|
||||||
|
|
||||||
var iconlist = [];
|
var iconlist = [];
|
||||||
Form.api.bindevent($("form[role=form]"));
|
Form.api.bindevent($("form[role=form]"), function (data) {
|
||||||
|
Fast.api.refreshmenu();
|
||||||
|
});
|
||||||
$(document).on('click', ".btn-search-icon", function () {
|
$(document).on('click', ".btn-search-icon", function () {
|
||||||
if (iconlist.length == 0) {
|
if (iconlist.length == 0) {
|
||||||
$.get(Config.site.cdnurl + "/assets/libs/font-awesome/less/variables.less", function (ret) {
|
$.get(Config.site.cdnurl + "/assets/libs/font-awesome/less/variables.less", function (ret) {
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,21 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//刷新菜单事件
|
||||||
|
$(document).on('refresh', '.sidebar-menu', function () {
|
||||||
|
Fast.api.ajax({
|
||||||
|
url: 'index/index',
|
||||||
|
data: {action: 'refreshmenu'}
|
||||||
|
}, function (data) {
|
||||||
|
$(".sidebar-menu li:not([data-rel='external'])").remove();
|
||||||
|
$(data.menulist).insertBefore($(".sidebar-menu li:first"));
|
||||||
|
$("#nav ul li[role='presentation'].active a").trigger('click');
|
||||||
|
return false;
|
||||||
|
}, function () {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//这一行需要放在点击左侧链接事件之前
|
//这一行需要放在点击左侧链接事件之前
|
||||||
var addtabs = Config.referer ? localStorage.getItem("addtabs") : null;
|
var addtabs = Config.referer ? localStorage.getItem("addtabs") : null;
|
||||||
|
|
||||||
|
|
@ -188,6 +203,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
||||||
} else {
|
} else {
|
||||||
$("ul.sidebar-menu li a[url!='javascript:;']:first").trigger("click");
|
$("ul.sidebar-menu li a[url!='javascript:;']:first").trigger("click");
|
||||||
}
|
}
|
||||||
|
|
||||||
//如果是刷新操作则直接返回刷新前的页面
|
//如果是刷新操作则直接返回刷新前的页面
|
||||||
if (Config.referer) {
|
if (Config.referer) {
|
||||||
if (Config.referer === $(addtabs).attr("url")) {
|
if (Config.referer === $(addtabs).attr("url")) {
|
||||||
|
|
@ -203,11 +219,6 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* List of all the available skins
|
|
||||||
*
|
|
||||||
* @type Array
|
|
||||||
*/
|
|
||||||
var my_skins = [
|
var my_skins = [
|
||||||
"skin-blue",
|
"skin-blue",
|
||||||
"skin-white",
|
"skin-white",
|
||||||
|
|
@ -224,19 +235,13 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
||||||
];
|
];
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggles layout classes
|
|
||||||
*
|
|
||||||
* @param String cls the layout class to toggle
|
|
||||||
* @returns void
|
|
||||||
*/
|
|
||||||
function change_layout(cls) {
|
function change_layout(cls) {
|
||||||
$("body").toggleClass(cls);
|
$("body").toggleClass(cls);
|
||||||
AdminLTE.layout.fixSidebar();
|
AdminLTE.layout.fixSidebar();
|
||||||
//Fix the problem with right sidebar and layout boxed
|
//Fix the problem with right sidebar and layout boxed
|
||||||
if (cls == "layout-boxed")
|
if (cls == "layout-boxed")
|
||||||
AdminLTE.controlSidebar._fix($(".control-sidebar-bg"));
|
AdminLTE.controlSidebar._fix($(".control-sidebar-bg"));
|
||||||
if ($('body').hasClass('fixed') && cls == 'fixed' && false) {
|
if ($('body').hasClass('fixed') && cls == 'fixed') {
|
||||||
AdminLTE.pushMenu.expandOnHover();
|
AdminLTE.pushMenu.expandOnHover();
|
||||||
AdminLTE.layout.activate();
|
AdminLTE.layout.activate();
|
||||||
}
|
}
|
||||||
|
|
@ -244,61 +249,18 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
||||||
AdminLTE.controlSidebar._fix($(".control-sidebar"));
|
AdminLTE.controlSidebar._fix($(".control-sidebar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces the old skin with the new skin
|
|
||||||
* @param String cls the new skin class
|
|
||||||
* @returns Boolean false to prevent link's default action
|
|
||||||
*/
|
|
||||||
function change_skin(cls) {
|
function change_skin(cls) {
|
||||||
if (!$("body").hasClass(cls)) {
|
if (!$("body").hasClass(cls)) {
|
||||||
$.each(my_skins, function (i) {
|
$("body").removeClass(my_skins.join(' ')).addClass(cls);
|
||||||
$("body").removeClass(my_skins[i]);
|
localStorage.setItem('skin', cls);
|
||||||
});
|
|
||||||
|
|
||||||
$("body").addClass(cls);
|
|
||||||
store('skin', cls);
|
|
||||||
var cssfile = Config.site.cdnurl + "/assets/css/skins/" + cls + ".css";
|
var cssfile = Config.site.cdnurl + "/assets/css/skins/" + cls + ".css";
|
||||||
$('head').append('<link rel="stylesheet" href="' + cssfile + '" type="text/css" />');
|
$('head').append('<link rel="stylesheet" href="' + cssfile + '" type="text/css" />');
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a new settings in the browser
|
|
||||||
*
|
|
||||||
* @param String name Name of the setting
|
|
||||||
* @param String val Value of the setting
|
|
||||||
* @returns void
|
|
||||||
*/
|
|
||||||
function store(name, val) {
|
|
||||||
if (typeof (Storage) !== "undefined") {
|
|
||||||
localStorage.setItem(name, val);
|
|
||||||
} else {
|
|
||||||
window.alert('Please use a modern browser to properly view this template!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a prestored setting
|
|
||||||
*
|
|
||||||
* @param String name Name of of the setting
|
|
||||||
* @returns String The value of the setting | null
|
|
||||||
*/
|
|
||||||
function get(name) {
|
|
||||||
if (typeof (Storage) !== "undefined") {
|
|
||||||
return localStorage.getItem(name);
|
|
||||||
} else {
|
|
||||||
window.alert('Please use a modern browser to properly view this template!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve default settings and apply them to the template
|
|
||||||
*
|
|
||||||
* @returns void
|
|
||||||
*/
|
|
||||||
function setup() {
|
function setup() {
|
||||||
var tmp = get('skin');
|
var tmp = localStorage.getItem('skin');
|
||||||
if (tmp && $.inArray(tmp, my_skins))
|
if (tmp && $.inArray(tmp, my_skins))
|
||||||
change_skin(tmp);
|
change_skin(tmp);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
||||||
{field: 'id', title: __('Id')},
|
{field: 'id', title: __('Id')},
|
||||||
{field: 'pid', title: __('Pid'), visible: false},
|
{field: 'pid', title: __('Pid'), visible: false},
|
||||||
{field: 'title', title: __('Title'), align: 'left'},
|
{field: 'title', title: __('Title'), align: 'left'},
|
||||||
{field: 'name', title: __('Name')},
|
{field: 'name', title: __('Name'), align: 'left'},
|
||||||
{field: 'remark', title: __('Remark')},
|
{field: 'remark', title: __('Remark')},
|
||||||
{field: 'ismenu', title: __('Ismenu'), formatter: Controller.api.formatter.toggle},
|
{field: 'ismenu', title: __('Ismenu'), formatter: Controller.api.formatter.toggle},
|
||||||
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime, visible: false},
|
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime, visible: false},
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@
|
||||||
|
|
||||||
var createFormCommon = function (pColumns, that) {
|
var createFormCommon = function (pColumns, that) {
|
||||||
var htmlForm = [];
|
var htmlForm = [];
|
||||||
var opList = ['=', '>', '>=', '<', '<=', '!=', 'LIKE', 'LIKE %...%', 'NOT LIKE', 'IN', 'NOT IN', 'IN(...)', 'NOT IN(...)', 'BETWEEN', 'NOT BETWEEN', 'RANGE', 'NOT RANGE', 'IS NULL', 'IS NOT NULL'];
|
var opList = ['=', '>', '>=', '<', '<=', '!=', 'FIND_IN_SET', 'LIKE', 'LIKE %...%', 'NOT LIKE', 'IN', 'NOT IN', 'IN(...)', 'NOT IN(...)', 'BETWEEN', 'NOT BETWEEN', 'RANGE', 'NOT RANGE', 'IS NULL', 'IS NOT NULL'];
|
||||||
htmlForm.push(sprintf('<form class="form-horizontal form-commonsearch" action="%s" >', that.options.actionForm));
|
htmlForm.push(sprintf('<form class="form-horizontal form-commonsearch" action="%s" >', that.options.actionForm));
|
||||||
htmlForm.push('<fieldset>');
|
htmlForm.push('<fieldset>');
|
||||||
if (that.options.titleForm.length > 0)
|
if (that.options.titleForm.length > 0)
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
if (!that.options.templateView) {
|
if (!that.options.templateView) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
that.options.cardView = true;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,8 +164,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine
|
||||||
options.area = [top.$(".tab-pane.active").width() + "px", top.$(".tab-pane.active").height() + "px"];
|
options.area = [top.$(".tab-pane.active").width() + "px", top.$(".tab-pane.active").height() + "px"];
|
||||||
options.offset = [top.$(".tab-pane.active").scrollTop() + "px", "0px"];
|
options.offset = [top.$(".tab-pane.active").scrollTop() + "px", "0px"];
|
||||||
}
|
}
|
||||||
Layer.open(options);
|
return Layer.open(options);
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
//关闭窗口并回传数据
|
//关闭窗口并回传数据
|
||||||
close: function (data) {
|
close: function (data) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
define(['frontend'], function (Frontend) {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -7,7 +7,7 @@ require.config({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
//在打包压缩时将会把include中的模块合并到主文件中
|
//在打包压缩时将会把include中的模块合并到主文件中
|
||||||
include: ['css', 'layer', 'toastr', 'fast', 'backend', 'table', 'form', 'dragsort', 'drag', 'drop', 'addtabs', 'selectpage'],
|
include: ['css', 'layer', 'toastr', 'fast', 'backend', 'backend-init', 'table', 'form', 'dragsort', 'drag', 'drop', 'addtabs', 'selectpage'],
|
||||||
paths: {
|
paths: {
|
||||||
'lang': "empty:",
|
'lang': "empty:",
|
||||||
'form': 'require-form',
|
'form': 'require-form',
|
||||||
|
|
@ -34,22 +34,20 @@ require.config({
|
||||||
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
|
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
|
||||||
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
|
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
|
||||||
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
|
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
|
||||||
'dragsort': '../libs/dragsort/jquery.dragsort',
|
'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort',
|
||||||
'qrcode': '../libs/jquery-qrcode/jquery.qrcode.min',
|
|
||||||
'sortable': '../libs/Sortable/Sortable.min',
|
'sortable': '../libs/Sortable/Sortable.min',
|
||||||
'addtabs': '../libs/jquery-addtabs/jquery.addtabs',
|
'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs',
|
||||||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||||
'summernote': '../libs/summernote/dist/lang/summernote-zh-CN.min',
|
|
||||||
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
||||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||||
'plupload': '../libs/plupload/js/plupload.min',
|
'plupload': '../libs/plupload/js/plupload.min',
|
||||||
'toastr': '../libs/toastr/toastr',
|
'toastr': '../libs/toastr/toastr',
|
||||||
'jstree': '../libs/jstree/dist/jstree.min',
|
'jstree': '../libs/jstree/dist/jstree.min',
|
||||||
'layer': '../libs/layer/src/layer',
|
'layer': '../libs/layer/dist/layer',
|
||||||
'cookie': '../libs/jquery.cookie/jquery.cookie',
|
'cookie': '../libs/jquery.cookie/jquery.cookie',
|
||||||
'cxselect': '../libs/jquery-cxselect/js/jquery.cxselect',
|
'cxselect': '../libs/fastadmin-cxselect/js/jquery.cxselect',
|
||||||
'template': '../libs/art-template/dist/template-native',
|
'template': '../libs/art-template/dist/template-native',
|
||||||
'selectpage': '../libs/selectpage/selectpage',
|
'selectpage': '../libs/fastadmin-selectpage/selectpage',
|
||||||
'citypicker': '../libs/city-picker/dist/js/city-picker.min',
|
'citypicker': '../libs/city-picker/dist/js/city-picker.min',
|
||||||
'citypicker-data': '../libs/city-picker/dist/js/city-picker.data',
|
'citypicker-data': '../libs/city-picker/dist/js/city-picker.data',
|
||||||
},
|
},
|
||||||
|
|
@ -106,7 +104,6 @@ require.config({
|
||||||
],
|
],
|
||||||
'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ],
|
'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ],
|
||||||
'bootstrap-select-lang': ['bootstrap-select'],
|
'bootstrap-select-lang': ['bootstrap-select'],
|
||||||
'summernote': ['../libs/summernote/dist/summernote.min', 'css!../libs/summernote/dist/summernote.css'],
|
|
||||||
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
||||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ],
|
'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ],
|
||||||
'plupload': {
|
'plupload': {
|
||||||
|
|
@ -116,7 +113,7 @@ require.config({
|
||||||
// 'layer': ['css!../libs/layer/dist/theme/default/layer.css'],
|
// 'layer': ['css!../libs/layer/dist/theme/default/layer.css'],
|
||||||
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
||||||
'validator-lang': ['validator-core'],
|
'validator-lang': ['validator-core'],
|
||||||
// 'selectpage': ['css!../libs/selectpage/selectpage.css'],
|
// 'selectpage': ['css!../libs/fastadmin-selectpage/selectpage.css'],
|
||||||
'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css']
|
'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css']
|
||||||
},
|
},
|
||||||
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
|
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
|
||||||
|
|
@ -144,7 +141,7 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
|
||||||
// 初始化
|
// 初始化
|
||||||
$(function () {
|
$(function () {
|
||||||
require(['fast'], function (Fast) {
|
require(['fast'], function (Fast) {
|
||||||
require(['backend', 'addons'], function (Backend, Addons) {
|
require(['backend', 'backend-init', 'addons'], function (Backend, undefined, Addons) {
|
||||||
//加载相应模块
|
//加载相应模块
|
||||||
if (Config.jsname) {
|
if (Config.jsname) {
|
||||||
require([Config.jsname], function (Controller) {
|
require([Config.jsname], function (Controller) {
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -40,6 +40,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
||||||
Form.api.submit($(ret), function (data, ret) {
|
Form.api.submit($(ret), function (data, ret) {
|
||||||
that.holdSubmit(false);
|
that.holdSubmit(false);
|
||||||
submitBtn.removeClass("disabled");
|
submitBtn.removeClass("disabled");
|
||||||
|
if (false === $(this).triggerHandler("success.form", [data, ret])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (typeof success === 'function') {
|
if (typeof success === 'function') {
|
||||||
if (false === success.call($(this), data, ret)) {
|
if (false === success.call($(this), data, ret)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -54,6 +57,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
||||||
return false;
|
return false;
|
||||||
}, function (data, ret) {
|
}, function (data, ret) {
|
||||||
that.holdSubmit(false);
|
that.holdSubmit(false);
|
||||||
|
if (false === $(this).triggerHandler("error.form", [data, ret])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
submitBtn.removeClass("disabled");
|
submitBtn.removeClass("disabled");
|
||||||
if (typeof error === 'function') {
|
if (typeof error === 'function') {
|
||||||
if (false === error.call($(this), data, ret)) {
|
if (false === error.call($(this), data, ret)) {
|
||||||
|
|
@ -81,13 +87,25 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
||||||
if ($(".selectpage", form).size() > 0) {
|
if ($(".selectpage", form).size() > 0) {
|
||||||
require(['selectpage'], function () {
|
require(['selectpage'], function () {
|
||||||
$('.selectpage', form).selectPage({
|
$('.selectpage', form).selectPage({
|
||||||
source: 'ajax/selectpage',
|
eAjaxSuccess: function (data) {
|
||||||
|
data.list = typeof data.rows !== 'undefined' ? data.rows : (typeof data.list !== 'undefined' ? data.list : []);
|
||||||
|
data.totalRow = typeof data.total !== 'undefined' ? data.total : (typeof data.totalRow !== 'undefined' ? data.totalRow : data.list.length);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
//给隐藏的元素添加上validate验证触发事件
|
//给隐藏的元素添加上validate验证触发事件
|
||||||
$(form).on("change", ".selectpage-input-hidden", function () {
|
$(document).on("change", ".sp_hidden", function () {
|
||||||
$(this).trigger("validate");
|
$(this).trigger("validate");
|
||||||
});
|
});
|
||||||
|
$(document).on("change", ".sp_input", function () {
|
||||||
|
$(this).closest(".sp_container").find(".sp_hidden").trigger("change");
|
||||||
|
});
|
||||||
|
$(form).on("reset", function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
$('.selectpage', form).selectPageClear();
|
||||||
|
}, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cxselect: function (form) {
|
cxselect: function (form) {
|
||||||
|
|
@ -132,6 +150,48 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
daterangepicker: function (form) {
|
||||||
|
//绑定日期时间元素事件
|
||||||
|
if ($(".datetimerange", form).size() > 0) {
|
||||||
|
require(['bootstrap-daterangepicker'], function () {
|
||||||
|
var ranges = {};
|
||||||
|
ranges[__('Today')] = [Moment().startOf('day'), Moment().endOf('day')];
|
||||||
|
ranges[__('Yesterday')] = [Moment().subtract(1, 'days').startOf('day'), Moment().subtract(1, 'days').endOf('day')];
|
||||||
|
ranges[__('Last 7 Days')] = [Moment().subtract(6, 'days').startOf('day'), Moment().endOf('day')];
|
||||||
|
ranges[__('Last 30 Days')] = [Moment().subtract(29, 'days').startOf('day'), Moment().endOf('day')];
|
||||||
|
ranges[__('This Month')] = [Moment().startOf('month'), Moment().endOf('month')];
|
||||||
|
ranges[__('Last Month')] = [Moment().subtract(1, 'month').startOf('month'), Moment().subtract(1, 'month').endOf('month')];
|
||||||
|
var options = {
|
||||||
|
timePicker: false,
|
||||||
|
autoUpdateInput: false,
|
||||||
|
timePickerSeconds: true,
|
||||||
|
timePicker24Hour: true,
|
||||||
|
autoApply: true,
|
||||||
|
locale: {
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
customRangeLabel: __("Custom Range"),
|
||||||
|
applyLabel: __("Apply"),
|
||||||
|
cancelLabel: __("Clear"),
|
||||||
|
},
|
||||||
|
ranges: ranges,
|
||||||
|
};
|
||||||
|
var origincallback = function (start, end) {
|
||||||
|
$(this.element).val(start.format(options.locale.format) + " - " + end.format(options.locale.format));
|
||||||
|
$(this.element).trigger('blur');
|
||||||
|
};
|
||||||
|
$(".datetimerange", form).each(function () {
|
||||||
|
var callback = typeof $(this).data('callback') == 'function' ? $(this).data('callback') : origincallback;
|
||||||
|
$(this).on('apply.daterangepicker', function (ev, picker) {
|
||||||
|
callback.call(picker, picker.startDate, picker.endDate);
|
||||||
|
});
|
||||||
|
$(this).on('cancel.daterangepicker', function (ev, picker) {
|
||||||
|
$(this).val('').trigger('blur');
|
||||||
|
});
|
||||||
|
$(this).daterangepicker($.extend({}, options, $(this).data()), callback);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
plupload: function (form) {
|
plupload: function (form) {
|
||||||
//绑定plupload上传元素事件
|
//绑定plupload上传元素事件
|
||||||
if ($(".plupload", form).size() > 0) {
|
if ($(".plupload", form).size() > 0) {
|
||||||
|
|
@ -287,6 +347,8 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
||||||
|
|
||||||
events.selectpicker(form);
|
events.selectpicker(form);
|
||||||
|
|
||||||
|
events.daterangepicker(form);
|
||||||
|
|
||||||
events.selectpage(form);
|
events.selectpage(form);
|
||||||
|
|
||||||
events.cxselect(form);
|
events.cxselect(form);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ require.config({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
//在打包压缩时将会把include中的模块合并到主文件中
|
//在打包压缩时将会把include中的模块合并到主文件中
|
||||||
include: ['css', 'layer', 'toastr', 'fast', 'frontend'],
|
include: ['css', 'layer', 'toastr', 'fast', 'frontend', 'frontend-init'],
|
||||||
paths: {
|
paths: {
|
||||||
'lang': "empty:",
|
'lang': "empty:",
|
||||||
'form': 'require-form',
|
'form': 'require-form',
|
||||||
|
|
@ -34,22 +34,20 @@ require.config({
|
||||||
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
|
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
|
||||||
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
|
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
|
||||||
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
|
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
|
||||||
'dragsort': '../libs/dragsort/jquery.dragsort',
|
'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort',
|
||||||
'qrcode': '../libs/jquery-qrcode/jquery.qrcode.min',
|
|
||||||
'sortable': '../libs/Sortable/Sortable.min',
|
'sortable': '../libs/Sortable/Sortable.min',
|
||||||
'addtabs': '../libs/jquery-addtabs/jquery.addtabs',
|
'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs',
|
||||||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||||
'summernote': '../libs/summernote/dist/lang/summernote-zh-CN.min',
|
|
||||||
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
||||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||||
'plupload': '../libs/plupload/js/plupload.min',
|
'plupload': '../libs/plupload/js/plupload.min',
|
||||||
'toastr': '../libs/toastr/toastr',
|
'toastr': '../libs/toastr/toastr',
|
||||||
'jstree': '../libs/jstree/dist/jstree.min',
|
'jstree': '../libs/jstree/dist/jstree.min',
|
||||||
'layer': '../libs/layer/src/layer',
|
'layer': '../libs/layer/dist/layer',
|
||||||
'cookie': '../libs/jquery.cookie/jquery.cookie',
|
'cookie': '../libs/jquery.cookie/jquery.cookie',
|
||||||
'cxselect': '../libs/jquery-cxselect/js/jquery.cxselect',
|
'cxselect': '../libs/fastadmin-cxselect/js/jquery.cxselect',
|
||||||
'template': '../libs/art-template/dist/template-native',
|
'template': '../libs/art-template/dist/template-native',
|
||||||
'selectpage': '../libs/selectpage/selectpage',
|
'selectpage': '../libs/fastadmin-selectpage/selectpage',
|
||||||
'citypicker': '../libs/city-picker/dist/js/city-picker.min',
|
'citypicker': '../libs/city-picker/dist/js/city-picker.min',
|
||||||
'citypicker-data': '../libs/city-picker/dist/js/city-picker.data',
|
'citypicker-data': '../libs/city-picker/dist/js/city-picker.data',
|
||||||
},
|
},
|
||||||
|
|
@ -106,7 +104,6 @@ require.config({
|
||||||
],
|
],
|
||||||
'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ],
|
'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ],
|
||||||
'bootstrap-select-lang': ['bootstrap-select'],
|
'bootstrap-select-lang': ['bootstrap-select'],
|
||||||
'summernote': ['../libs/summernote/dist/summernote.min', 'css!../libs/summernote/dist/summernote.css'],
|
|
||||||
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
||||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ],
|
'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ],
|
||||||
'plupload': {
|
'plupload': {
|
||||||
|
|
@ -116,7 +113,7 @@ require.config({
|
||||||
// 'layer': ['css!../libs/layer/dist/theme/default/layer.css'],
|
// 'layer': ['css!../libs/layer/dist/theme/default/layer.css'],
|
||||||
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
||||||
'validator-lang': ['validator-core'],
|
'validator-lang': ['validator-core'],
|
||||||
// 'selectpage': ['css!../libs/selectpage/selectpage.css'],
|
// 'selectpage': ['css!../libs/fastadmin-selectpage/selectpage.css'],
|
||||||
'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css']
|
'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css']
|
||||||
},
|
},
|
||||||
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
|
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,4 +1,4 @@
|
||||||
define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table', 'bootstrap-table-lang', 'bootstrap-table-mobile', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template'], function ($, undefined, Moment) {
|
define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table', 'bootstrap-table-lang', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template'], function ($, undefined, Moment) {
|
||||||
var Table = {
|
var Table = {
|
||||||
list: {},
|
list: {},
|
||||||
// Bootstrap-table 基础配置
|
// Bootstrap-table 基础配置
|
||||||
|
|
@ -32,7 +32,6 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
paginationPreText: __("Previous"),
|
paginationPreText: __("Previous"),
|
||||||
paginationNextText: __("Next"),
|
paginationNextText: __("Next"),
|
||||||
paginationLastText: __("Last"),
|
paginationLastText: __("Last"),
|
||||||
mobileResponsive: true, //是否自适应移动端
|
|
||||||
cardView: false, //卡片视图
|
cardView: false, //卡片视图
|
||||||
checkOnInit: true, //是否在初始化时判断
|
checkOnInit: true, //是否在初始化时判断
|
||||||
escape: true, //是否对内容进行转义
|
escape: true, //是否对内容进行转义
|
||||||
|
|
@ -152,7 +151,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 处理选中筛选框后按钮的状态统一变更
|
// 处理选中筛选框后按钮的状态统一变更
|
||||||
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table fa.event.check', function () {
|
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function () {
|
||||||
var ids = Table.api.selectedids(table);
|
var ids = Table.api.selectedids(table);
|
||||||
$(Table.config.disabledbtn, toolbar).toggleClass('disabled', !ids.length);
|
$(Table.config.disabledbtn, toolbar).toggleClass('disabled', !ids.length);
|
||||||
});
|
});
|
||||||
|
|
@ -176,7 +175,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
Fast.api.ajax({
|
Fast.api.ajax({
|
||||||
url: options.extend.import_url,
|
url: options.extend.import_url,
|
||||||
data: {file: data.url},
|
data: {file: data.url},
|
||||||
}, function () {
|
}, function (data, ret) {
|
||||||
table.bootstrapTable('refresh');
|
table.bootstrapTable('refresh');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -217,7 +216,8 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
$("tbody", table).dragsort({
|
$("tbody", table).dragsort({
|
||||||
itemSelector: 'tr:visible',
|
itemSelector: 'tr:visible',
|
||||||
dragSelector: "a.btn-dragsort",
|
dragSelector: "a.btn-dragsort",
|
||||||
dragEnd: function () {
|
dragEnd: function (a, b) {
|
||||||
|
var element = $("a.btn-dragsort", this);
|
||||||
var data = table.bootstrapTable('getData');
|
var data = table.bootstrapTable('getData');
|
||||||
var current = data[parseInt($(this).data("index"))];
|
var current = data[parseInt($(this).data("index"))];
|
||||||
var options = table.bootstrapTable('getOptions');
|
var options = table.bootstrapTable('getOptions');
|
||||||
|
|
@ -238,7 +238,21 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
table: options.extend.table
|
table: options.extend.table
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Fast.api.ajax(params, function (data) {
|
Fast.api.ajax(params, function (data, ret) {
|
||||||
|
var success = $(element).data("success") || $.noop;
|
||||||
|
if (typeof success === 'function') {
|
||||||
|
if (false === success.call(element, data, ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.bootstrapTable('refresh');
|
||||||
|
}, function () {
|
||||||
|
var error = $(element).data("error") || $.noop;
|
||||||
|
if (typeof error === 'function') {
|
||||||
|
if (false === error.call(element, data, ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
table.bootstrapTable('refresh');
|
table.bootstrapTable('refresh');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -246,7 +260,9 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
$(table).on("click", "input[data-id][name='checkbox']", function (e) {
|
$(table).on("click", "input[data-id][name='checkbox']", function (e) {
|
||||||
table.trigger('fa.event.check');
|
var ids = $(this).data("id");
|
||||||
|
var row = Table.api.getrowbyid(ids);
|
||||||
|
table.trigger('check.bs.table', [row, this]);
|
||||||
});
|
});
|
||||||
$(table).on("click", "[data-id].btn-change", function (e) {
|
$(table).on("click", "[data-id].btn-change", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -255,14 +271,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
$(table).on("click", "[data-id].btn-edit", function (e) {
|
$(table).on("click", "[data-id].btn-edit", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var ids = $(this).data("id");
|
var ids = $(this).data("id");
|
||||||
var row = {};
|
var row = Table.api.getrowbyid(ids);
|
||||||
var options = table.bootstrapTable("getOptions");
|
|
||||||
$.each(table.bootstrapTable('getData'), function (i, j) {
|
|
||||||
if (j[options.pk] == ids) {
|
|
||||||
row = j;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
row.ids = ids;
|
row.ids = ids;
|
||||||
var url = Table.api.replaceurl(options.extend.edit_url, row, table);
|
var url = Table.api.replaceurl(options.extend.edit_url, row, table);
|
||||||
Fast.api.open(url, __('Edit'), $(this).data() || {});
|
Fast.api.open(url, __('Edit'), $(this).data() || {});
|
||||||
|
|
@ -293,8 +302,21 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
url = this.replaceurl(url, {ids: ids}, table);
|
url = this.replaceurl(url, {ids: ids}, table);
|
||||||
var params = typeof data.params !== "undefined" ? (typeof data.params == 'object' ? $.param(data.params) : data.params) : '';
|
var params = typeof data.params !== "undefined" ? (typeof data.params == 'object' ? $.param(data.params) : data.params) : '';
|
||||||
var options = {url: url, data: {action: action, ids: ids, params: params}};
|
var options = {url: url, data: {action: action, ids: ids, params: params}};
|
||||||
Fast.api.ajax(options, function (data) {
|
Fast.api.ajax(options, function (data, ret) {
|
||||||
|
var success = $(element).data("success") || $.noop;
|
||||||
|
if (typeof success === 'function') {
|
||||||
|
if (false === success.call(element, data, ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
table.bootstrapTable('refresh');
|
table.bootstrapTable('refresh');
|
||||||
|
}, function (data, ret) {
|
||||||
|
var error = $(element).data("error") || $.noop;
|
||||||
|
if (typeof error === 'function') {
|
||||||
|
if (false === error.call(element, data, ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 单元格元素事件
|
// 单元格元素事件
|
||||||
|
|
@ -521,6 +543,22 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
||||||
index = parseInt(index);
|
index = parseInt(index);
|
||||||
var data = table.bootstrapTable('getData');
|
var data = table.bootstrapTable('getData');
|
||||||
return typeof data[index] !== 'undefined' ? data[index] : null;
|
return typeof data[index] !== 'undefined' ? data[index] : null;
|
||||||
|
},
|
||||||
|
// 根据行索引获取行数据
|
||||||
|
getrowbyindex: function (table, index) {
|
||||||
|
return Table.api.getrowdata(table, index);
|
||||||
|
},
|
||||||
|
// 根据主键ID获取行数据
|
||||||
|
getrowbyid: function (table, id) {
|
||||||
|
var row = {};
|
||||||
|
var options = table.bootstrapTable("getOptions");
|
||||||
|
$.each(table.bootstrapTable('getData'), function (i, j) {
|
||||||
|
if (j[options.pk] == id) {
|
||||||
|
row = j;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return row;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -15,7 +15,7 @@
|
||||||
@import url("../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css");
|
@import url("../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css");
|
||||||
@import url("../libs/bootstrap-daterangepicker/daterangepicker.css");
|
@import url("../libs/bootstrap-daterangepicker/daterangepicker.css");
|
||||||
@import url("../libs/nice-validator/dist/jquery.validator.css");
|
@import url("../libs/nice-validator/dist/jquery.validator.css");
|
||||||
@import url("../libs/selectpage/selectpage.css");
|
@import url("../libs/fastadmin-selectpage/selectpage.css");
|
||||||
|
|
||||||
@main-bg: #f1f4f6;
|
@main-bg: #f1f4f6;
|
||||||
@panel-intro-bg: darken(@main-bg,3%);
|
@panel-intro-bg: darken(@main-bg,3%);
|
||||||
|
|
@ -54,7 +54,6 @@ body.is-dialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.note-dialog .modal {z-index:1060;}
|
|
||||||
|
|
||||||
.bootstrap-dialog .modal-dialog {
|
.bootstrap-dialog .modal-dialog {
|
||||||
/*width: 70%;*/
|
/*width: 70%;*/
|
||||||
|
|
@ -668,13 +667,16 @@ form.form-horizontal .control-label {
|
||||||
background: #ecf0f1;
|
background: #ecf0f1;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
a {
|
a {
|
||||||
background-color: #95a5a6!important;
|
background-color: #95a5a6;
|
||||||
border-color: #95a5a6!important;
|
border-color: #95a5a6;
|
||||||
color:#fff!important;
|
color:#fff!important;
|
||||||
|
height:31px;
|
||||||
|
margin-top:0;
|
||||||
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
.layui-layer-btn0{
|
.layui-layer-btn0{
|
||||||
background-color: #18bc9c!important;
|
background-color: #18bc9c;
|
||||||
border-color: #18bc9c!important;
|
border-color: #18bc9c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.layui-layer-footer {
|
.layui-layer-footer {
|
||||||
|
|
@ -763,6 +765,14 @@ form.form-horizontal .control-label {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@media (min-width: 564px){
|
||||||
|
body.is-dialog .daterangepicker {
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
body.is-dialog .daterangepicker .ranges ul {
|
||||||
|
width: 130px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*手机版样式*/
|
/*手机版样式*/
|
||||||
@media (max-width: @screen-phone) {
|
@media (max-width: @screen-phone) {
|
||||||
|
|
@ -774,6 +784,9 @@ form.form-horizontal .control-label {
|
||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.fixed .content-wrapper, .fixed .right-side {
|
||||||
|
padding-top: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*平板样式*/
|
/*平板样式*/
|
||||||
@media (max-width: @screen-tablet) {
|
@media (max-width: @screen-tablet) {
|
||||||
|
|
|
||||||
|
|
@ -61,15 +61,6 @@ body {
|
||||||
.box-shadow(none);
|
.box-shadow(none);
|
||||||
}
|
}
|
||||||
|
|
||||||
.layui-layer-fast {
|
|
||||||
-webkit-animation-fill-mode: both;
|
|
||||||
animation-fill-mode: both;
|
|
||||||
-webkit-animation-duration: .3s;
|
|
||||||
animation-duration: .3s;
|
|
||||||
-webkit-animation-name: layer-bounceIn;
|
|
||||||
animation-name: layer-bounceIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*修复nice-validator和summernote的编辑框冲突*/
|
/*修复nice-validator和summernote的编辑框冲突*/
|
||||||
.nice-validator .note-editor .note-editing-area .note-editable{
|
.nice-validator .note-editor .note-editing-area .note-editable{
|
||||||
display:inherit;
|
display:inherit;
|
||||||
|
|
@ -329,7 +320,7 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
footer.footer{width:100%;color: #aaa;background: #555;margin-top:25px;}
|
footer.footer{width:100%;color: #aaa;background: #555;margin-top:25px;position: fixed;bottom: 0;}
|
||||||
footer.footer ul{margin:60px 0 30px 0;padding:0;}
|
footer.footer ul{margin:60px 0 30px 0;padding:0;}
|
||||||
footer.footer ul li.f-tit{margin-bottom:10px;font-size: 14px;color: #fff;}
|
footer.footer ul li.f-tit{margin-bottom:10px;font-size: 14px;color: #fff;}
|
||||||
footer.footer ul li{line-height: 26px;white-space: nowrap;list-style: none;margin:0;padding:0;}
|
footer.footer ul li{line-height: 26px;white-space: nowrap;list-style: none;margin:0;padding:0;}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue