新增插件分类、免费插件搜索
新增全局的Template 新增自定义通用搜索表单内容 新增通用搜索按钮显示配置 新增单独清除模板、插件缓存 新增后台登录失败重试配置 优化通用搜索,搜索元素支持自动绑定元素事件 优化本地插件显示 优化前台首页和API文档字体显示 修复元素验证指定data-target不生效的BUG 修复插件命令行添加--force不生效的BUG 修复noNeedLogin和noNeedRight大小写的BUG 修复fieldlist无法挺拽的BUG 修复一键CRUD后指定字段显示后无法显示关联数据的BUG
正在显示
29 个修改的文件
包含
500 行增加
和
508 行删除
@@ -19,14 +19,14 @@ class Addon extends Command | @@ -19,14 +19,14 @@ class Addon extends Command | ||
19 | protected function configure() | 19 | protected function configure() |
20 | { | 20 | { |
21 | $this | 21 | $this |
22 | - ->setName('addon') | ||
23 | - ->addOption('name', 'a', Option::VALUE_REQUIRED, 'addon name', null) | ||
24 | - ->addOption('action', 'c', Option::VALUE_REQUIRED, 'action(create/enable/disable/install/uninstall/refresh/upgrade/package)', 'create') | ||
25 | - ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', null) | ||
26 | - ->addOption('release', 'r', Option::VALUE_OPTIONAL, 'addon release version', null) | ||
27 | - ->addOption('uid', 'u', Option::VALUE_OPTIONAL, 'fastadmin uid', null) | ||
28 | - ->addOption('token', 't', Option::VALUE_OPTIONAL, 'fastadmin token', null) | ||
29 | - ->setDescription('Addon manager'); | 22 | + ->setName('addon') |
23 | + ->addOption('name', 'a', Option::VALUE_REQUIRED, 'addon name', null) | ||
24 | + ->addOption('action', 'c', Option::VALUE_REQUIRED, 'action(create/enable/disable/install/uninstall/refresh/upgrade/package)', 'create') | ||
25 | + ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', null) | ||
26 | + ->addOption('release', 'r', Option::VALUE_OPTIONAL, 'addon release version', null) | ||
27 | + ->addOption('uid', 'u', Option::VALUE_OPTIONAL, 'fastadmin uid', null) | ||
28 | + ->addOption('token', 't', Option::VALUE_OPTIONAL, 'fastadmin token', null) | ||
29 | + ->setDescription('Addon manager'); | ||
30 | } | 30 | } |
31 | 31 | ||
32 | protected function execute(Input $input, Output $output) | 32 | protected function execute(Input $input, Output $output) |
@@ -44,12 +44,10 @@ class Addon extends Command | @@ -44,12 +44,10 @@ class Addon extends Command | ||
44 | 44 | ||
45 | include dirname(__DIR__) . DS . 'common.php'; | 45 | include dirname(__DIR__) . DS . 'common.php'; |
46 | 46 | ||
47 | - if (!$name) | ||
48 | - { | 47 | + if (!$name) { |
49 | throw new Exception('Addon name could not be empty'); | 48 | throw new Exception('Addon name could not be empty'); |
50 | } | 49 | } |
51 | - if (!$action || !in_array($action, ['create', 'disable', 'enable', 'install', 'uninstall', 'refresh', 'upgrade', 'package'])) | ||
52 | - { | 50 | + if (!$action || !in_array($action, ['create', 'disable', 'enable', 'install', 'uninstall', 'refresh', 'upgrade', 'package'])) { |
53 | throw new Exception('Please input correct action name'); | 51 | throw new Exception('Please input correct action name'); |
54 | } | 52 | } |
55 | 53 | ||
@@ -57,17 +55,14 @@ class Addon extends Command | @@ -57,17 +55,14 @@ class Addon extends Command | ||
57 | Db::execute("SELECT 1"); | 55 | Db::execute("SELECT 1"); |
58 | 56 | ||
59 | $addonDir = ADDON_PATH . $name . DS; | 57 | $addonDir = ADDON_PATH . $name . DS; |
60 | - switch ($action) | ||
61 | - { | 58 | + switch ($action) { |
62 | case 'create': | 59 | case 'create': |
63 | //非覆盖模式时如果存在则报错 | 60 | //非覆盖模式时如果存在则报错 |
64 | - if (is_dir($addonDir) && !$force) | ||
65 | - { | 61 | + if (is_dir($addonDir) && !$force) { |
66 | throw new Exception("addon already exists!\nIf you need to create again, use the parameter --force=true "); | 62 | throw new Exception("addon already exists!\nIf you need to create again, use the parameter --force=true "); |
67 | } | 63 | } |
68 | //如果存在先移除 | 64 | //如果存在先移除 |
69 | - if (is_dir($addonDir)) | ||
70 | - { | 65 | + if (is_dir($addonDir)) { |
71 | rmdirs($addonDir); | 66 | rmdirs($addonDir); |
72 | } | 67 | } |
73 | mkdir($addonDir); | 68 | mkdir($addonDir); |
@@ -76,16 +71,12 @@ class Addon extends Command | @@ -76,16 +71,12 @@ class Addon extends Command | ||
76 | $createMenu = $this->getCreateMenu($menuList); | 71 | $createMenu = $this->getCreateMenu($menuList); |
77 | $prefix = Config::get('database.prefix'); | 72 | $prefix = Config::get('database.prefix'); |
78 | $createTableSql = ''; | 73 | $createTableSql = ''; |
79 | - try | ||
80 | - { | 74 | + try { |
81 | $result = Db::query("SHOW CREATE TABLE `" . $prefix . $name . "`;"); | 75 | $result = Db::query("SHOW CREATE TABLE `" . $prefix . $name . "`;"); |
82 | - if (isset($result[0]) && isset($result[0]['Create Table'])) | ||
83 | - { | 76 | + if (isset($result[0]) && isset($result[0]['Create Table'])) { |
84 | $createTableSql = $result[0]['Create Table']; | 77 | $createTableSql = $result[0]['Create Table']; |
85 | } | 78 | } |
86 | - } | ||
87 | - catch (PDOException $e) | ||
88 | - { | 79 | + } catch (PDOException $e) { |
89 | 80 | ||
90 | } | 81 | } |
91 | 82 | ||
@@ -102,8 +93,7 @@ class Addon extends Command | @@ -102,8 +93,7 @@ class Addon extends Command | ||
102 | $this->writeToFile("config", $data, $addonDir . 'config.php'); | 93 | $this->writeToFile("config", $data, $addonDir . 'config.php'); |
103 | $this->writeToFile("info", $data, $addonDir . 'info.ini'); | 94 | $this->writeToFile("info", $data, $addonDir . 'info.ini'); |
104 | $this->writeToFile("controller", $data, $addonDir . 'controller' . DS . 'Index.php'); | 95 | $this->writeToFile("controller", $data, $addonDir . 'controller' . DS . 'Index.php'); |
105 | - if ($createTableSql) | ||
106 | - { | 96 | + if ($createTableSql) { |
107 | $createTableSql = str_replace("`" . $prefix, '`__PREFIX__', $createTableSql); | 97 | $createTableSql = str_replace("`" . $prefix, '`__PREFIX__', $createTableSql); |
108 | file_put_contents($addonDir . 'install.sql', $createTableSql); | 98 | file_put_contents($addonDir . 'install.sql', $createTableSql); |
109 | } | 99 | } |
@@ -112,75 +102,61 @@ class Addon extends Command | @@ -112,75 +102,61 @@ class Addon extends Command | ||
112 | break; | 102 | break; |
113 | case 'disable': | 103 | case 'disable': |
114 | case 'enable': | 104 | case 'enable': |
115 | - try | ||
116 | - { | 105 | + try { |
117 | //调用启用、禁用的方法 | 106 | //调用启用、禁用的方法 |
118 | Service::$action($name, 0); | 107 | Service::$action($name, 0); |
119 | - } | ||
120 | - catch (AddonException $e) | ||
121 | - { | ||
122 | - if ($e->getCode() != -3) | ||
123 | - { | 108 | + } catch (AddonException $e) { |
109 | + if ($e->getCode() != -3) { | ||
124 | throw new Exception($e->getMessage()); | 110 | throw new Exception($e->getMessage()); |
125 | } | 111 | } |
126 | - //如果有冲突文件则提醒 | ||
127 | - $data = $e->getData(); | ||
128 | - foreach ($data['conflictlist'] as $k => $v) | ||
129 | - { | ||
130 | - $output->warning($v); | ||
131 | - } | ||
132 | - $output->info("Are you sure you want to " . ($action == 'enable' ? 'override' : 'delete') . " all those files? Type 'yes' to continue: "); | ||
133 | - $line = fgets(STDIN); | ||
134 | - if (trim($line) != 'yes') | ||
135 | - { | ||
136 | - throw new Exception("Operation is aborted!"); | 112 | + if (!$force) { |
113 | + //如果有冲突文件则提醒 | ||
114 | + $data = $e->getData(); | ||
115 | + foreach ($data['conflictlist'] as $k => $v) { | ||
116 | + $output->warning($v); | ||
117 | + } | ||
118 | + $output->info("Are you sure you want to " . ($action == 'enable' ? 'override' : 'delete') . " all those files? Type 'yes' to continue: "); | ||
119 | + $line = fgets(STDIN); | ||
120 | + if (trim($line) != 'yes') { | ||
121 | + throw new Exception("Operation is aborted!"); | ||
122 | + } | ||
137 | } | 123 | } |
138 | //调用启用、禁用的方法 | 124 | //调用启用、禁用的方法 |
139 | Service::$action($name, 1); | 125 | Service::$action($name, 1); |
140 | - } | ||
141 | - catch (Exception $e) | ||
142 | - { | 126 | + } catch (Exception $e) { |
143 | throw new Exception($e->getMessage()); | 127 | throw new Exception($e->getMessage()); |
144 | } | 128 | } |
145 | $output->info(ucfirst($action) . " Successed!"); | 129 | $output->info(ucfirst($action) . " Successed!"); |
146 | break; | 130 | break; |
147 | case 'install': | 131 | case 'install': |
148 | //非覆盖模式时如果存在则报错 | 132 | //非覆盖模式时如果存在则报错 |
149 | - if (is_dir($addonDir) && !$force) | ||
150 | - { | 133 | + if (is_dir($addonDir) && !$force) { |
151 | throw new Exception("addon already exists!\nIf you need to install again, use the parameter --force=true "); | 134 | throw new Exception("addon already exists!\nIf you need to install again, use the parameter --force=true "); |
152 | } | 135 | } |
153 | //如果存在先移除 | 136 | //如果存在先移除 |
154 | - if (is_dir($addonDir)) | ||
155 | - { | 137 | + if (is_dir($addonDir)) { |
156 | rmdirs($addonDir); | 138 | rmdirs($addonDir); |
157 | } | 139 | } |
158 | - try | ||
159 | - { | 140 | + try { |
160 | Service::install($name, 0, ['version' => $release]); | 141 | Service::install($name, 0, ['version' => $release]); |
161 | - } | ||
162 | - catch (AddonException $e) | ||
163 | - { | ||
164 | - if ($e->getCode() != -3) | ||
165 | - { | 142 | + } catch (AddonException $e) { |
143 | + if ($e->getCode() != -3) { | ||
166 | throw new Exception($e->getMessage()); | 144 | throw new Exception($e->getMessage()); |
167 | } | 145 | } |
168 | - //如果有冲突文件则提醒 | ||
169 | - $data = $e->getData(); | ||
170 | - foreach ($data['conflictlist'] as $k => $v) | ||
171 | - { | ||
172 | - $output->warning($v); | ||
173 | - } | ||
174 | - $output->info("Are you sure you want to override all those files? Type 'yes' to continue: "); | ||
175 | - $line = fgets(STDIN); | ||
176 | - if (trim($line) != 'yes') | ||
177 | - { | ||
178 | - throw new Exception("Operation is aborted!"); | 146 | + if (!$force) { |
147 | + //如果有冲突文件则提醒 | ||
148 | + $data = $e->getData(); | ||
149 | + foreach ($data['conflictlist'] as $k => $v) { | ||
150 | + $output->warning($v); | ||
151 | + } | ||
152 | + $output->info("Are you sure you want to override all those files? Type 'yes' to continue: "); | ||
153 | + $line = fgets(STDIN); | ||
154 | + if (trim($line) != 'yes') { | ||
155 | + throw new Exception("Operation is aborted!"); | ||
156 | + } | ||
179 | } | 157 | } |
180 | Service::install($name, 1, ['version' => $release, 'uid' => $uid, 'token' => $token]); | 158 | Service::install($name, 1, ['version' => $release, 'uid' => $uid, 'token' => $token]); |
181 | - } | ||
182 | - catch (Exception $e) | ||
183 | - { | 159 | + } catch (Exception $e) { |
184 | throw new Exception($e->getMessage()); | 160 | throw new Exception($e->getMessage()); |
185 | } | 161 | } |
186 | 162 | ||
@@ -188,36 +164,29 @@ class Addon extends Command | @@ -188,36 +164,29 @@ class Addon extends Command | ||
188 | break; | 164 | break; |
189 | case 'uninstall': | 165 | case 'uninstall': |
190 | //非覆盖模式时如果存在则报错 | 166 | //非覆盖模式时如果存在则报错 |
191 | - if (!$force) | ||
192 | - { | 167 | + if (!$force) { |
193 | throw new Exception("If you need to uninstall addon, use the parameter --force=true "); | 168 | throw new Exception("If you need to uninstall addon, use the parameter --force=true "); |
194 | } | 169 | } |
195 | - try | ||
196 | - { | 170 | + try { |
197 | Service::uninstall($name, 0); | 171 | Service::uninstall($name, 0); |
198 | - } | ||
199 | - catch (AddonException $e) | ||
200 | - { | ||
201 | - if ($e->getCode() != -3) | ||
202 | - { | 172 | + } catch (AddonException $e) { |
173 | + if ($e->getCode() != -3) { | ||
203 | throw new Exception($e->getMessage()); | 174 | throw new Exception($e->getMessage()); |
204 | } | 175 | } |
205 | - //如果有冲突文件则提醒 | ||
206 | - $data = $e->getData(); | ||
207 | - foreach ($data['conflictlist'] as $k => $v) | ||
208 | - { | ||
209 | - $output->warning($v); | ||
210 | - } | ||
211 | - $output->info("Are you sure you want to delete all those files? Type 'yes' to continue: "); | ||
212 | - $line = fgets(STDIN); | ||
213 | - if (trim($line) != 'yes') | ||
214 | - { | ||
215 | - throw new Exception("Operation is aborted!"); | 176 | + if (!$force) { |
177 | + //如果有冲突文件则提醒 | ||
178 | + $data = $e->getData(); | ||
179 | + foreach ($data['conflictlist'] as $k => $v) { | ||
180 | + $output->warning($v); | ||
181 | + } | ||
182 | + $output->info("Are you sure you want to delete all those files? Type 'yes' to continue: "); | ||
183 | + $line = fgets(STDIN); | ||
184 | + if (trim($line) != 'yes') { | ||
185 | + throw new Exception("Operation is aborted!"); | ||
186 | + } | ||
216 | } | 187 | } |
217 | Service::uninstall($name, 1); | 188 | Service::uninstall($name, 1); |
218 | - } | ||
219 | - catch (Exception $e) | ||
220 | - { | 189 | + } catch (Exception $e) { |
221 | throw new Exception($e->getMessage()); | 190 | throw new Exception($e->getMessage()); |
222 | } | 191 | } |
223 | 192 | ||
@@ -233,53 +202,44 @@ class Addon extends Command | @@ -233,53 +202,44 @@ class Addon extends Command | ||
233 | break; | 202 | break; |
234 | case 'package': | 203 | case 'package': |
235 | $infoFile = $addonDir . 'info.ini'; | 204 | $infoFile = $addonDir . 'info.ini'; |
236 | - if (!is_file($infoFile)) | ||
237 | - { | 205 | + if (!is_file($infoFile)) { |
238 | throw new Exception(__('Addon info file was not found')); | 206 | throw new Exception(__('Addon info file was not found')); |
239 | } | 207 | } |
240 | 208 | ||
241 | $info = get_addon_info($name); | 209 | $info = get_addon_info($name); |
242 | - if (!$info) | ||
243 | - { | 210 | + if (!$info) { |
244 | throw new Exception(__('Addon info file data incorrect')); | 211 | throw new Exception(__('Addon info file data incorrect')); |
245 | } | 212 | } |
246 | $infoname = isset($info['name']) ? $info['name'] : ''; | 213 | $infoname = isset($info['name']) ? $info['name'] : ''; |
247 | - if (!$infoname || !preg_match("/^[a-z]+$/i", $infoname) || $infoname != $name) | ||
248 | - { | 214 | + if (!$infoname || !preg_match("/^[a-z]+$/i", $infoname) || $infoname != $name) { |
249 | throw new Exception(__('Addon info name incorrect')); | 215 | throw new Exception(__('Addon info name incorrect')); |
250 | } | 216 | } |
251 | 217 | ||
252 | $infoversion = isset($info['version']) ? $info['version'] : ''; | 218 | $infoversion = isset($info['version']) ? $info['version'] : ''; |
253 | - if (!$infoversion || !preg_match("/^\d+\.\d+\.\d+$/i", $infoversion)) | ||
254 | - { | 219 | + if (!$infoversion || !preg_match("/^\d+\.\d+\.\d+$/i", $infoversion)) { |
255 | throw new Exception(__('Addon info version incorrect')); | 220 | throw new Exception(__('Addon info version incorrect')); |
256 | } | 221 | } |
257 | 222 | ||
258 | $addonTmpDir = RUNTIME_PATH . 'addons' . DS; | 223 | $addonTmpDir = RUNTIME_PATH . 'addons' . DS; |
259 | - if (!is_dir($addonTmpDir)) | ||
260 | - { | 224 | + if (!is_dir($addonTmpDir)) { |
261 | @mkdir($addonTmpDir, 0755, true); | 225 | @mkdir($addonTmpDir, 0755, true); |
262 | } | 226 | } |
263 | $addonFile = $addonTmpDir . $infoname . '-' . $infoversion . '.zip'; | 227 | $addonFile = $addonTmpDir . $infoname . '-' . $infoversion . '.zip'; |
264 | - if (!class_exists('ZipArchive')) | ||
265 | - { | 228 | + if (!class_exists('ZipArchive')) { |
266 | throw new Exception(__('ZinArchive not install')); | 229 | throw new Exception(__('ZinArchive not install')); |
267 | } | 230 | } |
268 | $zip = new \ZipArchive; | 231 | $zip = new \ZipArchive; |
269 | $zip->open($addonFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); | 232 | $zip->open($addonFile, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); |
270 | 233 | ||
271 | $files = new \RecursiveIteratorIterator( | 234 | $files = new \RecursiveIteratorIterator( |
272 | - new \RecursiveDirectoryIterator($addonDir), \RecursiveIteratorIterator::LEAVES_ONLY | 235 | + new \RecursiveDirectoryIterator($addonDir), \RecursiveIteratorIterator::LEAVES_ONLY |
273 | ); | 236 | ); |
274 | 237 | ||
275 | - foreach ($files as $name => $file) | ||
276 | - { | ||
277 | - if (!$file->isDir()) | ||
278 | - { | 238 | + foreach ($files as $name => $file) { |
239 | + if (!$file->isDir()) { | ||
279 | $filePath = $file->getRealPath(); | 240 | $filePath = $file->getRealPath(); |
280 | $relativePath = substr($filePath, strlen($addonDir)); | 241 | $relativePath = substr($filePath, strlen($addonDir)); |
281 | - if (!in_array($file->getFilename(), ['.git', '.DS_Store', 'Thumbs.db'])) | ||
282 | - { | 242 | + if (!in_array($file->getFilename(), ['.git', '.DS_Store', 'Thumbs.db'])) { |
283 | $zip->addFile($filePath, $relativePath); | 243 | $zip->addFile($filePath, $relativePath); |
284 | } | 244 | } |
285 | } | 245 | } |
@@ -301,22 +261,18 @@ class Addon extends Command | @@ -301,22 +261,18 @@ class Addon extends Command | ||
301 | protected function getCreateMenu($menu) | 261 | protected function getCreateMenu($menu) |
302 | { | 262 | { |
303 | $result = []; | 263 | $result = []; |
304 | - foreach ($menu as $k => & $v) | ||
305 | - { | 264 | + foreach ($menu as $k => & $v) { |
306 | $arr = [ | 265 | $arr = [ |
307 | 'name' => $v['name'], | 266 | 'name' => $v['name'], |
308 | 'title' => $v['title'], | 267 | 'title' => $v['title'], |
309 | ]; | 268 | ]; |
310 | - if ($v['icon'] != 'fa fa-circle-o') | ||
311 | - { | 269 | + if ($v['icon'] != 'fa fa-circle-o') { |
312 | $arr['icon'] = $v['icon']; | 270 | $arr['icon'] = $v['icon']; |
313 | } | 271 | } |
314 | - if ($v['ismenu']) | ||
315 | - { | 272 | + if ($v['ismenu']) { |
316 | $arr['ismenu'] = $v['ismenu']; | 273 | $arr['ismenu'] = $v['ismenu']; |
317 | } | 274 | } |
318 | - if (isset($v['childlist']) && $v['childlist']) | ||
319 | - { | 275 | + if (isset($v['childlist']) && $v['childlist']) { |
320 | $arr['sublist'] = $this->getCreateMenu($v['childlist']); | 276 | $arr['sublist'] = $this->getCreateMenu($v['childlist']); |
321 | } | 277 | } |
322 | $result[] = $arr; | 278 | $result[] = $arr; |
@@ -334,16 +290,14 @@ class Addon extends Command | @@ -334,16 +290,14 @@ class Addon extends Command | ||
334 | protected function writeToFile($name, $data, $pathname) | 290 | protected function writeToFile($name, $data, $pathname) |
335 | { | 291 | { |
336 | $search = $replace = []; | 292 | $search = $replace = []; |
337 | - foreach ($data as $k => $v) | ||
338 | - { | 293 | + foreach ($data as $k => $v) { |
339 | $search[] = "{%{$k}%}"; | 294 | $search[] = "{%{$k}%}"; |
340 | $replace[] = $v; | 295 | $replace[] = $v; |
341 | } | 296 | } |
342 | $stub = file_get_contents($this->getStub($name)); | 297 | $stub = file_get_contents($this->getStub($name)); |
343 | $content = str_replace($search, $replace, $stub); | 298 | $content = str_replace($search, $replace, $stub); |
344 | 299 | ||
345 | - if (!is_dir(dirname($pathname))) | ||
346 | - { | 300 | + if (!is_dir(dirname($pathname))) { |
347 | mkdir(strtolower(dirname($pathname)), 0755, true); | 301 | mkdir(strtolower(dirname($pathname)), 0755, true); |
348 | } | 302 | } |
349 | return file_put_contents($pathname, $content); | 303 | return file_put_contents($pathname, $content); |
@@ -9,7 +9,15 @@ | @@ -9,7 +9,15 @@ | ||
9 | <title>{$config.title}</title> | 9 | <title>{$config.title}</title> |
10 | <link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> | 10 | <link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> |
11 | <style type="text/css"> | 11 | <style type="text/css"> |
12 | - body { padding-top: 70px; margin-bottom: 15px; } | 12 | + body { |
13 | + padding-top: 70px; margin-bottom: 15px; | ||
14 | + -webkit-font-smoothing: antialiased; | ||
15 | + -moz-osx-font-smoothing: grayscale; | ||
16 | + font-family: "Roboto", "SF Pro SC", "SF Pro Display", "SF Pro Icons", "PingFang SC", BlinkMacSystemFont, -apple-system, "Segoe UI", "Microsoft Yahei", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif; | ||
17 | + font-weight: 400; | ||
18 | + } | ||
19 | + h2 { font-size: 1.6em; } | ||
20 | + hr { margin-top: 10px; } | ||
13 | .tab-pane { padding-top: 10px; } | 21 | .tab-pane { padding-top: 10px; } |
14 | .mt0 { margin-top: 0px; } | 22 | .mt0 { margin-top: 0px; } |
15 | .footer { font-size: 12px; color: #666; } | 23 | .footer { font-size: 12px; color: #666; } |
@@ -654,9 +654,10 @@ class Crud extends Command | @@ -654,9 +654,10 @@ class Crud extends Command | ||
654 | $priDefined = TRUE; | 654 | $priDefined = TRUE; |
655 | $javascriptList[] = "{checkbox: true}"; | 655 | $javascriptList[] = "{checkbox: true}"; |
656 | } | 656 | } |
657 | - //构造JS列信息 | ||
658 | - $javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr); | ||
659 | - | 657 | + if (!$fields || in_array($field, explode(',', $fields))) { |
658 | + //构造JS列信息 | ||
659 | + $javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr); | ||
660 | + } | ||
660 | //排序方式,如果有指定排序字段,否则按主键排序 | 661 | //排序方式,如果有指定排序字段,否则按主键排序 |
661 | $order = $field == $this->sortField ? $this->sortField : $order; | 662 | $order = $field == $this->sortField ? $this->sortField : $order; |
662 | } | 663 | } |
@@ -767,6 +768,11 @@ class Crud extends Command | @@ -767,6 +768,11 @@ class Crud extends Command | ||
767 | //构造关联模型的方法 | 768 | //构造关联模型的方法 |
768 | $relationMethodList[] = $this->getReplacedStub('mixins' . DS . 'modelrelationmethod', $relation); | 769 | $relationMethodList[] = $this->getReplacedStub('mixins' . DS . 'modelrelationmethod', $relation); |
769 | 770 | ||
771 | + //如果设置了显示主表字段,则必须显式将关联表字段显示 | ||
772 | + if ($fields) { | ||
773 | + $relationVisibleFieldList[] = "\$row->visible(['{$relation['relationMethod']}']);"; | ||
774 | + } | ||
775 | + | ||
770 | //显示的字段 | 776 | //显示的字段 |
771 | if ($relation['relationFields']) { | 777 | if ($relation['relationFields']) { |
772 | $relationVisibleFieldList[] = "\$row->getRelation('" . $relation['relationMethod'] . "')->visible(['" . implode("','", $relation['relationFields']) . "']);"; | 778 | $relationVisibleFieldList[] = "\$row->getRelation('" . $relation['relationMethod'] . "')->visible(['" . implode("','", $relation['relationFields']) . "']);"; |
@@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
3 | namespace app\admin\controller; | 3 | namespace app\admin\controller; |
4 | 4 | ||
5 | use app\common\controller\Backend; | 5 | use app\common\controller\Backend; |
6 | +use fast\Http; | ||
6 | use think\addons\AddonException; | 7 | use think\addons\AddonException; |
7 | use think\addons\Service; | 8 | use think\addons\Service; |
8 | use think\Cache; | 9 | use think\Cache; |
@@ -31,8 +32,7 @@ class Addon extends Backend | @@ -31,8 +32,7 @@ class Addon extends Backend | ||
31 | public function index() | 32 | public function index() |
32 | { | 33 | { |
33 | $addons = get_addon_list(); | 34 | $addons = get_addon_list(); |
34 | - foreach ($addons as $k => &$v) | ||
35 | - { | 35 | + foreach ($addons as $k => &$v) { |
36 | $config = get_addon_config($v['name']); | 36 | $config = get_addon_config($v['name']); |
37 | $v['config'] = $config ? 1 : 0; | 37 | $v['config'] = $config ? 1 : 0; |
38 | } | 38 | } |
@@ -46,60 +46,31 @@ class Addon extends Backend | @@ -46,60 +46,31 @@ class Addon extends Backend | ||
46 | public function config($ids = NULL) | 46 | public function config($ids = NULL) |
47 | { | 47 | { |
48 | $name = $this->request->get("name"); | 48 | $name = $this->request->get("name"); |
49 | - if (!$name) | ||
50 | - { | 49 | + if (!$name) { |
51 | $this->error(__('Parameter %s can not be empty', $ids ? 'id' : 'name')); | 50 | $this->error(__('Parameter %s can not be empty', $ids ? 'id' : 'name')); |
52 | } | 51 | } |
53 | - if (!is_dir(ADDON_PATH . $name)) | ||
54 | - { | 52 | + if (!is_dir(ADDON_PATH . $name)) { |
55 | $this->error(__('Directory not found')); | 53 | $this->error(__('Directory not found')); |
56 | } | 54 | } |
57 | $info = get_addon_info($name); | 55 | $info = get_addon_info($name); |
58 | $config = get_addon_fullconfig($name); | 56 | $config = get_addon_fullconfig($name); |
59 | if (!$info) | 57 | if (!$info) |
60 | $this->error(__('No Results were found')); | 58 | $this->error(__('No Results were found')); |
61 | - if ($this->request->isPost()) | ||
62 | - { | 59 | + if ($this->request->isPost()) { |
63 | $params = $this->request->post("row/a"); | 60 | $params = $this->request->post("row/a"); |
64 | - if ($params) | ||
65 | - { | ||
66 | - foreach ($config as $k => &$v) | ||
67 | - { | ||
68 | - if (isset($params[$v['name']])) | ||
69 | - { | ||
70 | - if ($v['type'] == 'array') | ||
71 | - { | ||
72 | - $fieldarr = $valuearr = []; | ||
73 | - $field = $params[$v['name']]['field']; | ||
74 | - $value = $params[$v['name']]['value']; | ||
75 | - | ||
76 | - foreach ($field as $m => $n) | ||
77 | - { | ||
78 | - if ($n != '') | ||
79 | - { | ||
80 | - $fieldarr[] = $field[$m]; | ||
81 | - $valuearr[] = $value[$m]; | ||
82 | - } | ||
83 | - } | ||
84 | - $params[$v['name']] = array_combine($fieldarr, $valuearr); | ||
85 | - $value = $params[$v['name']]; | ||
86 | - } | ||
87 | - else | ||
88 | - { | ||
89 | - $value = is_array($params[$v['name']]) ? implode(',', $params[$v['name']]) : $params[$v['name']]; | ||
90 | - } | ||
91 | - | 61 | + if ($params) { |
62 | + foreach ($config as $k => &$v) { | ||
63 | + if (isset($params[$v['name']])) { | ||
64 | + $value = is_array($params[$v['name']]) ? implode(',', $params[$v['name']]) : $params[$v['name']]; | ||
92 | $v['value'] = $value; | 65 | $v['value'] = $value; |
93 | } | 66 | } |
94 | } | 67 | } |
95 | - try | ||
96 | - { | 68 | + try { |
97 | //更新配置文件 | 69 | //更新配置文件 |
98 | set_addon_fullconfig($name, $config); | 70 | set_addon_fullconfig($name, $config); |
71 | + Service::refresh(); | ||
99 | $this->success(); | 72 | $this->success(); |
100 | - } | ||
101 | - catch (Exception $e) | ||
102 | - { | 73 | + } catch (Exception $e) { |
103 | $this->error($e->getMessage()); | 74 | $this->error($e->getMessage()); |
104 | } | 75 | } |
105 | } | 76 | } |
@@ -115,13 +86,11 @@ class Addon extends Backend | @@ -115,13 +86,11 @@ class Addon extends Backend | ||
115 | public function install() | 86 | public function install() |
116 | { | 87 | { |
117 | $name = $this->request->post("name"); | 88 | $name = $this->request->post("name"); |
118 | - $force = (int) $this->request->post("force"); | ||
119 | - if (!$name) | ||
120 | - { | 89 | + $force = (int)$this->request->post("force"); |
90 | + if (!$name) { | ||
121 | $this->error(__('Parameter %s can not be empty', 'name')); | 91 | $this->error(__('Parameter %s can not be empty', 'name')); |
122 | } | 92 | } |
123 | - try | ||
124 | - { | 93 | + try { |
125 | $uid = $this->request->post("uid"); | 94 | $uid = $this->request->post("uid"); |
126 | $token = $this->request->post("token"); | 95 | $token = $this->request->post("token"); |
127 | $version = $this->request->post("version"); | 96 | $version = $this->request->post("version"); |
@@ -137,13 +106,9 @@ class Addon extends Backend | @@ -137,13 +106,9 @@ class Addon extends Backend | ||
137 | $info['config'] = get_addon_config($name) ? 1 : 0; | 106 | $info['config'] = get_addon_config($name) ? 1 : 0; |
138 | $info['state'] = 1; | 107 | $info['state'] = 1; |
139 | $this->success(__('Install successful'), null, ['addon' => $info]); | 108 | $this->success(__('Install successful'), null, ['addon' => $info]); |
140 | - } | ||
141 | - catch (AddonException $e) | ||
142 | - { | 109 | + } catch (AddonException $e) { |
143 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); | 110 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); |
144 | - } | ||
145 | - catch (Exception $e) | ||
146 | - { | 111 | + } catch (Exception $e) { |
147 | $this->error($e->getMessage(), $e->getCode()); | 112 | $this->error($e->getMessage(), $e->getCode()); |
148 | } | 113 | } |
149 | } | 114 | } |
@@ -154,22 +119,16 @@ class Addon extends Backend | @@ -154,22 +119,16 @@ class Addon extends Backend | ||
154 | public function uninstall() | 119 | public function uninstall() |
155 | { | 120 | { |
156 | $name = $this->request->post("name"); | 121 | $name = $this->request->post("name"); |
157 | - $force = (int) $this->request->post("force"); | ||
158 | - if (!$name) | ||
159 | - { | 122 | + $force = (int)$this->request->post("force"); |
123 | + if (!$name) { | ||
160 | $this->error(__('Parameter %s can not be empty', 'name')); | 124 | $this->error(__('Parameter %s can not be empty', 'name')); |
161 | } | 125 | } |
162 | - try | ||
163 | - { | 126 | + try { |
164 | Service::uninstall($name, $force); | 127 | Service::uninstall($name, $force); |
165 | $this->success(__('Uninstall successful')); | 128 | $this->success(__('Uninstall successful')); |
166 | - } | ||
167 | - catch (AddonException $e) | ||
168 | - { | 129 | + } catch (AddonException $e) { |
169 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); | 130 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); |
170 | - } | ||
171 | - catch (Exception $e) | ||
172 | - { | 131 | + } catch (Exception $e) { |
173 | $this->error($e->getMessage()); | 132 | $this->error($e->getMessage()); |
174 | } | 133 | } |
175 | } | 134 | } |
@@ -181,25 +140,19 @@ class Addon extends Backend | @@ -181,25 +140,19 @@ class Addon extends Backend | ||
181 | { | 140 | { |
182 | $name = $this->request->post("name"); | 141 | $name = $this->request->post("name"); |
183 | $action = $this->request->post("action"); | 142 | $action = $this->request->post("action"); |
184 | - $force = (int) $this->request->post("force"); | ||
185 | - if (!$name) | ||
186 | - { | 143 | + $force = (int)$this->request->post("force"); |
144 | + if (!$name) { | ||
187 | $this->error(__('Parameter %s can not be empty', 'name')); | 145 | $this->error(__('Parameter %s can not be empty', 'name')); |
188 | } | 146 | } |
189 | - try | ||
190 | - { | 147 | + try { |
191 | $action = $action == 'enable' ? $action : 'disable'; | 148 | $action = $action == 'enable' ? $action : 'disable'; |
192 | //调用启用、禁用的方法 | 149 | //调用启用、禁用的方法 |
193 | Service::$action($name, $force); | 150 | Service::$action($name, $force); |
194 | Cache::rm('__menu__'); | 151 | Cache::rm('__menu__'); |
195 | $this->success(__('Operate successful')); | 152 | $this->success(__('Operate successful')); |
196 | - } | ||
197 | - catch (AddonException $e) | ||
198 | - { | 153 | + } catch (AddonException $e) { |
199 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); | 154 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); |
200 | - } | ||
201 | - catch (Exception $e) | ||
202 | - { | 155 | + } catch (Exception $e) { |
203 | $this->error($e->getMessage()); | 156 | $this->error($e->getMessage()); |
204 | } | 157 | } |
205 | } | 158 | } |
@@ -213,55 +166,46 @@ class Addon extends Backend | @@ -213,55 +166,46 @@ class Addon extends Backend | ||
213 | 166 | ||
214 | $file = $this->request->file('file'); | 167 | $file = $this->request->file('file'); |
215 | $addonTmpDir = RUNTIME_PATH . 'addons' . DS; | 168 | $addonTmpDir = RUNTIME_PATH . 'addons' . DS; |
216 | - if (!is_dir($addonTmpDir)) | ||
217 | - { | 169 | + if (!is_dir($addonTmpDir)) { |
218 | @mkdir($addonTmpDir, 0755, true); | 170 | @mkdir($addonTmpDir, 0755, true); |
219 | } | 171 | } |
220 | $info = $file->rule('uniqid')->validate(['size' => 10240000, 'ext' => 'zip'])->move($addonTmpDir); | 172 | $info = $file->rule('uniqid')->validate(['size' => 10240000, 'ext' => 'zip'])->move($addonTmpDir); |
221 | - if ($info) | ||
222 | - { | 173 | + if ($info) { |
223 | $tmpName = substr($info->getFilename(), 0, stripos($info->getFilename(), '.')); | 174 | $tmpName = substr($info->getFilename(), 0, stripos($info->getFilename(), '.')); |
224 | $tmpAddonDir = ADDON_PATH . $tmpName . DS; | 175 | $tmpAddonDir = ADDON_PATH . $tmpName . DS; |
225 | $tmpFile = $addonTmpDir . $info->getSaveName(); | 176 | $tmpFile = $addonTmpDir . $info->getSaveName(); |
226 | - try | ||
227 | - { | 177 | + try { |
228 | Service::unzip($tmpName); | 178 | Service::unzip($tmpName); |
229 | @unlink($tmpFile); | 179 | @unlink($tmpFile); |
230 | $infoFile = $tmpAddonDir . 'info.ini'; | 180 | $infoFile = $tmpAddonDir . 'info.ini'; |
231 | - if (!is_file($infoFile)) | ||
232 | - { | 181 | + if (!is_file($infoFile)) { |
233 | throw new Exception(__('Addon info file was not found')); | 182 | throw new Exception(__('Addon info file was not found')); |
234 | } | 183 | } |
235 | 184 | ||
236 | $config = Config::parse($infoFile, '', $tmpName); | 185 | $config = Config::parse($infoFile, '', $tmpName); |
237 | $name = isset($config['name']) ? $config['name'] : ''; | 186 | $name = isset($config['name']) ? $config['name'] : ''; |
238 | - if (!$name) | ||
239 | - { | 187 | + if (!$name) { |
240 | throw new Exception(__('Addon info file data incorrect')); | 188 | throw new Exception(__('Addon info file data incorrect')); |
241 | } | 189 | } |
242 | 190 | ||
243 | $newAddonDir = ADDON_PATH . $name . DS; | 191 | $newAddonDir = ADDON_PATH . $name . DS; |
244 | - if (is_dir($newAddonDir)) | ||
245 | - { | 192 | + if (is_dir($newAddonDir)) { |
246 | throw new Exception(__('Addon already exists')); | 193 | throw new Exception(__('Addon already exists')); |
247 | } | 194 | } |
248 | 195 | ||
249 | //重命名插件文件夹 | 196 | //重命名插件文件夹 |
250 | rename($tmpAddonDir, $newAddonDir); | 197 | rename($tmpAddonDir, $newAddonDir); |
251 | - try | ||
252 | - { | 198 | + try { |
253 | //默认禁用该插件 | 199 | //默认禁用该插件 |
254 | $info = get_addon_info($name); | 200 | $info = get_addon_info($name); |
255 | - if ($info['state']) | ||
256 | - { | 201 | + if ($info['state']) { |
257 | $info['state'] = 0; | 202 | $info['state'] = 0; |
258 | set_addon_info($name, $info); | 203 | set_addon_info($name, $info); |
259 | } | 204 | } |
260 | 205 | ||
261 | //执行插件的安装方法 | 206 | //执行插件的安装方法 |
262 | $class = get_addon_class($name); | 207 | $class = get_addon_class($name); |
263 | - if (class_exists($class)) | ||
264 | - { | 208 | + if (class_exists($class)) { |
265 | $addon = new $class(); | 209 | $addon = new $class(); |
266 | $addon->install(); | 210 | $addon->install(); |
267 | } | 211 | } |
@@ -271,22 +215,16 @@ class Addon extends Backend | @@ -271,22 +215,16 @@ class Addon extends Backend | ||
271 | 215 | ||
272 | $info['config'] = get_addon_config($name) ? 1 : 0; | 216 | $info['config'] = get_addon_config($name) ? 1 : 0; |
273 | $this->success(__('Offline installed tips'), null, ['addon' => $info]); | 217 | $this->success(__('Offline installed tips'), null, ['addon' => $info]); |
274 | - } | ||
275 | - catch (Exception $e) | ||
276 | - { | 218 | + } catch (Exception $e) { |
277 | @rmdirs($newAddonDir); | 219 | @rmdirs($newAddonDir); |
278 | throw new Exception($e->getMessage()); | 220 | throw new Exception($e->getMessage()); |
279 | } | 221 | } |
280 | - } | ||
281 | - catch (Exception $e) | ||
282 | - { | 222 | + } catch (Exception $e) { |
283 | @unlink($tmpFile); | 223 | @unlink($tmpFile); |
284 | @rmdirs($tmpAddonDir); | 224 | @rmdirs($tmpAddonDir); |
285 | $this->error($e->getMessage()); | 225 | $this->error($e->getMessage()); |
286 | } | 226 | } |
287 | - } | ||
288 | - else | ||
289 | - { | 227 | + } else { |
290 | // 上传失败获取错误信息 | 228 | // 上传失败获取错误信息 |
291 | $this->error($file->getError()); | 229 | $this->error($file->getError()); |
292 | } | 230 | } |
@@ -298,12 +236,10 @@ class Addon extends Backend | @@ -298,12 +236,10 @@ class Addon extends Backend | ||
298 | public function upgrade() | 236 | public function upgrade() |
299 | { | 237 | { |
300 | $name = $this->request->post("name"); | 238 | $name = $this->request->post("name"); |
301 | - if (!$name) | ||
302 | - { | 239 | + if (!$name) { |
303 | $this->error(__('Parameter %s can not be empty', 'name')); | 240 | $this->error(__('Parameter %s can not be empty', 'name')); |
304 | } | 241 | } |
305 | - try | ||
306 | - { | 242 | + try { |
307 | $uid = $this->request->post("uid"); | 243 | $uid = $this->request->post("uid"); |
308 | $token = $this->request->post("token"); | 244 | $token = $this->request->post("token"); |
309 | $version = $this->request->post("version"); | 245 | $version = $this->request->post("version"); |
@@ -318,29 +254,9 @@ class Addon extends Backend | @@ -318,29 +254,9 @@ class Addon extends Backend | ||
318 | Service::upgrade($name, $extend); | 254 | Service::upgrade($name, $extend); |
319 | Cache::rm('__menu__'); | 255 | Cache::rm('__menu__'); |
320 | $this->success(__('Operate successful')); | 256 | $this->success(__('Operate successful')); |
321 | - } | ||
322 | - catch (AddonException $e) | ||
323 | - { | 257 | + } catch (AddonException $e) { |
324 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); | 258 | $this->result($e->getData(), $e->getCode(), $e->getMessage()); |
325 | - } | ||
326 | - catch (Exception $e) | ||
327 | - { | ||
328 | - $this->error($e->getMessage()); | ||
329 | - } | ||
330 | - } | ||
331 | - | ||
332 | - /** | ||
333 | - * 刷新缓存 | ||
334 | - */ | ||
335 | - public function refresh() | ||
336 | - { | ||
337 | - try | ||
338 | - { | ||
339 | - Service::refresh(); | ||
340 | - $this->success(__('Operate successful')); | ||
341 | - } | ||
342 | - catch (Exception $e) | ||
343 | - { | 259 | + } catch (Exception $e) { |
344 | $this->error($e->getMessage()); | 260 | $this->error($e->getMessage()); |
345 | } | 261 | } |
346 | } | 262 | } |
@@ -350,31 +266,51 @@ class Addon extends Backend | @@ -350,31 +266,51 @@ class Addon extends Backend | ||
350 | */ | 266 | */ |
351 | public function downloaded() | 267 | public function downloaded() |
352 | { | 268 | { |
353 | - $offset = (int) $this->request->get("offset"); | ||
354 | - $limit = (int) $this->request->get("limit"); | 269 | + $offset = (int)$this->request->get("offset"); |
270 | + $limit = (int)$this->request->get("limit"); | ||
271 | + $filter = $this->request->get("filter"); | ||
355 | $search = $this->request->get("search"); | 272 | $search = $this->request->get("search"); |
356 | $search = htmlspecialchars(strip_tags($search)); | 273 | $search = htmlspecialchars(strip_tags($search)); |
357 | - | 274 | + $onlineaddons = Cache::get("onlineaddons"); |
275 | + if (!is_array($onlineaddons)) { | ||
276 | + $onlineaddons = []; | ||
277 | + $result = Http::sendRequest(config('fastadmin.api_url') . '/addon/index'); | ||
278 | + if ($result['ret']) { | ||
279 | + $json = json_decode($result['msg'], TRUE); | ||
280 | + $rows = isset($json['rows']) ? $json['rows'] : []; | ||
281 | + foreach ($rows as $index => $row) { | ||
282 | + $onlineaddons[$row['name']] = $row; | ||
283 | + } | ||
284 | + } | ||
285 | + Cache::set("onlineaddons", $onlineaddons, 600); | ||
286 | + } | ||
287 | + $filter = (array)json_decode($filter, true); | ||
358 | $addons = get_addon_list(); | 288 | $addons = get_addon_list(); |
359 | $list = []; | 289 | $list = []; |
360 | - foreach ($addons as $k => $v) | ||
361 | - { | 290 | + foreach ($addons as $k => $v) { |
362 | if ($search && stripos($v['name'], $search) === FALSE && stripos($v['intro'], $search) === FALSE) | 291 | if ($search && stripos($v['name'], $search) === FALSE && stripos($v['intro'], $search) === FALSE) |
363 | continue; | 292 | continue; |
364 | 293 | ||
365 | - $v['flag'] = ''; | ||
366 | - $v['banner'] = ''; | ||
367 | - $v['image'] = ''; | ||
368 | - $v['donateimage'] = ''; | ||
369 | - $v['demourl'] = ''; | ||
370 | - $v['price'] = '0.00'; | 294 | + if (isset($onlineaddons[$v['name']])) { |
295 | + $v = array_merge($onlineaddons[$v['name']], $v); | ||
296 | + } else { | ||
297 | + $v['category_id'] = 0; | ||
298 | + $v['flag'] = ''; | ||
299 | + $v['banner'] = ''; | ||
300 | + $v['image'] = ''; | ||
301 | + $v['donateimage'] = ''; | ||
302 | + $v['demourl'] = ''; | ||
303 | + $v['price'] = '0.00'; | ||
304 | + } | ||
371 | $v['url'] = addon_url($v['name']); | 305 | $v['url'] = addon_url($v['name']); |
372 | $v['createtime'] = filemtime(ADDON_PATH . $v['name']); | 306 | $v['createtime'] = filemtime(ADDON_PATH . $v['name']); |
307 | + if ($filter && isset($filter['category_id']) && is_numeric($filter['category_id']) && $filter['category_id'] != $v['category_id']) { | ||
308 | + continue; | ||
309 | + } | ||
373 | $list[] = $v; | 310 | $list[] = $v; |
374 | } | 311 | } |
375 | $total = count($list); | 312 | $total = count($list); |
376 | - if ($limit) | ||
377 | - { | 313 | + if ($limit) { |
378 | $list = array_slice($list, $offset, $limit); | 314 | $list = array_slice($list, $offset, $limit); |
379 | } | 315 | } |
380 | $result = array("total" => $total, "rows" => $list); | 316 | $result = array("total" => $total, "rows" => $list); |
@@ -4,6 +4,7 @@ namespace app\admin\controller; | @@ -4,6 +4,7 @@ namespace app\admin\controller; | ||
4 | 4 | ||
5 | use app\common\controller\Backend; | 5 | use app\common\controller\Backend; |
6 | use fast\Random; | 6 | use fast\Random; |
7 | +use think\addons\Service; | ||
7 | use think\Cache; | 8 | use think\Cache; |
8 | use think\Config; | 9 | use think\Config; |
9 | use think\Db; | 10 | use think\Db; |
@@ -47,8 +48,7 @@ class Ajax extends Backend | @@ -47,8 +48,7 @@ class Ajax extends Backend | ||
47 | { | 48 | { |
48 | Config::set('default_return_type', 'json'); | 49 | Config::set('default_return_type', 'json'); |
49 | $file = $this->request->file('file'); | 50 | $file = $this->request->file('file'); |
50 | - if (empty($file)) | ||
51 | - { | 51 | + if (empty($file)) { |
52 | $this->error(__('No file upload or server upload limit exceeded')); | 52 | $this->error(__('No file upload or server upload limit exceeded')); |
53 | } | 53 | } |
54 | 54 | ||
@@ -60,7 +60,7 @@ class Ajax extends Backend | @@ -60,7 +60,7 @@ class Ajax extends Backend | ||
60 | preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches); | 60 | preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches); |
61 | $type = strtolower($matches[2]); | 61 | $type = strtolower($matches[2]); |
62 | $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3]; | 62 | $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3]; |
63 | - $size = (int) $upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0); | 63 | + $size = (int)$upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0); |
64 | $fileInfo = $file->getInfo(); | 64 | $fileInfo = $file->getInfo(); |
65 | $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION)); | 65 | $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION)); |
66 | $suffix = $suffix ? $suffix : 'file'; | 66 | $suffix = $suffix ? $suffix : 'file'; |
@@ -68,8 +68,7 @@ class Ajax extends Backend | @@ -68,8 +68,7 @@ class Ajax extends Backend | ||
68 | $mimetypeArr = explode(',', $upload['mimetype']); | 68 | $mimetypeArr = explode(',', $upload['mimetype']); |
69 | $typeArr = explode('/', $fileInfo['type']); | 69 | $typeArr = explode('/', $fileInfo['type']); |
70 | //验证文件后缀 | 70 | //验证文件后缀 |
71 | - if ($upload['mimetype'] !== '*' && !in_array($suffix, $mimetypeArr) && !in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)) | ||
72 | - { | 71 | + if ($upload['mimetype'] !== '*' && !in_array($suffix, $mimetypeArr) && !in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)) { |
73 | $this->error(__('Uploaded file format is limited')); | 72 | $this->error(__('Uploaded file format is limited')); |
74 | } | 73 | } |
75 | $replaceArr = [ | 74 | $replaceArr = [ |
@@ -93,11 +92,9 @@ class Ajax extends Backend | @@ -93,11 +92,9 @@ class Ajax extends Backend | ||
93 | $fileName = substr($savekey, strripos($savekey, '/') + 1); | 92 | $fileName = substr($savekey, strripos($savekey, '/') + 1); |
94 | // | 93 | // |
95 | $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName); | 94 | $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName); |
96 | - if ($splInfo) | ||
97 | - { | 95 | + if ($splInfo) { |
98 | $imagewidth = $imageheight = 0; | 96 | $imagewidth = $imageheight = 0; |
99 | - if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'])) | ||
100 | - { | 97 | + if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'])) { |
101 | $imgInfo = getimagesize($splInfo->getPathname()); | 98 | $imgInfo = getimagesize($splInfo->getPathname()); |
102 | $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth; | 99 | $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth; |
103 | $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight; | 100 | $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight; |
@@ -121,9 +118,7 @@ class Ajax extends Backend | @@ -121,9 +118,7 @@ class Ajax extends Backend | ||
121 | $this->success(__('Upload successful'), null, [ | 118 | $this->success(__('Upload successful'), null, [ |
122 | 'url' => $uploadDir . $splInfo->getSaveName() | 119 | 'url' => $uploadDir . $splInfo->getSaveName() |
123 | ]); | 120 | ]); |
124 | - } | ||
125 | - else | ||
126 | - { | 121 | + } else { |
127 | // 上传失败获取错误信息 | 122 | // 上传失败获取错误信息 |
128 | $this->error($file->getError()); | 123 | $this->error($file->getError()); |
129 | } | 124 | } |
@@ -153,12 +148,10 @@ class Ajax extends Backend | @@ -153,12 +148,10 @@ class Ajax extends Backend | ||
153 | $field = in_array($field, ['weigh']) ? $field : 'weigh'; | 148 | $field = in_array($field, ['weigh']) ? $field : 'weigh'; |
154 | 149 | ||
155 | // 如果设定了pid的值,此时只匹配满足条件的ID,其它忽略 | 150 | // 如果设定了pid的值,此时只匹配满足条件的ID,其它忽略 |
156 | - if ($pid !== '') | ||
157 | - { | 151 | + if ($pid !== '') { |
158 | $hasids = []; | 152 | $hasids = []; |
159 | $list = Db::name($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pid)->field('id,pid')->select(); | 153 | $list = Db::name($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pid)->field('id,pid')->select(); |
160 | - foreach ($list as $k => $v) | ||
161 | - { | 154 | + foreach ($list as $k => $v) { |
162 | $hasids[] = $v['id']; | 155 | $hasids[] = $v['id']; |
163 | } | 156 | } |
164 | $ids = array_values(array_intersect($ids, $hasids)); | 157 | $ids = array_values(array_intersect($ids, $hasids)); |
@@ -166,20 +159,15 @@ class Ajax extends Backend | @@ -166,20 +159,15 @@ class Ajax extends Backend | ||
166 | 159 | ||
167 | //直接修复排序 | 160 | //直接修复排序 |
168 | $one = Db::name($table)->field("{$field},COUNT(*) AS nums")->group($field)->having('nums > 1')->find(); | 161 | $one = Db::name($table)->field("{$field},COUNT(*) AS nums")->group($field)->having('nums > 1')->find(); |
169 | - if ($one) | ||
170 | - { | 162 | + if ($one) { |
171 | $list = Db::name($table)->field("$prikey,$field")->order($field, $orderway)->select(); | 163 | $list = Db::name($table)->field("$prikey,$field")->order($field, $orderway)->select(); |
172 | - foreach ($list as $k => $v) | ||
173 | - { | 164 | + foreach ($list as $k => $v) { |
174 | Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]); | 165 | Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]); |
175 | } | 166 | } |
176 | $this->success(); | 167 | $this->success(); |
177 | - } | ||
178 | - else | ||
179 | - { | 168 | + } else { |
180 | $list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select(); | 169 | $list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select(); |
181 | - foreach ($list as $k => $v) | ||
182 | - { | 170 | + foreach ($list as $k => $v) { |
183 | $sour[] = $v[$prikey]; | 171 | $sour[] = $v[$prikey]; |
184 | $weighdata[$v[$prikey]] = $v[$field]; | 172 | $weighdata[$v[$prikey]] = $v[$field]; |
185 | } | 173 | } |
@@ -192,20 +180,13 @@ class Ajax extends Backend | @@ -192,20 +180,13 @@ class Ajax extends Backend | ||
192 | //echo "替换的ID:{$desc_id}\n"; | 180 | //echo "替换的ID:{$desc_id}\n"; |
193 | $weighids = array(); | 181 | $weighids = array(); |
194 | $temp = array_values(array_diff_assoc($ids, $sour)); | 182 | $temp = array_values(array_diff_assoc($ids, $sour)); |
195 | - foreach ($temp as $m => $n) | ||
196 | - { | ||
197 | - if ($n == $sour_id) | ||
198 | - { | 183 | + foreach ($temp as $m => $n) { |
184 | + if ($n == $sour_id) { | ||
199 | $offset = $desc_id; | 185 | $offset = $desc_id; |
200 | - } | ||
201 | - else | ||
202 | - { | ||
203 | - if ($sour_id == $temp[0]) | ||
204 | - { | 186 | + } else { |
187 | + if ($sour_id == $temp[0]) { | ||
205 | $offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id; | 188 | $offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id; |
206 | - } | ||
207 | - else | ||
208 | - { | 189 | + } else { |
209 | $offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id; | 190 | $offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id; |
210 | } | 191 | } |
211 | } | 192 | } |
@@ -221,15 +202,23 @@ class Ajax extends Backend | @@ -221,15 +202,23 @@ class Ajax extends Backend | ||
221 | */ | 202 | */ |
222 | public function wipecache() | 203 | public function wipecache() |
223 | { | 204 | { |
224 | - $wipe_cache_type = ['TEMP_PATH', 'LOG_PATH', 'CACHE_PATH']; | ||
225 | - foreach ($wipe_cache_type as $item) | ||
226 | - { | ||
227 | - $dir = constant($item); | ||
228 | - if (!is_dir($dir)) | ||
229 | - continue; | ||
230 | - rmdirs($dir); | 205 | + $type = $this->request->request("type"); |
206 | + switch ($type) { | ||
207 | + case 'content' || 'all': | ||
208 | + rmdirs(CACHE_PATH, false); | ||
209 | + Cache::clear(); | ||
210 | + if ($type == 'content') | ||
211 | + break; | ||
212 | + case 'template' || 'all': | ||
213 | + rmdirs(TEMP_PATH, false); | ||
214 | + if ($type == 'template') | ||
215 | + break; | ||
216 | + case 'addons' || 'all': | ||
217 | + Service::refresh(); | ||
218 | + if ($type == 'addons') | ||
219 | + break; | ||
231 | } | 220 | } |
232 | - Cache::clear(); | 221 | + |
233 | \think\Hook::listen("wipecache_after"); | 222 | \think\Hook::listen("wipecache_after"); |
234 | $this->success(); | 223 | $this->success(); |
235 | } | 224 | } |
@@ -243,14 +232,11 @@ class Ajax extends Backend | @@ -243,14 +232,11 @@ class Ajax extends Backend | ||
243 | $pid = $this->request->get('pid'); | 232 | $pid = $this->request->get('pid'); |
244 | $where = ['status' => 'normal']; | 233 | $where = ['status' => 'normal']; |
245 | $categorylist = null; | 234 | $categorylist = null; |
246 | - if ($pid !== '') | ||
247 | - { | ||
248 | - if ($type) | ||
249 | - { | 235 | + if ($pid !== '') { |
236 | + if ($type) { | ||
250 | $where['type'] = $type; | 237 | $where['type'] = $type; |
251 | } | 238 | } |
252 | - if ($pid) | ||
253 | - { | 239 | + if ($pid) { |
254 | $where['pid'] = $pid; | 240 | $where['pid'] = $pid; |
255 | } | 241 | } |
256 | 242 | ||
@@ -268,17 +254,13 @@ class Ajax extends Backend | @@ -268,17 +254,13 @@ class Ajax extends Backend | ||
268 | $city = $this->request->get('city'); | 254 | $city = $this->request->get('city'); |
269 | $where = ['pid' => 0, 'level' => 1]; | 255 | $where = ['pid' => 0, 'level' => 1]; |
270 | $provincelist = null; | 256 | $provincelist = null; |
271 | - if ($province !== '') | ||
272 | - { | ||
273 | - if ($province) | ||
274 | - { | 257 | + if ($province !== '') { |
258 | + if ($province) { | ||
275 | $where['pid'] = $province; | 259 | $where['pid'] = $province; |
276 | $where['level'] = 2; | 260 | $where['level'] = 2; |
277 | } | 261 | } |
278 | - if ($city !== '') | ||
279 | - { | ||
280 | - if ($city) | ||
281 | - { | 262 | + if ($city !== '') { |
263 | + if ($city) { | ||
282 | $where['pid'] = $city; | 264 | $where['pid'] = $city; |
283 | $where['level'] = 3; | 265 | $where['level'] = 3; |
284 | } | 266 | } |
@@ -30,6 +30,8 @@ return [ | @@ -30,6 +30,8 @@ return [ | ||
30 | 'Please disable addon first' => '请先禁用插件再进行升级', | 30 | 'Please disable addon first' => '请先禁用插件再进行升级', |
31 | 'Login now' => '立即登录', | 31 | 'Login now' => '立即登录', |
32 | 'Continue install' => '不登录,继续安装', | 32 | 'Continue install' => '不登录,继续安装', |
33 | + 'All' => '全部', | ||
34 | + 'Uncategoried' => '未归类', | ||
33 | 'Recommend' => '推荐', | 35 | 'Recommend' => '推荐', |
34 | 'Hot' => '热门', | 36 | 'Hot' => '热门', |
35 | 'New' => '新', | 37 | 'New' => '新', |
@@ -33,6 +33,10 @@ return [ | @@ -33,6 +33,10 @@ return [ | ||
33 | 'Wipe cache completed' => '清除缓存成功', | 33 | 'Wipe cache completed' => '清除缓存成功', |
34 | 'Wipe cache failed' => '清除缓存失败', | 34 | 'Wipe cache failed' => '清除缓存失败', |
35 | 'Wipe cache' => '清空缓存', | 35 | 'Wipe cache' => '清空缓存', |
36 | + 'Wipe all cache' => '一键清除缓存', | ||
37 | + 'Wipe content cache' => '清空内容缓存', | ||
38 | + 'Wipe template cache' => '清除模板缓存', | ||
39 | + 'Wipe addons cache' => '清除插件缓存', | ||
36 | 'Check for updates' => '检测更新', | 40 | 'Check for updates' => '检测更新', |
37 | 'Latest news' => '最新消息', | 41 | 'Latest news' => '最新消息', |
38 | 'View more' => '查看更多', | 42 | 'View more' => '查看更多', |
@@ -30,7 +30,7 @@ class Auth extends \fast\Auth | @@ -30,7 +30,7 @@ class Auth extends \fast\Auth | ||
30 | 30 | ||
31 | /** | 31 | /** |
32 | * 管理员登录 | 32 | * 管理员登录 |
33 | - * | 33 | + * |
34 | * @param string $username 用户名 | 34 | * @param string $username 用户名 |
35 | * @param string $password 密码 | 35 | * @param string $password 密码 |
36 | * @param int $keeptime 有效时长 | 36 | * @param int $keeptime 有效时长 |
@@ -44,7 +44,7 @@ class Auth extends \fast\Auth | @@ -44,7 +44,7 @@ class Auth extends \fast\Auth | ||
44 | $this->setError('Username is incorrect'); | 44 | $this->setError('Username is incorrect'); |
45 | return false; | 45 | return false; |
46 | } | 46 | } |
47 | - if ($admin->loginfailure >= 3 && time() - $admin->updatetime < 86400) | 47 | + if (Config::get('fastadmin.login_failure_retry') && $admin->loginfailure >= 10 && time() - $admin->updatetime < 86400) |
48 | { | 48 | { |
49 | $this->setError('Please try again after 1 day'); | 49 | $this->setError('Please try again after 1 day'); |
50 | return false; | 50 | return false; |
@@ -119,7 +119,7 @@ class Auth extends \fast\Auth | @@ -119,7 +119,7 @@ class Auth extends \fast\Auth | ||
119 | 119 | ||
120 | /** | 120 | /** |
121 | * 刷新保持登录的Cookie | 121 | * 刷新保持登录的Cookie |
122 | - * | 122 | + * |
123 | * @param int $keeptime | 123 | * @param int $keeptime |
124 | * @return boolean | 124 | * @return boolean |
125 | */ | 125 | */ |
@@ -155,6 +155,7 @@ class Auth extends \fast\Auth | @@ -155,6 +155,7 @@ class Auth extends \fast\Auth | ||
155 | return FALSE; | 155 | return FALSE; |
156 | } | 156 | } |
157 | 157 | ||
158 | + $arr = array_map('strtolower', $arr); | ||
158 | // 是否存在 | 159 | // 是否存在 |
159 | if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) | 160 | if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) |
160 | { | 161 | { |
@@ -21,20 +21,13 @@ | @@ -21,20 +21,13 @@ | ||
21 | <textarea name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}" {$item.extend}>{$item.value}</textarea> | 21 | <textarea name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}" {$item.extend}>{$item.value}</textarea> |
22 | {/case} | 22 | {/case} |
23 | {case array} | 23 | {case array} |
24 | - <dl class="fieldlist" rel="{$item.value|count}" data-name="row[{$item.name}]"> | 24 | + <dl class="fieldlist" data-name="row[{$item.name}]"> |
25 | <dd> | 25 | <dd> |
26 | <ins>{:__('Array key')}</ins> | 26 | <ins>{:__('Array key')}</ins> |
27 | <ins>{:__('Array value')}</ins> | 27 | <ins>{:__('Array value')}</ins> |
28 | </dd> | 28 | </dd> |
29 | - {foreach $item.value as $key => $vo} | ||
30 | - <dd class="form-inline"> | ||
31 | - <input type="text" name="row[{$item.name}][field][{$key}]" class="form-control" value="{$key}" size="10" /> | ||
32 | - <input type="text" name="row[{$item.name}][value][{$key}]" class="form-control" value="{$vo}" size="30" /> | ||
33 | - <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> | ||
34 | - <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span> | ||
35 | - </dd> | ||
36 | - {/foreach} | ||
37 | - <dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd> | 29 | + <dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd> |
30 | + <textarea name="row[{$item.name}]" cols="30" rows="5" class="hide">{$item.value|json_encode}</textarea> | ||
38 | </dl> | 31 | </dl> |
39 | {/case} | 32 | {/case} |
40 | {case datetime} | 33 | {case datetime} |
1 | <style type="text/css"> | 1 | <style type="text/css"> |
2 | .noimage {width:100%;text-align: center;background:#18bc9c;color:#fff;padding-bottom:66.66%;position:relative;} | 2 | .noimage {width:100%;text-align: center;background:#18bc9c;color:#fff;padding-bottom:66.66%;position:relative;} |
3 | .noimage > div {position: absolute;top:48%;width:100%;text-align:center;} | 3 | .noimage > div {position: absolute;top:48%;width:100%;text-align:center;} |
4 | - .addon {position: relative;} | 4 | + .addon {position: relative;border-color:#e4e4e4;} |
5 | .addon > span {position:absolute;left:15px;top:15px;z-index:9;} | 5 | .addon > span {position:absolute;left:15px;top:15px;z-index:9;} |
6 | .addon > span a{opacity: 0.5;border:none;color:#fff;} | 6 | .addon > span a{opacity: 0.5;border:none;color:#fff;} |
7 | .layui-layer-pay .layui-layer-content {padding:0;height:600px!important;} | 7 | .layui-layer-pay .layui-layer-content {padding:0;height:600px!important;} |
@@ -16,9 +16,34 @@ | @@ -16,9 +16,34 @@ | ||
16 | .status-disabled .noimage { | 16 | .status-disabled .noimage { |
17 | background:#d2d6de; | 17 | background:#d2d6de; |
18 | } | 18 | } |
19 | + @media (min-width: 992px) { | ||
20 | + .addon { | ||
21 | + -webkit-transition:all 0.3s ease; | ||
22 | + -moz-transition: all 0.3s ease; | ||
23 | + -o-transition: all 0.3s ease; | ||
24 | + transition: all 0.3s ease; | ||
25 | + } | ||
26 | + .addon:hover { | ||
27 | + border-color: #dddddd; | ||
28 | + -webkit-box-shadow: 0 26px 40px -24px rgba(0,36,100,0.3); | ||
29 | + -moz-box-shadow: 0 26px 40px -24px rgba(0,36,100,0.3); | ||
30 | + box-shadow: 0 26px 40px -24px rgba(0,36,100,0.3); | ||
31 | + -webkit-transition: all 0.3s ease; | ||
32 | + -moz-transition: all 0.3s ease; | ||
33 | + -o-transition: all 0.3s ease; | ||
34 | + transition: all 0.3s ease; | ||
35 | + } | ||
36 | + } | ||
19 | </style> | 37 | </style> |
20 | <div class="panel panel-default panel-intro"> | 38 | <div class="panel panel-default panel-intro"> |
21 | - {:build_heading()} | 39 | + <div class="panel-heading"> |
40 | + {:build_heading(null,FALSE)} | ||
41 | + <ul class="nav nav-tabs nav-category"> | ||
42 | + <li class="active"><a href="javascript:;" data-id="">{:__('All')}</a></li> | ||
43 | + <li><a href="javascript:;" data-id="0">{:__('Uncategoried')}</a></li> | ||
44 | + </ul> | ||
45 | + | ||
46 | + </div> | ||
22 | 47 | ||
23 | <div class="panel-body"> | 48 | <div class="panel-body"> |
24 | <div id="myTabContent" class="tab-content"> | 49 | <div id="myTabContent" class="tab-content"> |
@@ -27,10 +52,11 @@ | @@ -27,10 +52,11 @@ | ||
27 | <div id="toolbar" class="toolbar"> | 52 | <div id="toolbar" class="toolbar"> |
28 | {:build_toolbar('refresh')} | 53 | {:build_toolbar('refresh')} |
29 | <button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i> {:__('Offline install')}</button> | 54 | <button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i> {:__('Offline install')}</button> |
30 | - <a class="btn btn-success btn-ajax" href="addon/refresh"><i class="fa fa-refresh"></i> {:__('Refresh addon cache')}</a> | ||
31 | <div class="btn-group"> | 55 | <div class="btn-group"> |
32 | - <a href="#" class="btn btn-info btn-switch active" data-url="{$config.fastadmin.api_url}/addon/index"><i class="fa fa-cloud"></i> {:__('Online store')}</a> | ||
33 | - <a href="#" class="btn btn-info btn-switch" data-url="addon/downloaded"><i class="fa fa-laptop"></i> {:__('Local addon')}</a> | 56 | + <a href="#" class="btn btn-info btn-switch active" data-type="all" data-url="{$config.fastadmin.api_url}/addon/index"><i class="fa fa-list"></i> {:__('全部')}</a> |
57 | + <a href="#" class="btn btn-info btn-switch" data-type="free" data-url="{$config.fastadmin.api_url}/addon/index"><i class="fa fa-gift"></i> {:__('免费')}</a> | ||
58 | + <a href="#" class="btn btn-info btn-switch" data-type="price" data-url="{$config.fastadmin.api_url}/addon/index"><i class="fa fa-rmb"></i> {:__('付费')}</a> | ||
59 | + <a href="#" class="btn btn-info btn-switch" data-type="local" data-url="addon/downloaded"><i class="fa fa-laptop"></i> {:__('Local addon')}</a> | ||
34 | </div> | 60 | </div> |
35 | <a class="btn btn-primary btn-userinfo" href="javascript:;"><i class="fa fa-user"></i> {:__('Userinfo')}</a> | 61 | <a class="btn btn-primary btn-userinfo" href="javascript:;"><i class="fa fa-user"></i> {:__('Userinfo')}</a> |
36 | </div> | 62 | </div> |
@@ -44,6 +70,55 @@ | @@ -44,6 +70,55 @@ | ||
44 | </div> | 70 | </div> |
45 | </div> | 71 | </div> |
46 | </div> | 72 | </div> |
73 | +<script id="searchformtpl" type="text/html"> | ||
74 | + <form action="" class="form-commonsearch hide"> | ||
75 | + <div class="well" style="box-shadow:none;border-radius:2px;margin-bottom:10px;"> | ||
76 | + <div class="row"> | ||
77 | + <div class="col-xs-12 col-sm-6 col-md-3"> | ||
78 | + <div class="form-group"> | ||
79 | + <label class="control-label">标题</label> | ||
80 | + <input class="operate" type="hidden" data-name="title" value="like"/> | ||
81 | + <input class="form-control" type="text" name="title" placeholder="请输入查找的标题" value=""/> | ||
82 | + </div> | ||
83 | + </div> | ||
84 | + <div class="col-xs-12 col-sm-6 col-md-3"> | ||
85 | + <div class="form-group"> | ||
86 | + <label class="control-label">类型</label> | ||
87 | + <input class="operate" type="hidden" data-name="type" value="="/> | ||
88 | + <input class="form-control" type="text" name="type" placeholder="all" value=""/> | ||
89 | + </div> | ||
90 | + </div> | ||
91 | + <div class="col-xs-12 col-sm-6 col-md-3"> | ||
92 | + <div class="form-group"> | ||
93 | + <label class="control-label">分类</label> | ||
94 | + <input type="hidden" class="operate" data-name="category_id" value="="/> | ||
95 | + <input class="form-control" name="category_id" type="text" value=""> | ||
96 | + </div> | ||
97 | + </div> | ||
98 | + <div class="col-xs-12 col-sm-6 col-md-3"> | ||
99 | + <div class="form-group"> | ||
100 | + <label class="control-label">版本号</label> | ||
101 | + <input type="hidden" class="operate" data-name="faversion" value="="/> | ||
102 | + <input class="form-control" name="faversion" type="text" value="{$config.fastadmin.version}"> | ||
103 | + </div> | ||
104 | + </div> | ||
105 | + <div class="col-xs-12 col-sm-6 col-md-3"> | ||
106 | + <div class="form-group"> | ||
107 | + <label class="control-label"></label> | ||
108 | + <div class="row"> | ||
109 | + <div class="col-xs-6"> | ||
110 | + <input type="submit" class="btn btn-success btn-block" value="提交"/> | ||
111 | + </div> | ||
112 | + <div class="col-xs-6"> | ||
113 | + <input type="reset" class="btn btn-primary btn-block" value="重置"/> | ||
114 | + </div> | ||
115 | + </div> | ||
116 | + </div> | ||
117 | + </div> | ||
118 | + </div> | ||
119 | + </div> | ||
120 | + </form> | ||
121 | +</script> | ||
47 | <script id="logintpl" type="text/html"> | 122 | <script id="logintpl" type="text/html"> |
48 | <div> | 123 | <div> |
49 | <form class="form-horizontal"> | 124 | <form class="form-horizontal"> |
@@ -180,7 +255,7 @@ | @@ -180,7 +255,7 @@ | ||
180 | <%}%> | 255 | <%}%> |
181 | </a> | 256 | </a> |
182 | <div class="caption"> | 257 | <div class="caption"> |
183 | - <h4><%=item.title?item.title:'{:__('None')}'%> | 258 | + <h4><%=item.title?item.title:'{:__('None')}'%> |
184 | <% if(item.flag.indexOf("recommend")>-1){%> | 259 | <% if(item.flag.indexOf("recommend")>-1){%> |
185 | <span class="label label-success">{:__('Recommend')}</span> | 260 | <span class="label label-success">{:__('Recommend')}</span> |
186 | <% } %> | 261 | <% } %> |
@@ -203,7 +278,7 @@ | @@ -203,7 +278,7 @@ | ||
203 | <% if(!addon){ %> | 278 | <% if(!addon){ %> |
204 | <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> | 279 | <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> |
205 | <span class="btn-group"> | 280 | <span class="btn-group"> |
206 | - <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> | 281 | + <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> |
207 | <a class="btn btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;"> | 282 | <a class="btn btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;"> |
208 | <span class="fa fa-caret-down"></span> | 283 | <span class="fa fa-caret-down"></span> |
209 | </a> | 284 | </a> |
@@ -214,10 +289,10 @@ | @@ -214,10 +289,10 @@ | ||
214 | </ul> | 289 | </ul> |
215 | </span> | 290 | </span> |
216 | <% }else{%> | 291 | <% }else{%> |
217 | - <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> | 292 | + <a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>" data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a> |
218 | <% } %> | 293 | <% } %> |
219 | <% if(item.demourl){ %> | 294 | <% if(item.demourl){ %> |
220 | - <a href="<%=item.demourl%>" class="btn btn-primary btn-info btn-demo" target="_blank"><i class="fa fa-flash"></i> {:__('Demo')}</a> | 295 | + <a href="<%=item.demourl%>" class="btn btn-primary btn-info btn-demo" target="_blank"><i class="fa fa-flash"></i> {:__('Demo')}</a> |
221 | <% } %> | 296 | <% } %> |
222 | <% } %> | 297 | <% } %> |
223 | 298 | ||
@@ -235,7 +310,7 @@ | @@ -235,7 +310,7 @@ | ||
235 | <% if(addon && item && addon.version!=item.version){%> | 310 | <% if(addon && item && addon.version!=item.version){%> |
236 | <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> | 311 | <% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%> |
237 | <span class="btn-group"> | 312 | <span class="btn-group"> |
238 | - <a href="javascript:;" class="btn btn-info btn-success btn-upgrade" data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a> | 313 | + <a href="javascript:;" class="btn btn-info btn-success btn-upgrade" data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a> |
239 | <a class="btn btn-info dropdown-toggle" data-toggle="dropdown" href="javascript:;"> | 314 | <a class="btn btn-info dropdown-toggle" data-toggle="dropdown" href="javascript:;"> |
240 | <span class="fa fa-caret-down"></span> | 315 | <span class="fa fa-caret-down"></span> |
241 | </a> | 316 | </a> |
@@ -25,7 +25,7 @@ | @@ -25,7 +25,7 @@ | ||
25 | <a href="__PUBLIC__" target="_blank"><i class="fa fa-home" style="font-size:14px;"></i></a> | 25 | <a href="__PUBLIC__" target="_blank"><i class="fa fa-home" style="font-size:14px;"></i></a> |
26 | </li> | 26 | </li> |
27 | 27 | ||
28 | - <li class="dropdown notifications-menu"> | 28 | + <li class="dropdown notifications-menu hidden-xs"> |
29 | <a href="#" class="dropdown-toggle" data-toggle="dropdown"> | 29 | <a href="#" class="dropdown-toggle" data-toggle="dropdown"> |
30 | <i class="fa fa-bell-o"></i> | 30 | <i class="fa fa-bell-o"></i> |
31 | <span class="label label-warning"></span> | 31 | <span class="label label-warning"></span> |
@@ -41,19 +41,26 @@ | @@ -41,19 +41,26 @@ | ||
41 | <li class="footer"><a href="#" target="_blank">{:__('View more')}</a></li> | 41 | <li class="footer"><a href="#" target="_blank">{:__('View more')}</a></li> |
42 | </ul> | 42 | </ul> |
43 | </li> | 43 | </li> |
44 | - | ||
45 | - <li> | 44 | + |
45 | + <li class="hidden-xs"> | ||
46 | <a href="javascript:;" data-toggle="checkupdate" title="{:__('Check for updates')}"> | 46 | <a href="javascript:;" data-toggle="checkupdate" title="{:__('Check for updates')}"> |
47 | <i class="fa fa-refresh"></i> | 47 | <i class="fa fa-refresh"></i> |
48 | </a> | 48 | </a> |
49 | </li> | 49 | </li> |
50 | - | 50 | + |
51 | <li> | 51 | <li> |
52 | - <a href="javascript:;" data-toggle="wipecache" title="{:__('Wipe cache')}"> | 52 | + <a href="javascript:;" data-toggle="dropdown" title="{:__('Wipe cache')}"> |
53 | <i class="fa fa-trash"></i> | 53 | <i class="fa fa-trash"></i> |
54 | </a> | 54 | </a> |
55 | + <ul class="dropdown-menu wipecache"> | ||
56 | + <li><a href="javascript:;" data-type="all"><i class="fa fa-trash"></i> {:__('Wipe all cache')}</a></li> | ||
57 | + <li><a href="javascript:;" data-type="content"><i class="fa fa-file-text"></i> {:__('Wipe content cache')}</a></li> | ||
58 | + <li><a href="javascript:;" data-type="template"><i class="fa fa-file-image-o"></i> {:__('Wipe template cache')}</a></li> | ||
59 | + <li><a href="javascript:;" data-type="addons"><i class="fa fa-rocket"></i> {:__('Wipe addons cache')}</a></li> | ||
60 | + </ul> | ||
55 | </li> | 61 | </li> |
56 | 62 | ||
63 | + {if $Think.config.lang_switch_on} | ||
57 | <li class="hidden-xs"> | 64 | <li class="hidden-xs"> |
58 | <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-language"></i></a> | 65 | <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-language"></i></a> |
59 | <ul class="dropdown-menu"> | 66 | <ul class="dropdown-menu"> |
@@ -65,6 +72,7 @@ | @@ -65,6 +72,7 @@ | ||
65 | </li> | 72 | </li> |
66 | </ul> | 73 | </ul> |
67 | </li> | 74 | </li> |
75 | + {/if} | ||
68 | 76 | ||
69 | <li class="hidden-xs"> | 77 | <li class="hidden-xs"> |
70 | <a href="#" data-toggle="fullscreen"><i class="fa fa-arrows-alt"></i></a> | 78 | <a href="#" data-toggle="fullscreen"><i class="fa fa-arrows-alt"></i></a> |
@@ -103,16 +111,18 @@ | @@ -103,16 +111,18 @@ | ||
103 | <!-- Menu Footer--> | 111 | <!-- Menu Footer--> |
104 | <li class="user-footer"> | 112 | <li class="user-footer"> |
105 | <div class="pull-left"> | 113 | <div class="pull-left"> |
106 | - <a href="general/profile" class="btn btn-primary addtabsit"><i class="fa fa-user"></i> {:__('Profile')}</a> | 114 | + <a href="general/profile" class="btn btn-primary addtabsit"><i class="fa fa-user"></i> |
115 | + {:__('Profile')}</a> | ||
107 | </div> | 116 | </div> |
108 | <div class="pull-right"> | 117 | <div class="pull-right"> |
109 | - <a href="{:url('index/logout')}" class="btn btn-danger"><i class="fa fa-sign-out"></i> {:__('Logout')}</a> | 118 | + <a href="{:url('index/logout')}" class="btn btn-danger"><i class="fa fa-sign-out"></i> |
119 | + {:__('Logout')}</a> | ||
110 | </div> | 120 | </div> |
111 | </li> | 121 | </li> |
112 | </ul> | 122 | </ul> |
113 | </li> | 123 | </li> |
114 | <!-- 控制栏切换按钮 --> | 124 | <!-- 控制栏切换按钮 --> |
115 | - <li> | 125 | + <li class="hidden-xs"> |
116 | <a href="javascript:;" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a> | 126 | <a href="javascript:;" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a> |
117 | </li> | 127 | </li> |
118 | </ul> | 128 | </ul> |
@@ -80,7 +80,7 @@ | @@ -80,7 +80,7 @@ | ||
80 | <div class="input-group"> | 80 | <div class="input-group"> |
81 | <div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div> | 81 | <div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div> |
82 | <input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length(4)" /> | 82 | <input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length(4)" /> |
83 | - <span class="input-group-addon" style="padding:0;border:none;"> | 83 | + <span class="input-group-addon" style="padding:0;border:none;cursor:pointer;"> |
84 | <img src="{:captcha_src()}" width="100" height="30" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/> | 84 | <img src="{:captcha_src()}" width="100" height="30" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/> |
85 | </span> | 85 | </span> |
86 | </div> | 86 | </div> |
@@ -97,7 +97,7 @@ | @@ -97,7 +97,7 @@ | ||
97 | </form> | 97 | </form> |
98 | </div> | 98 | </div> |
99 | </div> | 99 | </div> |
100 | - <p class="copyright"><a href="https://www.fastadmin.net?ref=demo">Powered By FastAdmin</a></p> | 100 | + <p class="copyright"><a href="https://www.fastadmin.net">Powered By FastAdmin</a></p> |
101 | </div> | 101 | </div> |
102 | </div> | 102 | </div> |
103 | </div> | 103 | </div> |
@@ -279,6 +279,7 @@ class Backend extends Controller | @@ -279,6 +279,7 @@ class Backend extends Controller | ||
279 | { | 279 | { |
280 | $k = $tableName . $k; | 280 | $k = $tableName . $k; |
281 | } | 281 | } |
282 | + $v = !is_array($v) ? trim($v) : $v; | ||
282 | $sym = strtoupper(isset($op[$k]) ? $op[$k] : $sym); | 283 | $sym = strtoupper(isset($op[$k]) ? $op[$k] : $sym); |
283 | switch ($sym) | 284 | switch ($sym) |
284 | { | 285 | { |
@@ -306,7 +307,7 @@ class Backend extends Controller | @@ -306,7 +307,7 @@ class Backend extends Controller | ||
306 | case 'IN(...)': | 307 | case 'IN(...)': |
307 | case 'NOT IN': | 308 | case 'NOT IN': |
308 | case 'NOT IN(...)': | 309 | case 'NOT IN(...)': |
309 | - $where[] = [$k, str_replace('(...)', '', $sym), explode(',', $v)]; | 310 | + $where[] = [$k, str_replace('(...)', '', $sym), is_array($v) ? $v : explode(',', $v)]; |
310 | break; | 311 | break; |
311 | case 'BETWEEN': | 312 | case 'BETWEEN': |
312 | case 'NOT BETWEEN': | 313 | case 'NOT BETWEEN': |
@@ -382,6 +382,7 @@ class Auth | @@ -382,6 +382,7 @@ class Auth | ||
382 | $rules[] = $v['name']; | 382 | $rules[] = $v['name']; |
383 | } | 383 | } |
384 | $url = ($module ? $module : request()->module()) . '/' . (is_null($path) ? $this->getRequestUri() : $path); | 384 | $url = ($module ? $module : request()->module()) . '/' . (is_null($path) ? $this->getRequestUri() : $path); |
385 | + $url = strtolower(str_replace('.', '/', $url)); | ||
385 | return in_array($url, $rules) ? TRUE : FALSE; | 386 | return in_array($url, $rules) ? TRUE : FALSE; |
386 | } | 387 | } |
387 | 388 | ||
@@ -539,6 +540,7 @@ class Auth | @@ -539,6 +540,7 @@ class Auth | ||
539 | { | 540 | { |
540 | return FALSE; | 541 | return FALSE; |
541 | } | 542 | } |
543 | + $arr = array_map('strtolower', $arr); | ||
542 | // 是否存在 | 544 | // 是否存在 |
543 | if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) | 545 | if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) |
544 | { | 546 | { |
@@ -21,6 +21,13 @@ class Category Extends Model | @@ -21,6 +21,13 @@ class Category Extends Model | ||
21 | 'flag_text', | 21 | 'flag_text', |
22 | ]; | 22 | ]; |
23 | 23 | ||
24 | + protected static function init() | ||
25 | + { | ||
26 | + self::afterInsert(function ($row) { | ||
27 | + $row->save(['weigh' => $row['id']]); | ||
28 | + }); | ||
29 | + } | ||
30 | + | ||
24 | public function setFlagAttr($value, $data) | 31 | public function setFlagAttr($value, $data) |
25 | { | 32 | { |
26 | return is_array($value) ? implode(',', $value) : $value; | 33 | return is_array($value) ? implode(',', $value) : $value; |
@@ -258,18 +258,20 @@ return [ | @@ -258,18 +258,20 @@ return [ | ||
258 | //FastAdmin配置 | 258 | //FastAdmin配置 |
259 | 'fastadmin' => [ | 259 | 'fastadmin' => [ |
260 | //是否开启前台会员中心 | 260 | //是否开启前台会员中心 |
261 | - 'usercenter' => true, | 261 | + 'usercenter' => true, |
262 | //登录验证码 | 262 | //登录验证码 |
263 | - 'login_captcha' => false, | 263 | + 'login_captcha' => true, |
264 | + //登录失败超过10则1天后重试 | ||
265 | + 'login_failure_retry' => true, | ||
264 | //是否同一账号同一时间只能在一个地方登录 | 266 | //是否同一账号同一时间只能在一个地方登录 |
265 | - 'login_unique' => false, | 267 | + 'login_unique' => false, |
266 | //登录页默认背景图 | 268 | //登录页默认背景图 |
267 | - 'login_background' => "/assets/img/loginbg.jpg", | 269 | + 'login_background' => "/assets/img/loginbg.jpg", |
268 | //自动检测更新 | 270 | //自动检测更新 |
269 | - 'checkupdate' => false, | 271 | + 'checkupdate' => false, |
270 | //版本号 | 272 | //版本号 |
271 | - 'version' => '1.0.0.20180401_beta', | 273 | + 'version' => '1.0.0.20180406_beta', |
272 | //API接口地址 | 274 | //API接口地址 |
273 | - 'api_url' => 'https://api.fastadmin.net', | 275 | + 'api_url' => 'https://api.fastadmin.net', |
274 | ], | 276 | ], |
275 | ]; | 277 | ]; |
@@ -9,7 +9,15 @@ | @@ -9,7 +9,15 @@ | ||
9 | <title>FastAdmin</title> | 9 | <title>FastAdmin</title> |
10 | <link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> | 10 | <link href="https://cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> |
11 | <style type="text/css"> | 11 | <style type="text/css"> |
12 | - body { padding-top: 70px; margin-bottom: 15px; } | 12 | + body { |
13 | + padding-top: 70px; margin-bottom: 15px; | ||
14 | + -webkit-font-smoothing: antialiased; | ||
15 | + -moz-osx-font-smoothing: grayscale; | ||
16 | + font-family: "Roboto", "SF Pro SC", "SF Pro Display", "SF Pro Icons", "PingFang SC", BlinkMacSystemFont, -apple-system, "Segoe UI", "Microsoft Yahei", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif; | ||
17 | + font-weight: 400; | ||
18 | + } | ||
19 | + h2 { font-size: 1.6em; } | ||
20 | + hr { margin-top: 10px; } | ||
13 | .tab-pane { padding-top: 10px; } | 21 | .tab-pane { padding-top: 10px; } |
14 | .mt0 { margin-top: 0px; } | 22 | .mt0 { margin-top: 0px; } |
15 | .footer { font-size: 12px; color: #666; } | 23 | .footer { font-size: 12px; color: #666; } |
@@ -3351,7 +3359,7 @@ | @@ -3351,7 +3359,7 @@ | ||
3351 | 3359 | ||
3352 | <div class="row mt0 footer"> | 3360 | <div class="row mt0 footer"> |
3353 | <div class="col-md-6" align="left"> | 3361 | <div class="col-md-6" align="left"> |
3354 | - Generated on 2018-04-01 15:11:14 </div> | 3362 | + Generated on 2018-04-06 19:15:01 </div> |
3355 | <div class="col-md-6" align="right"> | 3363 | <div class="col-md-6" align="right"> |
3356 | <a href="https://www.fastadmin.net" target="_blank">FastAdmin</a> | 3364 | <a href="https://www.fastadmin.net" target="_blank">FastAdmin</a> |
3357 | </div> | 3365 | </div> |
@@ -807,4 +807,6 @@ form.form-horizontal .control-label { | @@ -807,4 +807,6 @@ form.form-horizontal .control-label { | ||
807 | .checkbox > label > input { | 807 | .checkbox > label > input { |
808 | margin: 2px 0 0; | 808 | margin: 2px 0 0; |
809 | } | 809 | } |
810 | -/*# sourceMappingURL=backend.css.map */ | ||
810 | +.wipecache li a { | ||
811 | + color: #444444!important; | ||
812 | +} |
此 diff 太大无法显示。
@@ -4,7 +4,10 @@ body { | @@ -4,7 +4,10 @@ body { | ||
4 | width: 100%; | 4 | width: 100%; |
5 | } | 5 | } |
6 | body { | 6 | body { |
7 | - font-family: 'Muli', 'Helvetica', 'Arial', 'sans-serif'; | 7 | + -webkit-font-smoothing: antialiased; |
8 | + -moz-osx-font-smoothing: grayscale; | ||
9 | + font-family: "Roboto", "SF Pro SC", "SF Pro Display", "SF Pro Icons", "PingFang SC", BlinkMacSystemFont, -apple-system, "Segoe UI", "Microsoft Yahei", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif; | ||
10 | + font-weight: 400; | ||
8 | } | 11 | } |
9 | a { | 12 | a { |
10 | -webkit-transition: all 0.35s; | 13 | -webkit-transition: all 0.35s; |
1 | -define(['fast', 'moment'], function (Fast, Moment) { | 1 | +define(['fast', 'template', 'moment'], function (Fast, Template, Moment) { |
2 | var Backend = { | 2 | var Backend = { |
3 | api: { | 3 | api: { |
4 | sidebar: function (params) { | 4 | sidebar: function (params) { |
@@ -8,13 +8,11 @@ define(['fast', 'moment'], function (Fast, Moment) { | @@ -8,13 +8,11 @@ define(['fast', 'moment'], function (Fast, Moment) { | ||
8 | $.each(params, function (k, v) { | 8 | $.each(params, function (k, v) { |
9 | $url = Fast.api.fixurl(k); | 9 | $url = Fast.api.fixurl(k); |
10 | 10 | ||
11 | - if ($.isArray(v)) | ||
12 | - { | 11 | + if ($.isArray(v)) { |
13 | $nums = typeof v[0] !== 'undefined' ? v[0] : 0; | 12 | $nums = typeof v[0] !== 'undefined' ? v[0] : 0; |
14 | $color = typeof v[1] !== 'undefined' ? v[1] : colorArr[(!isNaN($nums) ? $nums : $nums.length) % $colorNums]; | 13 | $color = typeof v[1] !== 'undefined' ? v[1] : colorArr[(!isNaN($nums) ? $nums : $nums.length) % $colorNums]; |
15 | $class = typeof v[2] !== 'undefined' ? v[2] : 'label'; | 14 | $class = typeof v[2] !== 'undefined' ? v[2] : 'label'; |
16 | - } else | ||
17 | - { | 15 | + } else { |
18 | $nums = v; | 16 | $nums = v; |
19 | $color = colorArr[(!isNaN($nums) ? $nums : $nums.length) % $colorNums]; | 17 | $color = colorArr[(!isNaN($nums) ? $nums : $nums.length) % $colorNums]; |
20 | $class = 'label'; | 18 | $class = 'label'; |
@@ -58,7 +56,10 @@ define(['fast', 'moment'], function (Fast, Moment) { | @@ -58,7 +56,10 @@ define(['fast', 'moment'], function (Fast, Moment) { | ||
58 | var id = Math.floor(new Date().valueOf() * Math.random()); | 56 | var id = Math.floor(new Date().valueOf() * Math.random()); |
59 | icon = typeof icon !== 'undefined' ? icon : 'fa fa-circle-o'; | 57 | icon = typeof icon !== 'undefined' ? icon : 'fa fa-circle-o'; |
60 | title = typeof title !== 'undefined' ? title : ''; | 58 | title = typeof title !== 'undefined' ? title : ''; |
61 | - top.window.$("<a />").append('<i class="' + icon + '"></i> <span>' + title + '</span>').prop("href", url).attr({url: url, addtabs: id}).addClass("hide").appendTo(top.window.document.body).trigger("click"); | 59 | + top.window.$("<a />").append('<i class="' + icon + '"></i> <span>' + title + '</span>').prop("href", url).attr({ |
60 | + url: url, | ||
61 | + addtabs: id | ||
62 | + }).addClass("hide").appendTo(top.window.document.body).trigger("click"); | ||
62 | } | 63 | } |
63 | } | 64 | } |
64 | } | 65 | } |
@@ -227,6 +228,8 @@ define(['fast', 'moment'], function (Fast, Moment) { | @@ -227,6 +228,8 @@ define(['fast', 'moment'], function (Fast, Moment) { | ||
227 | } | 228 | } |
228 | }; | 229 | }; |
229 | Backend.api = $.extend(Fast.api, Backend.api); | 230 | Backend.api = $.extend(Fast.api, Backend.api); |
231 | + //将Template渲染至全局,以便于在子框架中调用 | ||
232 | + window.Template = Template; | ||
230 | //将Moment渲染至全局,以便于在子框架中调用 | 233 | //将Moment渲染至全局,以便于在子框架中调用 |
231 | window.Moment = Moment; | 234 | window.Moment = Moment; |
232 | //将Backend渲染至全局,以便于在子框架中调用 | 235 | //将Backend渲染至全局,以便于在子框架中调用 |
@@ -14,6 +14,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | @@ -14,6 +14,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | ||
14 | 14 | ||
15 | var table = $("#table"); | 15 | var table = $("#table"); |
16 | 16 | ||
17 | + table.on('load-success.bs.table', function (e, json) { | ||
18 | + if (json && typeof json.category != 'undefined' && $(".nav-category li").size() == 2) { | ||
19 | + $.each(json.category, function (i, j) { | ||
20 | + $("<li><a href='javascript:;' data-id='" + j.id + "'>" + j.name + "</a></li>").insertBefore($(".nav-category li:last")); | ||
21 | + }); | ||
22 | + } | ||
23 | + }); | ||
17 | table.on('post-body.bs.table', function (e, settings, json, xhr) { | 24 | table.on('post-body.bs.table', function (e, settings, json, xhr) { |
18 | var parenttable = table.closest('.bootstrap-table'); | 25 | var parenttable = table.closest('.bootstrap-table'); |
19 | var d = $(".fixed-table-toolbar", parenttable).find(".search input"); | 26 | var d = $(".fixed-table-toolbar", parenttable).find(".search input"); |
@@ -53,19 +60,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | @@ -53,19 +60,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | ||
53 | showColumns: false, | 60 | showColumns: false, |
54 | showToggle: false, | 61 | showToggle: false, |
55 | showExport: false, | 62 | showExport: false, |
56 | - commonSearch: false, | ||
57 | - searchFormVisible: false, | 63 | + showSearch: false, |
64 | + commonSearch: true, | ||
65 | + searchFormVisible: true, | ||
66 | + searchFormTemplate: 'searchformtpl', | ||
58 | pageSize: 12, | 67 | pageSize: 12, |
59 | pagination: false, | 68 | pagination: false, |
60 | - queryParams: function (params) { | ||
61 | - var filter = params.filter ? JSON.parse(params.filter) : {}; | ||
62 | - var op = params.op ? JSON.parse(params.op) : {}; | ||
63 | - filter.faversion = Config.fastadmin.version; | ||
64 | - op.faversion = "="; | ||
65 | - params.filter = JSON.stringify(filter); | ||
66 | - params.op = JSON.stringify(op); | ||
67 | - return params; | ||
68 | - } | ||
69 | }); | 69 | }); |
70 | 70 | ||
71 | // 为表格绑定事件 | 71 | // 为表格绑定事件 |
@@ -124,14 +124,23 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | @@ -124,14 +124,23 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | ||
124 | return false; | 124 | return false; |
125 | } | 125 | } |
126 | }); | 126 | }); |
127 | - | ||
128 | - // 切换URL | 127 | + |
128 | + // 切换 | ||
129 | $(document).on("click", ".btn-switch", function () { | 129 | $(document).on("click", ".btn-switch", function () { |
130 | $(".btn-switch").removeClass("active"); | 130 | $(".btn-switch").removeClass("active"); |
131 | $(this).addClass("active"); | 131 | $(this).addClass("active"); |
132 | + $("form.form-commonsearch input[name='type']").val($(this).data("type")); | ||
132 | table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1}); | 133 | table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1}); |
134 | + return false; | ||
133 | }); | 135 | }); |
134 | - | 136 | + $(document).on("click", ".nav-category li a", function () { |
137 | + $(".nav-category li").removeClass("active"); | ||
138 | + $(this).parent().addClass("active"); | ||
139 | + $("form.form-commonsearch input[name='category_id']").val($(this).data("id")); | ||
140 | + table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1}); | ||
141 | + return false; | ||
142 | + }); | ||
143 | + | ||
135 | // 会员信息 | 144 | // 会员信息 |
136 | $(document).on("click", ".btn-userinfo", function () { | 145 | $(document).on("click", ".btn-userinfo", function () { |
137 | var userinfo = Controller.api.userinfo.get(); | 146 | var userinfo = Controller.api.userinfo.get(); |
@@ -146,7 +155,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | @@ -146,7 +155,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | ||
146 | Fast.api.ajax({ | 155 | Fast.api.ajax({ |
147 | url: Config.fastadmin.api_url + '/user/login', | 156 | url: Config.fastadmin.api_url + '/user/login', |
148 | dataType: 'jsonp', | 157 | dataType: 'jsonp', |
149 | - data: {account: $("#inputAccount", layero).val(), password: $("#inputPassword", layero).val(), _method: 'POST'} | 158 | + data: { |
159 | + account: $("#inputAccount", layero).val(), | ||
160 | + password: $("#inputPassword", layero).val(), | ||
161 | + _method: 'POST' | ||
162 | + } | ||
150 | }, function (data, ret) { | 163 | }, function (data, ret) { |
151 | Controller.api.userinfo.set(data); | 164 | Controller.api.userinfo.set(data); |
152 | Layer.closeAll(); | 165 | Layer.closeAll(); |
@@ -199,7 +212,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | @@ -199,7 +212,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function | ||
199 | var token = userinfo ? userinfo.token : ''; | 212 | var token = userinfo ? userinfo.token : ''; |
200 | Fast.api.ajax({ | 213 | Fast.api.ajax({ |
201 | url: 'addon/install', | 214 | url: 'addon/install', |
202 | - data: {name: name, force: force ? 1 : 0, uid: uid, token: token, version: version, faversion: Config.fastadmin.version} | 215 | + data: { |
216 | + name: name, | ||
217 | + force: force ? 1 : 0, | ||
218 | + uid: uid, | ||
219 | + token: token, | ||
220 | + version: version, | ||
221 | + faversion: Config.fastadmin.version | ||
222 | + } | ||
203 | }, function (data, ret) { | 223 | }, function (data, ret) { |
204 | Layer.closeAll(); | 224 | Layer.closeAll(); |
205 | Config['addons'][data.addon.name] = ret.data.addon; | 225 | Config['addons'][data.addon.name] = ret.data.addon; |
@@ -180,10 +180,11 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi | @@ -180,10 +180,11 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi | ||
180 | }); | 180 | }); |
181 | 181 | ||
182 | //清除缓存 | 182 | //清除缓存 |
183 | - $(document).on('click', "[data-toggle='wipecache']", function () { | 183 | + $(document).on('click', "ul.wipecache li a", function () { |
184 | $.ajax({ | 184 | $.ajax({ |
185 | url: 'ajax/wipecache', | 185 | url: 'ajax/wipecache', |
186 | dataType: 'json', | 186 | dataType: 'json', |
187 | + data: {type: $(this).data("type")}, | ||
187 | cache: false, | 188 | cache: false, |
188 | success: function (ret) { | 189 | success: function (ret) { |
189 | if (ret.hasOwnProperty("code")) { | 190 | if (ret.hasOwnProperty("code")) { |
1 | /** | 1 | /** |
2 | + * FastAdmin通用搜索 | ||
3 | + * | ||
2 | * @author: pppscn <35696959@qq.com> | 4 | * @author: pppscn <35696959@qq.com> |
3 | - * @version: v0.0.1 | 5 | + * @update 2017-05-07 <https://gitee.com/pp/fastadmin> |
4 | * | 6 | * |
5 | - * @update 2017-05-07 <http://git.oschina.net/pp/fastadmin> | ||
6 | - * @update 2017-09-17 <http://git.oschina.net/karson/fastadmin> | 7 | + * @author: Karson <karsonzhang@163.com> |
8 | + * @update 2018-04-05 <https://gitee.com/karson/fastadmin> | ||
7 | */ | 9 | */ |
8 | 10 | ||
9 | !function ($) { | 11 | !function ($) { |
@@ -17,75 +19,16 @@ | @@ -17,75 +19,16 @@ | ||
17 | var vFormCommon = createFormCommon(pColumns, that); | 19 | var vFormCommon = createFormCommon(pColumns, that); |
18 | 20 | ||
19 | var vModal = sprintf("<div class=\"commonsearch-table %s\">", that.options.searchFormVisible ? "" : "hidden"); | 21 | var vModal = sprintf("<div class=\"commonsearch-table %s\">", that.options.searchFormVisible ? "" : "hidden"); |
20 | - vModal += vFormCommon.join(''); | 22 | + vModal += vFormCommon; |
21 | vModal += "</div>"; | 23 | vModal += "</div>"; |
22 | that.$container.prepend($(vModal)); | 24 | that.$container.prepend($(vModal)); |
23 | that.$commonsearch = $(".commonsearch-table", that.$container); | 25 | that.$commonsearch = $(".commonsearch-table", that.$container); |
24 | var form = $("form.form-commonsearch", that.$commonsearch); | 26 | var form = $("form.form-commonsearch", that.$commonsearch); |
25 | 27 | ||
26 | - //绑定日期时间元素事件 | ||
27 | - if ($(".datetimepicker", form).size() > 0) { | ||
28 | - | ||
29 | - require(['bootstrap-datetimepicker'], function () { | ||
30 | - $('.datetimepicker', form).parent().css('position', 'relative'); | ||
31 | - $('.datetimepicker', form).datetimepicker({ | ||
32 | - //format: 'YYYY-MM-DD', | ||
33 | - icons: { | ||
34 | - time: 'fa fa-clock-o', | ||
35 | - date: 'fa fa-calendar', | ||
36 | - up: 'fa fa-chevron-up', | ||
37 | - down: 'fa fa-chevron-down', | ||
38 | - previous: 'fa fa-chevron-left', | ||
39 | - next: 'fa fa-chevron-right', | ||
40 | - today: 'fa fa-history', | ||
41 | - clear: 'fa fa-trash', | ||
42 | - close: 'fa fa-remove' | ||
43 | - }, | ||
44 | - showTodayButton: true, | ||
45 | - showClose: true | ||
46 | - }); | ||
47 | - }); | ||
48 | - } | ||
49 | - if ($(".datetimerange", form).size() > 0) { | ||
50 | - var ranges = {}; | ||
51 | - ranges[__('Today')] = [Moment().startOf('day'), Moment().endOf('day')]; | ||
52 | - ranges[__('Yesterday')] = [Moment().subtract(1, 'days').startOf('day'), Moment().subtract(1, 'days').endOf('day')]; | ||
53 | - ranges[__('Last 7 Days')] = [Moment().subtract(6, 'days').startOf('day'), Moment().endOf('day')]; | ||
54 | - ranges[__('Last 30 Days')] = [Moment().subtract(29, 'days').startOf('day'), Moment().endOf('day')]; | ||
55 | - ranges[__('This Month')] = [Moment().startOf('month'), Moment().endOf('month')]; | ||
56 | - ranges[__('Last Month')] = [Moment().subtract(1, 'month').startOf('month'), Moment().subtract(1, 'month').endOf('month')]; | ||
57 | - var options = { | ||
58 | - timePicker: false, | ||
59 | - autoUpdateInput: false, | ||
60 | - timePickerSeconds: true, | ||
61 | - timePicker24Hour: true, | ||
62 | - autoApply: true, | ||
63 | - locale: { | ||
64 | - format: 'YYYY-MM-DD HH:mm:ss', | ||
65 | - customRangeLabel: __("Custom Range"), | ||
66 | - applyLabel: __("Apply"), | ||
67 | - cancelLabel: __("Clear"), | ||
68 | - }, | ||
69 | - ranges: ranges, | ||
70 | - }; | ||
71 | - var callback = function (start, end) { | ||
72 | - $(this.element).val(start.format(options.locale.format) + " - " + end.format(options.locale.format)); | ||
73 | - }; | ||
74 | - var column, index; | ||
75 | - require(['bootstrap-daterangepicker'], function () { | ||
76 | - $(".datetimerange", form).each(function () { | ||
77 | - $(this).on('apply.daterangepicker', function (ev, picker) { | ||
78 | - callback.call(picker, picker.startDate, picker.endDate); | ||
79 | - }); | ||
80 | - $(this).on('cancel.daterangepicker', function (ev, picker) { | ||
81 | - $(this).val(''); | ||
82 | - }); | ||
83 | - index = $(this).data("index"); | ||
84 | - column = pColumns[index]; | ||
85 | - $(this).daterangepicker($.extend({}, options, column.options || {}), callback); | ||
86 | - }); | ||
87 | - }); | ||
88 | - } | 28 | + require(['form'], function (Form) { |
29 | + Form.api.bindevent(form); | ||
30 | + form.validator("destroy"); | ||
31 | + }); | ||
89 | 32 | ||
90 | // 表单提交 | 33 | // 表单提交 |
91 | form.on("submit", function (event) { | 34 | form.on("submit", function (event) { |
@@ -103,9 +46,12 @@ | @@ -103,9 +46,12 @@ | ||
103 | }; | 46 | }; |
104 | 47 | ||
105 | var createFormCommon = function (pColumns, that) { | 48 | var createFormCommon = function (pColumns, that) { |
49 | + // 如果有使用模板则直接返回模板的内容 | ||
50 | + if (that.options.searchFormTemplate) { | ||
51 | + return Template(that.options.searchFormTemplate, {columns: pColumns, table: that}); | ||
52 | + } | ||
106 | var htmlForm = []; | 53 | var htmlForm = []; |
107 | - 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']; | ||
108 | - htmlForm.push(sprintf('<form class="form-horizontal form-commonsearch" action="%s" >', that.options.actionForm)); | 54 | + htmlForm.push(sprintf('<form class="form-horizontal form-commonsearch" novalidate method="post" action="%s" >', that.options.actionForm)); |
109 | htmlForm.push('<fieldset>'); | 55 | htmlForm.push('<fieldset>'); |
110 | if (that.options.titleForm.length > 0) | 56 | if (that.options.titleForm.length > 0) |
111 | htmlForm.push(sprintf("<legend>%s</legend>", that.options.titleForm)); | 57 | htmlForm.push(sprintf("<legend>%s</legend>", that.options.titleForm)); |
@@ -114,24 +60,28 @@ | @@ -114,24 +60,28 @@ | ||
114 | var vObjCol = pColumns[i]; | 60 | var vObjCol = pColumns[i]; |
115 | if (!vObjCol.checkbox && vObjCol.field !== 'operate' && vObjCol.searchable && vObjCol.operate !== false) { | 61 | if (!vObjCol.checkbox && vObjCol.field !== 'operate' && vObjCol.searchable && vObjCol.operate !== false) { |
116 | var query = Backend.api.query(vObjCol.field); | 62 | var query = Backend.api.query(vObjCol.field); |
117 | - query = query ? query : ''; | ||
118 | - vObjCol.defaultValue = that.options.renderDefault && query != '' ? query : (typeof vObjCol.defaultValue === 'undefined' ? '' : vObjCol.defaultValue); | 63 | + var operate = Backend.api.query(vObjCol.field + "-operate"); |
64 | + | ||
65 | + vObjCol.defaultValue = that.options.renderDefault && query ? query : (typeof vObjCol.defaultValue === 'undefined' ? '' : vObjCol.defaultValue); | ||
66 | + vObjCol.operate = that.options.renderDefault && operate ? operate : (typeof vObjCol.operate === 'undefined' ? '=' : vObjCol.operate); | ||
119 | ColumnsForSearch.push(vObjCol); | 67 | ColumnsForSearch.push(vObjCol); |
120 | 68 | ||
121 | htmlForm.push('<div class="form-group col-xs-12 col-sm-6 col-md-4 col-lg-3">'); | 69 | htmlForm.push('<div class="form-group col-xs-12 col-sm-6 col-md-4 col-lg-3">'); |
122 | htmlForm.push(sprintf('<label for="%s" class="control-label col-xs-4">%s</label>', vObjCol.field, vObjCol.title)); | 70 | htmlForm.push(sprintf('<label for="%s" class="control-label col-xs-4">%s</label>', vObjCol.field, vObjCol.title)); |
123 | htmlForm.push('<div class="col-xs-8">'); | 71 | htmlForm.push('<div class="col-xs-8">'); |
124 | 72 | ||
125 | - vObjCol.operate = (typeof vObjCol.operate === 'undefined' || $.inArray(vObjCol.operate.toUpperCase(), opList) === -1) ? '=' : vObjCol.operate.toUpperCase(); | ||
126 | - htmlForm.push(sprintf('<input type="hidden" class="form-control operate" name="field-%s" data-name="%s" value="%s" readonly>', vObjCol.field, vObjCol.field, vObjCol.operate)); | 73 | + vObjCol.operate = vObjCol.operate ? vObjCol.operate.toUpperCase() : '='; |
74 | + htmlForm.push(sprintf('<input type="hidden" class="form-control operate" name="%s-operate" data-name="%s" value="%s" readonly>', vObjCol.field, vObjCol.field, vObjCol.operate)); | ||
127 | 75 | ||
76 | + var addClass = typeof vObjCol.addClass === 'undefined' ? (typeof vObjCol.addclass === 'undefined' ? 'form-control' : 'form-control ' + vObjCol.addclass) : 'form-control ' + vObjCol.addClass; | ||
77 | + var extend = typeof vObjCol.extend === 'undefined' ? '' : vObjCol.extend; | ||
128 | var style = typeof vObjCol.style === 'undefined' ? '' : sprintf('style="%s"', vObjCol.style); | 78 | var style = typeof vObjCol.style === 'undefined' ? '' : sprintf('style="%s"', vObjCol.style); |
79 | + extend = typeof vObjCol.data !== 'undefined' && extend == '' ? vObjCol.data : extend; | ||
129 | if (vObjCol.searchList) { | 80 | if (vObjCol.searchList) { |
130 | if (typeof vObjCol.searchList === 'object' && typeof vObjCol.searchList.then === 'function') { | 81 | if (typeof vObjCol.searchList === 'object' && typeof vObjCol.searchList.then === 'function') { |
131 | - htmlForm.push(sprintf('<select class="form-control" name="%s" %s>%s</select>', vObjCol.field, style, sprintf('<option value="">%s</option>', that.options.formatCommonChoose()))); | 82 | + htmlForm.push(sprintf('<select class="%s" name="%s" %s %s>%s</select>', addClass, vObjCol.field, style, extend, sprintf('<option value="">%s</option>', that.options.formatCommonChoose()))); |
132 | (function (vObjCol, that) { | 83 | (function (vObjCol, that) { |
133 | $.when(vObjCol.searchList).done(function (ret) { | 84 | $.when(vObjCol.searchList).done(function (ret) { |
134 | - | ||
135 | var isArray = false; | 85 | var isArray = false; |
136 | if (ret.data && ret.data.searchlist && $.isArray(ret.data.searchlist)) { | 86 | if (ret.data && ret.data.searchlist && $.isArray(ret.data.searchlist)) { |
137 | var resultlist = {}; | 87 | var resultlist = {}; |
@@ -160,23 +110,21 @@ | @@ -160,23 +110,21 @@ | ||
160 | var isSelect = (isArray ? value : key) == vObjCol.defaultValue ? 'selected' : ''; | 110 | var isSelect = (isArray ? value : key) == vObjCol.defaultValue ? 'selected' : ''; |
161 | searchList.push(sprintf("<option value='" + (isArray ? value : key) + "' %s>" + value + "</option>", isSelect)); | 111 | searchList.push(sprintf("<option value='" + (isArray ? value : key) + "' %s>" + value + "</option>", isSelect)); |
162 | }); | 112 | }); |
163 | - htmlForm.push(sprintf('<select class="form-control" name="%s" %s>%s</select>', vObjCol.field, style, searchList.join(''))); | 113 | + htmlForm.push(sprintf('<select class="%s" name="%s" %s %s>%s</select>', addClass, vObjCol.field, style, extend, searchList.join(''))); |
164 | } | 114 | } |
165 | } else { | 115 | } else { |
166 | var placeholder = typeof vObjCol.placeholder === 'undefined' ? vObjCol.title : vObjCol.placeholder; | 116 | var placeholder = typeof vObjCol.placeholder === 'undefined' ? vObjCol.title : vObjCol.placeholder; |
167 | var type = typeof vObjCol.type === 'undefined' ? 'text' : vObjCol.type; | 117 | var type = typeof vObjCol.type === 'undefined' ? 'text' : vObjCol.type; |
168 | - var addclass = typeof vObjCol.addclass === 'undefined' ? 'form-control' : 'form-control ' + vObjCol.addclass; | ||
169 | - var data = typeof vObjCol.data === 'undefined' ? '' : vObjCol.data; | ||
170 | var defaultValue = typeof vObjCol.defaultValue === 'undefined' ? '' : vObjCol.defaultValue; | 118 | var defaultValue = typeof vObjCol.defaultValue === 'undefined' ? '' : vObjCol.defaultValue; |
171 | if (/BETWEEN$/.test(vObjCol.operate)) { | 119 | if (/BETWEEN$/.test(vObjCol.operate)) { |
172 | var defaultValueArr = defaultValue.toString().match(/\|/) ? defaultValue.split('|') : ['', '']; | 120 | var defaultValueArr = defaultValue.toString().match(/\|/) ? defaultValue.split('|') : ['', '']; |
173 | var placeholderArr = placeholder.toString().match(/\|/) ? placeholder.split('|') : [placeholder, placeholder]; | 121 | var placeholderArr = placeholder.toString().match(/\|/) ? placeholder.split('|') : [placeholder, placeholder]; |
174 | htmlForm.push('<div class="row row-between">'); | 122 | htmlForm.push('<div class="row row-between">'); |
175 | - htmlForm.push(sprintf('<div class="col-xs-6 11"><input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s></div>', type, addclass, vObjCol.field, defaultValueArr[0], placeholderArr[0], vObjCol.field, i, style, data)); | ||
176 | - htmlForm.push(sprintf('<div class="col-xs-6 22"><input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s></div>', type, addclass, vObjCol.field, defaultValueArr[1], placeholderArr[1], vObjCol.field, i, style, data)); | 123 | + htmlForm.push(sprintf('<div class="col-xs-6"><input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s></div>', type, addClass, vObjCol.field, defaultValueArr[0], placeholderArr[0], vObjCol.field, i, style, extend)); |
124 | + htmlForm.push(sprintf('<div class="col-xs-6"><input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s></div>', type, addClass, vObjCol.field, defaultValueArr[1], placeholderArr[1], vObjCol.field, i, style, extend)); | ||
177 | htmlForm.push('</div>'); | 125 | htmlForm.push('</div>'); |
178 | } else { | 126 | } else { |
179 | - htmlForm.push(sprintf('<input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s>', type, addclass, vObjCol.field, defaultValue, placeholder, vObjCol.field, i, style, data)); | 127 | + htmlForm.push(sprintf('<input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s>', type, addClass, vObjCol.field, defaultValue, placeholder, vObjCol.field, i, style, extend)); |
180 | } | 128 | } |
181 | } | 129 | } |
182 | 130 | ||
@@ -191,7 +139,7 @@ | @@ -191,7 +139,7 @@ | ||
191 | htmlForm.push('</fieldset>'); | 139 | htmlForm.push('</fieldset>'); |
192 | htmlForm.push('</form>'); | 140 | htmlForm.push('</form>'); |
193 | 141 | ||
194 | - return htmlForm; | 142 | + return htmlForm.join(''); |
195 | }; | 143 | }; |
196 | 144 | ||
197 | var createFormBtn = function (that) { | 145 | var createFormBtn = function (that) { |
@@ -199,7 +147,7 @@ | @@ -199,7 +147,7 @@ | ||
199 | var searchSubmit = that.options.formatCommonSubmitButton(); | 147 | var searchSubmit = that.options.formatCommonSubmitButton(); |
200 | var searchReset = that.options.formatCommonResetButton(); | 148 | var searchReset = that.options.formatCommonResetButton(); |
201 | htmlBtn.push('<div class="col-sm-8 col-xs-offset-4">'); | 149 | htmlBtn.push('<div class="col-sm-8 col-xs-offset-4">'); |
202 | - htmlBtn.push(sprintf('<button type="submit" class="btn btn-success" >%s</button> ', searchSubmit)); | 150 | + htmlBtn.push(sprintf('<button type="submit" class="btn btn-success" formnovalidate>%s</button> ', searchSubmit)); |
203 | htmlBtn.push(sprintf('<button type="reset" class="btn btn-default" >%s</button> ', searchReset)); | 151 | htmlBtn.push(sprintf('<button type="reset" class="btn btn-default" >%s</button> ', searchReset)); |
204 | htmlBtn.push('</div>'); | 152 | htmlBtn.push('</div>'); |
205 | return htmlBtn; | 153 | return htmlBtn; |
@@ -219,16 +167,17 @@ | @@ -219,16 +167,17 @@ | ||
219 | var op = {}; | 167 | var op = {}; |
220 | var filter = {}; | 168 | var filter = {}; |
221 | var value = ''; | 169 | var value = ''; |
222 | - $("form.form-commonsearch input.operate", that.$commonsearch).each(function (i) { | 170 | + $("form.form-commonsearch .operate", that.$commonsearch).each(function (i) { |
223 | var name = $(this).data("name"); | 171 | var name = $(this).data("name"); |
224 | - var sym = $(this).val().toUpperCase(); | 172 | + var sym = $(this).is("select") ? $("option:selected", this).val() : $(this).val().toUpperCase(); |
225 | var obj = $("[name='" + name + "']", that.$commonsearch); | 173 | var obj = $("[name='" + name + "']", that.$commonsearch); |
226 | if (obj.size() == 0) | 174 | if (obj.size() == 0) |
227 | return true; | 175 | return true; |
228 | var vObjCol = ColumnsForSearch[i]; | 176 | var vObjCol = ColumnsForSearch[i]; |
229 | if (obj.size() > 1) { | 177 | if (obj.size() > 1) { |
230 | if (/BETWEEN$/.test(sym)) { | 178 | if (/BETWEEN$/.test(sym)) { |
231 | - var value_begin = $.trim($("[name='" + name + "']:first", that.$commonsearch).val()), value_end = $.trim($("[name='" + name + "']:last", that.$commonsearch).val()); | 179 | + var value_begin = $.trim($("[name='" + name + "']:first", that.$commonsearch).val()), |
180 | + value_end = $.trim($("[name='" + name + "']:last", that.$commonsearch).val()); | ||
232 | if (value_begin.length || value_end.length) { | 181 | if (value_begin.length || value_end.length) { |
233 | if (typeof vObjCol.process === 'function') { | 182 | if (typeof vObjCol.process === 'function') { |
234 | value_begin = vObjCol.process(value_begin, 'begin'); | 183 | value_begin = vObjCol.process(value_begin, 'begin'); |
@@ -244,11 +193,12 @@ | @@ -244,11 +193,12 @@ | ||
244 | } | 193 | } |
245 | } else { | 194 | } else { |
246 | value = $("[name='" + name + "']:checked", that.$commonsearch).val(); | 195 | value = $("[name='" + name + "']:checked", that.$commonsearch).val(); |
196 | + value = (vObjCol && typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : obj.val(); | ||
247 | } | 197 | } |
248 | } else { | 198 | } else { |
249 | - value = (vObjCol && typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : (sym == 'LIKE %...%' ? obj.val().replace(/\*/g, '%') : obj.val()); | 199 | + value = (vObjCol && typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : obj.val(); |
250 | } | 200 | } |
251 | - if (removeempty && value == '' && sym.indexOf("NULL") == -1) { | 201 | + if (removeempty && (value == '' || value == null || ($.isArray(value) && value.length == 0)) && !sym.match(/null/i)) { |
252 | return true; | 202 | return true; |
253 | } | 203 | } |
254 | 204 | ||
@@ -267,7 +217,7 @@ | @@ -267,7 +217,7 @@ | ||
267 | //移除empty的值 | 217 | //移除empty的值 |
268 | if (removeempty) { | 218 | if (removeempty) { |
269 | $.each(params.filter, function (i, j) { | 219 | $.each(params.filter, function (i, j) { |
270 | - if (j === '') { | 220 | + if ((j == '' || j == null || ($.isArray(j) && j.length == 0)) && !params.op[i].match(/null/i)) { |
271 | delete params.filter[i]; | 221 | delete params.filter[i]; |
272 | delete params.op[i]; | 222 | delete params.op[i]; |
273 | } | 223 | } |
@@ -282,8 +232,10 @@ | @@ -282,8 +232,10 @@ | ||
282 | commonSearch: false, | 232 | commonSearch: false, |
283 | titleForm: "Common search", | 233 | titleForm: "Common search", |
284 | actionForm: "", | 234 | actionForm: "", |
235 | + searchFormTemplate: "", | ||
285 | searchFormVisible: true, | 236 | searchFormVisible: true, |
286 | searchClass: 'searchit', | 237 | searchClass: 'searchit', |
238 | + showSearch: true, | ||
287 | renderDefault: true, | 239 | renderDefault: true, |
288 | onCommonSearch: function (field, text) { | 240 | onCommonSearch: function (field, text) { |
289 | return false; | 241 | return false; |
@@ -322,10 +274,10 @@ | @@ -322,10 +274,10 @@ | ||
322 | $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales); | 274 | $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales); |
323 | 275 | ||
324 | var BootstrapTable = $.fn.bootstrapTable.Constructor, | 276 | var BootstrapTable = $.fn.bootstrapTable.Constructor, |
325 | - _initHeader = BootstrapTable.prototype.initHeader, | ||
326 | - _initToolbar = BootstrapTable.prototype.initToolbar, | ||
327 | - _load = BootstrapTable.prototype.load, | ||
328 | - _initSearch = BootstrapTable.prototype.initSearch; | 277 | + _initHeader = BootstrapTable.prototype.initHeader, |
278 | + _initToolbar = BootstrapTable.prototype.initToolbar, | ||
279 | + _load = BootstrapTable.prototype.load, | ||
280 | + _initSearch = BootstrapTable.prototype.initSearch; | ||
329 | 281 | ||
330 | BootstrapTable.prototype.initHeader = function () { | 282 | BootstrapTable.prototype.initHeader = function () { |
331 | _initHeader.apply(this, Array.prototype.slice.apply(arguments)); | 283 | _initHeader.apply(this, Array.prototype.slice.apply(arguments)); |
@@ -344,12 +296,13 @@ | @@ -344,12 +296,13 @@ | ||
344 | } | 296 | } |
345 | 297 | ||
346 | var that = this, | 298 | var that = this, |
347 | - html = []; | ||
348 | - html.push(sprintf('<div class="columns-%s pull-%s" style="margin-top:10px;margin-bottom:10px;">', this.options.buttonsAlign, this.options.buttonsAlign)); | ||
349 | - html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="commonSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatCommonSearch())); | ||
350 | - html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.commonSearchIcon)) | ||
351 | - html.push('</button></div>'); | ||
352 | - | 299 | + html = []; |
300 | + if(that.options.showSearch){ | ||
301 | + html.push(sprintf('<div class="columns-%s pull-%s" style="margin-top:10px;margin-bottom:10px;">', this.options.buttonsAlign, this.options.buttonsAlign)); | ||
302 | + html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="commonSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatCommonSearch())); | ||
303 | + html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.commonSearchIcon)) | ||
304 | + html.push('</button></div>'); | ||
305 | + } | ||
353 | if (that.$toolbar.find(".pull-right").size() > 0) { | 306 | if (that.$toolbar.find(".pull-right").size() > 0) { |
354 | $(html.join('')).insertBefore(that.$toolbar.find(".pull-right:first")); | 307 | $(html.join('')).insertBefore(that.$toolbar.find(".pull-right:first")); |
355 | } else { | 308 | } else { |
@@ -359,7 +312,7 @@ | @@ -359,7 +312,7 @@ | ||
359 | initCommonSearch(that.columns, that); | 312 | initCommonSearch(that.columns, that); |
360 | 313 | ||
361 | that.$toolbar.find('button[name="commonSearch"]') | 314 | that.$toolbar.find('button[name="commonSearch"]') |
362 | - .off('click').on('click', function () { | 315 | + .off('click').on('click', function () { |
363 | that.$commonsearch.toggleClass("hidden"); | 316 | that.$commonsearch.toggleClass("hidden"); |
364 | return; | 317 | return; |
365 | }); | 318 | }); |
@@ -374,7 +327,7 @@ | @@ -374,7 +327,7 @@ | ||
374 | var queryParams = that.options.queryParams; | 327 | var queryParams = that.options.queryParams; |
375 | //匹配默认搜索值 | 328 | //匹配默认搜索值 |
376 | this.options.queryParams = function (params) { | 329 | this.options.queryParams = function (params) { |
377 | - return queryParams(getQueryParams(params, getSearchQuery(this, true))); | 330 | + return queryParams(getQueryParams(params, getSearchQuery(that, true))); |
378 | }; | 331 | }; |
379 | this.trigger('post-common-search', that); | 332 | this.trigger('post-common-search', that); |
380 | 333 | ||
@@ -409,8 +362,8 @@ | @@ -409,8 +362,8 @@ | ||
409 | var fval = fp[key].toLowerCase(); | 362 | var fval = fp[key].toLowerCase(); |
410 | var value = item[key]; | 363 | var value = item[key]; |
411 | value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, | 364 | value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, |
412 | - that.header.formatters[$.inArray(key, that.header.fields)], | ||
413 | - [value, item, i], value); | 365 | + that.header.formatters[$.inArray(key, that.header.fields)], |
366 | + [value, item, i], value); | ||
414 | 367 | ||
415 | if (!($.inArray(key, that.header.fields) !== -1 && | 368 | if (!($.inArray(key, that.header.fields) !== -1 && |
416 | (typeof value === 'string' || typeof value === 'number') && | 369 | (typeof value === 'string' || typeof value === 'number') && |
1 | -define(['fast'], function (Fast) { | 1 | +define(['fast', 'template'], function (Fast, Template) { |
2 | var Frontend = { | 2 | var Frontend = { |
3 | api: Fast.api, | 3 | api: Fast.api, |
4 | init: function () { | 4 | init: function () { |
@@ -53,6 +53,8 @@ define(['fast'], function (Fast) { | @@ -53,6 +53,8 @@ define(['fast'], function (Fast) { | ||
53 | } | 53 | } |
54 | }; | 54 | }; |
55 | Frontend.api = $.extend(Fast.api, Frontend.api); | 55 | Frontend.api = $.extend(Fast.api, Frontend.api); |
56 | + //将Template渲染至全局,以便于在子框架中调用 | ||
57 | + window.Template = Template; | ||
56 | //将Frontend渲染至全局,以便于在子框架中调用 | 58 | //将Frontend渲染至全局,以便于在子框架中调用 |
57 | window.Frontend = Frontend; | 59 | window.Frontend = Frontend; |
58 | 60 |
此 diff 太大无法显示。
1 | define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, Upload, Validator) { | 1 | define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, Upload, Validator) { |
2 | var Form = { | 2 | var Form = { |
3 | config: { | 3 | config: { |
4 | - fieldlisttpl: '<dd class="form-inline"><input type="text" name="<%=name%>[<%=index%>][key]" class="form-control" value="<%=row.key%>" size="10" /> <input type="text" name="<%=name%>[<%=index%>][value]" class="form-control" value="<%=row.value%>" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>' | 4 | + fieldlisttpl: '<dd class="form-inline"><input type="text" name="<%=name%>[<%=index%>][key]" class="form-control" value="<%=row.key%>" size="10" /> <input type="text" name="<%=name%>[<%=index%>][value]" class="form-control" value="<%=row.value%>" size="30" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>' |
5 | }, | 5 | }, |
6 | events: { | 6 | events: { |
7 | validator: function (form, success, error, submit) { | 7 | validator: function (form, success, error, submit) { |
@@ -26,6 +26,10 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | @@ -26,6 +26,10 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | ||
26 | } | 26 | } |
27 | }, | 27 | }, |
28 | target: function (input) { | 28 | target: function (input) { |
29 | + var target = $(input).data("target"); | ||
30 | + if (target && $(target).size() > 0) { | ||
31 | + return $(target); | ||
32 | + } | ||
29 | var $formitem = $(input).closest('.form-group'), | 33 | var $formitem = $(input).closest('.form-group'), |
30 | $msgbox = $formitem.find('span.msg-box'); | 34 | $msgbox = $formitem.find('span.msg-box'); |
31 | if (!$msgbox.length) { | 35 | if (!$msgbox.length) { |
@@ -282,7 +286,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | @@ -282,7 +286,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | ||
282 | refresh($(this).closest("dl").data("name")); | 286 | refresh($(this).closest("dl").data("name")); |
283 | }); | 287 | }); |
284 | //追加控制 | 288 | //追加控制 |
285 | - $(".fieldlist", form).on("click", ".btn-append", function (e, row) { | 289 | + $(".fieldlist", form).on("click", ".btn-append,.append", function (e, row) { |
286 | var container = $(this).closest("dl"); | 290 | var container = $(this).closest("dl"); |
287 | var index = container.data("index"); | 291 | var index = container.data("index"); |
288 | var name = container.data("name"); | 292 | var name = container.data("name"); |
@@ -305,7 +309,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | @@ -305,7 +309,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | ||
305 | //拖拽排序 | 309 | //拖拽排序 |
306 | $("dl.fieldlist", form).dragsort({ | 310 | $("dl.fieldlist", form).dragsort({ |
307 | itemSelector: 'dd', | 311 | itemSelector: 'dd', |
308 | - dragSelector: ".btn-fdragsort", | 312 | + dragSelector: ".btn-dragsort", |
309 | dragEnd: function () { | 313 | dragEnd: function () { |
310 | refresh($(this).closest("dl").data("name")); | 314 | refresh($(this).closest("dl").data("name")); |
311 | }, | 315 | }, |
@@ -319,8 +323,13 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | @@ -319,8 +323,13 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U | ||
319 | return true; | 323 | return true; |
320 | } | 324 | } |
321 | var template = $(this).data("template"); | 325 | var template = $(this).data("template"); |
322 | - $.each(JSON.parse(textarea.val()), function (i, j) { | ||
323 | - $(".btn-append", container).trigger('click', template ? j : { | 326 | + var json = {}; |
327 | + try { | ||
328 | + json = JSON.parse(textarea.val()); | ||
329 | + } catch (e) { | ||
330 | + } | ||
331 | + $.each(json, function (i, j) { | ||
332 | + $(".btn-append,.append", container).trigger('click', template ? j : { | ||
324 | key: i, | 333 | key: i, |
325 | value: j | 334 | value: j |
326 | }); | 335 | }); |
@@ -973,7 +973,9 @@ define('fast',['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, u | @@ -973,7 +973,9 @@ define('fast',['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, u | ||
973 | return Fast; | 973 | return Fast; |
974 | }); | 974 | }); |
975 | 975 | ||
976 | -define('frontend',['fast'], function (Fast) { | 976 | +/*!art-template - Template Engine | http://aui.github.com/artTemplate/*/ |
977 | +!function(){function a(a){return a.replace(t,"").replace(u,",").replace(v,"").replace(w,"").replace(x,"").split(y)}function b(a){return"'"+a.replace(/('|\\)/g,"\\$1").replace(/\r/g,"\\r").replace(/\n/g,"\\n")+"'"}function c(c,d){function e(a){return m+=a.split(/\n/).length-1,k&&(a=a.replace(/\s+/g," ").replace(/<!--[\w\W]*?-->/g,"")),a&&(a=s[1]+b(a)+s[2]+"\n"),a}function f(b){var c=m;if(j?b=j(b,d):g&&(b=b.replace(/\n/g,function(){return m++,"$line="+m+";"})),0===b.indexOf("=")){var e=l&&!/^=[=#]/.test(b);if(b=b.replace(/^=[=#]?|[\s;]*$/g,""),e){var f=b.replace(/\s*\([^\)]+\)/,"");n[f]||/^(include|print)$/.test(f)||(b="$escape("+b+")")}else b="$string("+b+")";b=s[1]+b+s[2]}return g&&(b="$line="+c+";"+b),r(a(b),function(a){if(a&&!p[a]){var b;b="print"===a?u:"include"===a?v:n[a]?"$utils."+a:o[a]?"$helpers."+a:"$data."+a,w+=a+"="+b+",",p[a]=!0}}),b+"\n"}var g=d.debug,h=d.openTag,i=d.closeTag,j=d.parser,k=d.compress,l=d.escape,m=1,p={$data:1,$filename:1,$utils:1,$helpers:1,$out:1,$line:1},q="".trim,s=q?["$out='';","$out+=",";","$out"]:["$out=[];","$out.push(",");","$out.join('')"],t=q?"$out+=text;return $out;":"$out.push(text);",u="function(){var text=''.concat.apply('',arguments);"+t+"}",v="function(filename,data){data=data||$data;var text=$utils.$include(filename,data,$filename);"+t+"}",w="'use strict';var $utils=this,$helpers=$utils.$helpers,"+(g?"$line=0,":""),x=s[0],y="return new String("+s[3]+");";r(c.split(h),function(a){a=a.split(i);var b=a[0],c=a[1];1===a.length?x+=e(b):(x+=f(b),c&&(x+=e(c)))});var z=w+x+y;g&&(z="try{"+z+"}catch(e){throw {filename:$filename,name:'Render Error',message:e.message,line:$line,source:"+b(c)+".split(/\\n/)[$line-1].replace(/^\\s+/,'')};}");try{var A=new Function("$data","$filename",z);return A.prototype=n,A}catch(a){throw a.temp="function anonymous($data,$filename) {"+z+"}",a}}var d=function(a,b){return"string"==typeof b?q(b,{filename:a}):g(a,b)};d.version="3.0.0",d.config=function(a,b){e[a]=b};var e=d.defaults={openTag:"<%",closeTag:"%>",escape:!0,cache:!0,compress:!1,parser:null},f=d.cache={};d.render=function(a,b){return q(a)(b)};var g=d.renderFile=function(a,b){var c=d.get(a)||p({filename:a,name:"Render Error",message:"Template not found"});return b?c(b):c};d.get=function(a){var b;if(f[a])b=f[a];else if("object"==typeof document){var c=document.getElementById(a);if(c){var d=(c.value||c.innerHTML).replace(/^\s*|\s*$/g,"");b=q(d,{filename:a})}}return b};var h=function(a,b){return"string"!=typeof a&&(b=typeof a,"number"===b?a+="":a="function"===b?h(a.call(a)):""),a},i={"<":"<",">":">",'"':""","'":"'","&":"&"},j=function(a){return i[a]},k=function(a){return h(a).replace(/&(?![\w#]+;)|[<>"']/g,j)},l=Array.isArray||function(a){return"[object Array]"==={}.toString.call(a)},m=function(a,b){var c,d;if(l(a))for(c=0,d=a.length;c<d;c++)b.call(a,a[c],c,a);else for(c in a)b.call(a,a[c],c)},n=d.utils={$helpers:{},$include:g,$string:h,$escape:k,$each:m};d.helper=function(a,b){o[a]=b};var o=d.helpers=n.$helpers;d.onerror=function(a){var b="Template Error\n\n";for(var c in a)b+="<"+c+">\n"+a[c]+"\n\n";"object"==typeof console&&console.error(b)};var p=function(a){return d.onerror(a),function(){return"{Template Error}"}},q=d.compile=function(a,b){function d(c){try{return new i(c,h)+""}catch(d){return b.debug?p(d)():(b.debug=!0,q(a,b)(c))}}b=b||{};for(var g in e)void 0===b[g]&&(b[g]=e[g]);var h=b.filename;try{var i=c(a,b)}catch(a){return a.filename=h||"anonymous",a.name="Syntax Error",p(a)}return d.prototype=i.prototype,d.toString=function(){return i.toString()},h&&b.cache&&(f[h]=d),d},r=n.$each,s="break,case,catch,continue,debugger,default,delete,do,else,false,finally,for,function,if,in,instanceof,new,null,return,switch,this,throw,true,try,typeof,var,void,while,with,abstract,boolean,byte,char,class,const,double,enum,export,extends,final,float,goto,implements,import,int,interface,long,native,package,private,protected,public,short,static,super,synchronized,throws,transient,volatile,arguments,let,yield,undefined",t=/\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|\s*\.\s*[$\w\.]+/g,u=/[^\w$]+/g,v=new RegExp(["\\b"+s.replace(/,/g,"\\b|\\b")+"\\b"].join("|"),"g"),w=/^\d[^,]*|,\d[^,]*/g,x=/^,+|,+$/g,y=/^$|,+/;"object"==typeof exports&&"undefined"!=typeof module?module.exports=d:"function"==typeof define?define('template',[],function(){return d}):this.template=d}(); | ||
978 | +define('frontend',['fast', 'template'], function (Fast, Template) { | ||
977 | var Frontend = { | 979 | var Frontend = { |
978 | api: Fast.api, | 980 | api: Fast.api, |
979 | init: function () { | 981 | init: function () { |
@@ -1028,6 +1030,8 @@ define('frontend',['fast'], function (Fast) { | @@ -1028,6 +1030,8 @@ define('frontend',['fast'], function (Fast) { | ||
1028 | } | 1030 | } |
1029 | }; | 1031 | }; |
1030 | Frontend.api = $.extend(Fast.api, Frontend.api); | 1032 | Frontend.api = $.extend(Fast.api, Frontend.api); |
1033 | + //将Template渲染至全局,以便于在子框架中调用 | ||
1034 | + window.Template = Template; | ||
1031 | //将Frontend渲染至全局,以便于在子框架中调用 | 1035 | //将Frontend渲染至全局,以便于在子框架中调用 |
1032 | window.Frontend = Frontend; | 1036 | window.Frontend = Frontend; |
1033 | 1037 |
-
请 注册 或 登录 后发表评论