正在显示
35 个修改的文件
包含
2121 行增加
和
5 行删除
addons/command/.addonrc
0 → 100644
1 | +{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"10789","licensekey":"ogGuqfEhWU5smPv7 ZCMeDKwDoQx8JuH\/Lrj4FA==","domains":[],"licensecodes":[],"validations":[],"menus":["command","command\/index","command\/add","command\/detail","command\/execute","command\/del","command\/multi"]} |
addons/command/Command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\command; | ||
4 | + | ||
5 | +use app\common\library\Menu; | ||
6 | +use think\Addons; | ||
7 | + | ||
8 | +/** | ||
9 | + * 在线命令插件 | ||
10 | + */ | ||
11 | +class Command extends Addons | ||
12 | +{ | ||
13 | + | ||
14 | + /** | ||
15 | + * 插件安装方法 | ||
16 | + * @return bool | ||
17 | + */ | ||
18 | + public function install() | ||
19 | + { | ||
20 | + $menu = [ | ||
21 | + [ | ||
22 | + 'name' => 'command', | ||
23 | + 'title' => '在线命令管理', | ||
24 | + 'icon' => 'fa fa-terminal', | ||
25 | + 'sublist' => [ | ||
26 | + ['name' => 'command/index', 'title' => '查看'], | ||
27 | + ['name' => 'command/add', 'title' => '添加'], | ||
28 | + ['name' => 'command/detail', 'title' => '详情'], | ||
29 | + ['name' => 'command/execute', 'title' => '运行'], | ||
30 | + ['name' => 'command/del', 'title' => '删除'], | ||
31 | + ['name' => 'command/multi', 'title' => '批量更新'], | ||
32 | + ] | ||
33 | + ] | ||
34 | + ]; | ||
35 | + Menu::create($menu); | ||
36 | + return true; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * 插件卸载方法 | ||
41 | + * @return bool | ||
42 | + */ | ||
43 | + public function uninstall() | ||
44 | + { | ||
45 | + Menu::delete('command'); | ||
46 | + return true; | ||
47 | + } | ||
48 | + | ||
49 | + /** | ||
50 | + * 插件启用方法 | ||
51 | + * @return bool | ||
52 | + */ | ||
53 | + public function enable() | ||
54 | + { | ||
55 | + Menu::enable('command'); | ||
56 | + return true; | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * 插件禁用方法 | ||
61 | + * @return bool | ||
62 | + */ | ||
63 | + public function disable() | ||
64 | + { | ||
65 | + Menu::disable('command'); | ||
66 | + return true; | ||
67 | + } | ||
68 | + | ||
69 | +} |
addons/command/config.php
0 → 100644
addons/command/controller/Index.php
0 → 100644
addons/command/info.ini
0 → 100644
addons/command/install.sql
0 → 100644
1 | +CREATE TABLE IF NOT EXISTS `__PREFIX__command` ( | ||
2 | + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID', | ||
3 | + `type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型', | ||
4 | + `params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '参数', | ||
5 | + `command` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '命令', | ||
6 | + `content` text COMMENT '返回结果', | ||
7 | + `executetime` int(10) UNSIGNED DEFAULT NULL COMMENT '执行时间', | ||
8 | + `createtime` int(10) UNSIGNED DEFAULT NULL COMMENT '创建时间', | ||
9 | + `updatetime` int(10) UNSIGNED DEFAULT NULL COMMENT '更新时间', | ||
10 | + `status` enum('successed','failured') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'failured' COMMENT '状态', | ||
11 | + PRIMARY KEY (`id`) USING BTREE | ||
12 | +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '在线命令表'; |
addons/command/library/Output.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace addons\command\library; | ||
4 | + | ||
5 | +/** | ||
6 | + * Class Output | ||
7 | + */ | ||
8 | +class Output extends \think\console\Output | ||
9 | +{ | ||
10 | + | ||
11 | + protected $message = []; | ||
12 | + | ||
13 | + public function __construct($driver = 'console') | ||
14 | + { | ||
15 | + parent::__construct($driver); | ||
16 | + } | ||
17 | + | ||
18 | + protected function block($style, $message) | ||
19 | + { | ||
20 | + $this->message[] = $message; | ||
21 | + } | ||
22 | + | ||
23 | + public function getMessage() | ||
24 | + { | ||
25 | + return $this->message; | ||
26 | + } | ||
27 | + | ||
28 | +} |
application/admin/controller/Command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | +use think\Config; | ||
7 | +use think\console\Input; | ||
8 | +use think\Db; | ||
9 | +use think\Exception; | ||
10 | + | ||
11 | +/** | ||
12 | + * 在线命令管理 | ||
13 | + * | ||
14 | + * @icon fa fa-circle-o | ||
15 | + */ | ||
16 | +class Command extends Backend | ||
17 | +{ | ||
18 | + | ||
19 | + /** | ||
20 | + * Command模型对象 | ||
21 | + */ | ||
22 | + protected $model = null; | ||
23 | + protected $noNeedRight = ['get_controller_list', 'get_field_list']; | ||
24 | + | ||
25 | + public function _initialize() | ||
26 | + { | ||
27 | + parent::_initialize(); | ||
28 | + $this->model = model('Command'); | ||
29 | + $this->view->assign("statusList", $this->model->getStatusList()); | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * 添加 | ||
34 | + */ | ||
35 | + public function add() | ||
36 | + { | ||
37 | + | ||
38 | + $tableList = []; | ||
39 | + $list = \think\Db::query("SHOW TABLES"); | ||
40 | + foreach ($list as $key => $row) { | ||
41 | + $tableList[reset($row)] = reset($row); | ||
42 | + } | ||
43 | + | ||
44 | + $this->view->assign("tableList", $tableList); | ||
45 | + return $this->view->fetch(); | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * 获取字段列表 | ||
50 | + * @internal | ||
51 | + */ | ||
52 | + public function get_field_list() | ||
53 | + { | ||
54 | + $dbname = Config::get('database.database'); | ||
55 | + $prefix = Config::get('database.prefix'); | ||
56 | + $table = $this->request->request('table'); | ||
57 | + //从数据库中获取表字段信息 | ||
58 | + $sql = "SELECT * FROM `information_schema`.`columns` " | ||
59 | + . "WHERE TABLE_SCHEMA = ? AND table_name = ? " | ||
60 | + . "ORDER BY ORDINAL_POSITION"; | ||
61 | + //加载主表的列 | ||
62 | + $columnList = Db::query($sql, [$dbname, $table]); | ||
63 | + $fieldlist = []; | ||
64 | + foreach ($columnList as $index => $item) { | ||
65 | + $fieldlist[] = $item['COLUMN_NAME']; | ||
66 | + } | ||
67 | + $this->success("", null, ['fieldlist' => $fieldlist]); | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * 获取控制器列表 | ||
72 | + * @internal | ||
73 | + */ | ||
74 | + public function get_controller_list() | ||
75 | + { | ||
76 | + //搜索关键词,客户端输入以空格分开,这里接收为数组 | ||
77 | + $word = (array)$this->request->request("q_word/a"); | ||
78 | + $word = implode('', $word); | ||
79 | + | ||
80 | + $adminPath = dirname(__DIR__) . DS; | ||
81 | + $controllerDir = $adminPath . 'controller' . DS; | ||
82 | + $files = new \RecursiveIteratorIterator( | ||
83 | + new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY | ||
84 | + ); | ||
85 | + $list = []; | ||
86 | + foreach ($files as $name => $file) { | ||
87 | + if (!$file->isDir()) { | ||
88 | + $filePath = $file->getRealPath(); | ||
89 | + $name = str_replace($controllerDir, '', $filePath); | ||
90 | + $name = str_replace(DS, "/", $name); | ||
91 | + if (!preg_match("/(.*)\.php\$/", $name)) { | ||
92 | + continue; | ||
93 | + } | ||
94 | + if (!$word || stripos($name, $word) !== false) { | ||
95 | + $list[] = ['id' => $name, 'name' => $name]; | ||
96 | + } | ||
97 | + } | ||
98 | + } | ||
99 | + $pageNumber = $this->request->request("pageNumber"); | ||
100 | + $pageSize = $this->request->request("pageSize"); | ||
101 | + return json(['list' => array_slice($list, ($pageNumber - 1) * $pageSize, $pageSize), 'total' => count($list)]); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * 详情 | ||
106 | + */ | ||
107 | + public function detail($ids) | ||
108 | + { | ||
109 | + $row = $this->model->get($ids); | ||
110 | + if (!$row) { | ||
111 | + $this->error(__('No Results were found')); | ||
112 | + } | ||
113 | + $this->view->assign("row", $row); | ||
114 | + return $this->view->fetch(); | ||
115 | + } | ||
116 | + | ||
117 | + /** | ||
118 | + * 执行 | ||
119 | + */ | ||
120 | + public function execute($ids) | ||
121 | + { | ||
122 | + $row = $this->model->get($ids); | ||
123 | + if (!$row) { | ||
124 | + $this->error(__('No Results were found')); | ||
125 | + } | ||
126 | + $result = $this->doexecute($row['type'], json_decode($row['params'], true)); | ||
127 | + $this->success("", null, ['result' => $result]); | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * 执行命令 | ||
132 | + */ | ||
133 | + public function command($action = '') | ||
134 | + { | ||
135 | + $commandtype = $this->request->request("commandtype"); | ||
136 | + $params = $this->request->request(); | ||
137 | + $allowfields = [ | ||
138 | + 'crud' => 'table,controller,model,fields,force,local,delete,menu', | ||
139 | + 'menu' => 'controller,delete', | ||
140 | + 'min' => 'module,resource,optimize', | ||
141 | + 'api' => 'url,module,output,template,force,title,author,class,language', | ||
142 | + ]; | ||
143 | + $argv = []; | ||
144 | + $allowfields = isset($allowfields[$commandtype]) ? explode(',', $allowfields[$commandtype]) : []; | ||
145 | + $allowfields = array_filter(array_intersect_key($params, array_flip($allowfields))); | ||
146 | + if (isset($params['local']) && !$params['local']) { | ||
147 | + $allowfields['local'] = $params['local']; | ||
148 | + } else { | ||
149 | + unset($allowfields['local']); | ||
150 | + } | ||
151 | + foreach ($allowfields as $key => $param) { | ||
152 | + $argv[] = "--{$key}=" . (is_array($param) ? implode(',', $param) : $param); | ||
153 | + } | ||
154 | + if ($commandtype == 'crud') { | ||
155 | + $extend = 'setcheckboxsuffix,enumradiosuffix,imagefield,filefield,intdatesuffix,switchsuffix,citysuffix,selectpagesuffix,selectpagessuffix,ignorefields,sortfield,editorsuffix,headingfilterfield'; | ||
156 | + $extendArr = explode(',', $extend); | ||
157 | + foreach ($params as $index => $item) { | ||
158 | + if (in_array($index, $extendArr)) { | ||
159 | + foreach (explode(',', $item) as $key => $value) { | ||
160 | + if ($value) { | ||
161 | + $argv[] = "--{$index}={$value}"; | ||
162 | + } | ||
163 | + } | ||
164 | + } | ||
165 | + } | ||
166 | + $isrelation = (int)$this->request->request('isrelation'); | ||
167 | + if ($isrelation && isset($params['relation'])) { | ||
168 | + foreach ($params['relation'] as $index => $relation) { | ||
169 | + foreach ($relation as $key => $value) { | ||
170 | + $argv[] = "--{$key}=" . (is_array($value) ? implode(',', $value) : $value); | ||
171 | + } | ||
172 | + } | ||
173 | + } | ||
174 | + } else { | ||
175 | + if ($commandtype == 'menu') { | ||
176 | + if (isset($params['allcontroller']) && $params['allcontroller']) { | ||
177 | + $argv[] = "--controller=all-controller"; | ||
178 | + } else { | ||
179 | + foreach (explode(',', $params['controllerfile']) as $index => $param) { | ||
180 | + if ($param) { | ||
181 | + $argv[] = "--controller=" . substr($param, 0, -4); | ||
182 | + } | ||
183 | + } | ||
184 | + } | ||
185 | + } else { | ||
186 | + if ($commandtype == 'min') { | ||
187 | + | ||
188 | + } else { | ||
189 | + if ($commandtype == 'api') { | ||
190 | + | ||
191 | + } else { | ||
192 | + | ||
193 | + } | ||
194 | + } | ||
195 | + } | ||
196 | + } | ||
197 | + if ($action == 'execute') { | ||
198 | + $result = $this->doexecute($commandtype, $argv); | ||
199 | + $this->success("", null, ['result' => $result]); | ||
200 | + } else { | ||
201 | + $this->success("", null, ['command' => "php think {$commandtype} " . implode(' ', $argv)]); | ||
202 | + } | ||
203 | + | ||
204 | + return; | ||
205 | + } | ||
206 | + | ||
207 | + protected function doexecute($commandtype, $argv) | ||
208 | + { | ||
209 | + $commandName = "\\app\\admin\\command\\" . ucfirst($commandtype); | ||
210 | + $input = new Input($argv); | ||
211 | + $output = new \addons\command\library\Output(); | ||
212 | + $command = new $commandName($commandtype); | ||
213 | + $data = [ | ||
214 | + 'type' => $commandtype, | ||
215 | + 'params' => json_encode($argv), | ||
216 | + 'command' => "php think {$commandtype} " . implode(' ', $argv), | ||
217 | + 'executetime' => time(), | ||
218 | + ]; | ||
219 | + $this->model->save($data); | ||
220 | + try { | ||
221 | + $command->run($input, $output); | ||
222 | + $result = implode("\n", $output->getMessage()); | ||
223 | + $this->model->status = 'successed'; | ||
224 | + } catch (Exception $e) { | ||
225 | + $result = implode("\n", $output->getMessage()) . "\n"; | ||
226 | + $result .= $e->getMessage(); | ||
227 | + $this->model->status = 'failured'; | ||
228 | + } | ||
229 | + $result = trim($result); | ||
230 | + $this->model->content = $result; | ||
231 | + $this->model->save(); | ||
232 | + return $result; | ||
233 | + } | ||
234 | + | ||
235 | + | ||
236 | +} |
application/admin/controller/Timeslot.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\controller; | ||
4 | + | ||
5 | +use app\common\controller\Backend; | ||
6 | + | ||
7 | +/** | ||
8 | + * 秒杀时间段 | ||
9 | + * | ||
10 | + * @icon fa fa-circle-o | ||
11 | + */ | ||
12 | +class Timeslot extends Backend | ||
13 | +{ | ||
14 | + | ||
15 | + /** | ||
16 | + * Timeslot模型对象 | ||
17 | + * @var \app\admin\model\Timeslot | ||
18 | + */ | ||
19 | + protected $model = null; | ||
20 | + | ||
21 | + public function _initialize() | ||
22 | + { | ||
23 | + parent::_initialize(); | ||
24 | + $this->model = new \app\admin\model\Timeslot; | ||
25 | + | ||
26 | + } | ||
27 | + | ||
28 | + public function import() | ||
29 | + { | ||
30 | + parent::import(); | ||
31 | + } | ||
32 | + | ||
33 | + /** | ||
34 | + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 | ||
35 | + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 | ||
36 | + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 | ||
37 | + */ | ||
38 | + | ||
39 | + | ||
40 | +} |
application/admin/lang/zh-cn/command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +return [ | ||
4 | + 'Id' => 'ID', | ||
5 | + 'Type' => '类型', | ||
6 | + 'Params' => '参数', | ||
7 | + 'Command' => '命令', | ||
8 | + 'Content' => '返回结果', | ||
9 | + 'Executetime' => '执行时间', | ||
10 | + 'Createtime' => '创建时间', | ||
11 | + 'Updatetime' => '更新时间', | ||
12 | + 'Execute again' => '再次执行', | ||
13 | + 'Successed' => '成功', | ||
14 | + 'Failured' => '失败', | ||
15 | + 'Status' => '状态' | ||
16 | +]; |
application/admin/lang/zh-cn/timeslot.php
0 → 100644
application/admin/model/Command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\model; | ||
4 | + | ||
5 | +use think\Model; | ||
6 | + | ||
7 | +class Command extends Model | ||
8 | +{ | ||
9 | + // 表名 | ||
10 | + protected $name = 'command'; | ||
11 | + | ||
12 | + // 自动写入时间戳字段 | ||
13 | + protected $autoWriteTimestamp = 'int'; | ||
14 | + | ||
15 | + // 定义时间戳字段名 | ||
16 | + protected $createTime = 'createtime'; | ||
17 | + protected $updateTime = 'updatetime'; | ||
18 | + | ||
19 | + // 追加属性 | ||
20 | + protected $append = [ | ||
21 | + 'executetime_text', | ||
22 | + 'type_text', | ||
23 | + 'status_text' | ||
24 | + ]; | ||
25 | + | ||
26 | + | ||
27 | + public function getStatusList() | ||
28 | + { | ||
29 | + return ['successed' => __('Successed'), 'failured' => __('Failured')]; | ||
30 | + } | ||
31 | + | ||
32 | + | ||
33 | + public function getExecutetimeTextAttr($value, $data) | ||
34 | + { | ||
35 | + $value = $value ? $value : $data['executetime']; | ||
36 | + return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; | ||
37 | + } | ||
38 | + | ||
39 | + public function getTypeTextAttr($value, $data) | ||
40 | + { | ||
41 | + $value = $value ? $value : $data['type']; | ||
42 | + $list = ['crud' => '一键生成CRUD', 'menu' => '一键生成菜单', 'min' => '一键压缩打包', 'api' => '一键生成文档']; | ||
43 | + return isset($list[$value]) ? $list[$value] : ''; | ||
44 | + } | ||
45 | + | ||
46 | + public function getStatusTextAttr($value, $data) | ||
47 | + { | ||
48 | + $value = $value ? $value : $data['status']; | ||
49 | + $list = $this->getStatusList(); | ||
50 | + return isset($list[$value]) ? $list[$value] : ''; | ||
51 | + } | ||
52 | + | ||
53 | + protected function setExecutetimeAttr($value) | ||
54 | + { | ||
55 | + return $value && !is_numeric($value) ? strtotime($value) : $value; | ||
56 | + } | ||
57 | + | ||
58 | + | ||
59 | +} |
application/admin/model/Timeslot.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\model; | ||
4 | + | ||
5 | +use think\Model; | ||
6 | + | ||
7 | + | ||
8 | +class Timeslot extends Model | ||
9 | +{ | ||
10 | + | ||
11 | + | ||
12 | + | ||
13 | + | ||
14 | + | ||
15 | + // 表名 | ||
16 | + protected $name = 'timeslot'; | ||
17 | + | ||
18 | + // 自动写入时间戳字段 | ||
19 | + protected $autoWriteTimestamp = false; | ||
20 | + | ||
21 | + // 定义时间戳字段名 | ||
22 | + protected $createTime = false; | ||
23 | + protected $updateTime = false; | ||
24 | + protected $deleteTime = false; | ||
25 | + | ||
26 | + // 追加属性 | ||
27 | + protected $append = [ | ||
28 | + 'time_text' | ||
29 | + ]; | ||
30 | + | ||
31 | + | ||
32 | + | ||
33 | + | ||
34 | + | ||
35 | + | ||
36 | + public function getTimeTextAttr($value, $data) | ||
37 | + { | ||
38 | + $value = $value ? $value : (isset($data['time']) ? $data['time'] : ''); | ||
39 | + return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; | ||
40 | + } | ||
41 | + | ||
42 | + | ||
43 | +} |
application/admin/validate/Command.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\validate; | ||
4 | + | ||
5 | +use think\Validate; | ||
6 | + | ||
7 | +class Command extends Validate | ||
8 | +{ | ||
9 | + /** | ||
10 | + * 验证规则 | ||
11 | + */ | ||
12 | + protected $rule = [ | ||
13 | + ]; | ||
14 | + /** | ||
15 | + * 提示消息 | ||
16 | + */ | ||
17 | + protected $message = [ | ||
18 | + ]; | ||
19 | + /** | ||
20 | + * 验证场景 | ||
21 | + */ | ||
22 | + protected $scene = [ | ||
23 | + 'add' => [], | ||
24 | + 'edit' => [], | ||
25 | + ]; | ||
26 | + | ||
27 | +} |
application/admin/validate/Timeslot.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace app\admin\validate; | ||
4 | + | ||
5 | +use think\Validate; | ||
6 | + | ||
7 | +class Timeslot extends Validate | ||
8 | +{ | ||
9 | + /** | ||
10 | + * 验证规则 | ||
11 | + */ | ||
12 | + protected $rule = [ | ||
13 | + ]; | ||
14 | + /** | ||
15 | + * 提示消息 | ||
16 | + */ | ||
17 | + protected $message = [ | ||
18 | + ]; | ||
19 | + /** | ||
20 | + * 验证场景 | ||
21 | + */ | ||
22 | + protected $scene = [ | ||
23 | + 'add' => [], | ||
24 | + 'edit' => [], | ||
25 | + ]; | ||
26 | + | ||
27 | +} |
application/admin/view/command/add.html
0 → 100644
1 | +<style> | ||
2 | + .relation-item {margin-top:10px;} | ||
3 | + legend {padding-bottom:5px;font-size:14px;font-weight:600;} | ||
4 | + label {font-weight:normal;} | ||
5 | + .form-control{padding:6px 8px;} | ||
6 | + #extend-zone .col-xs-2 {margin-top:10px;padding-right:0;} | ||
7 | + #extend-zone .col-xs-2:nth-child(6n+0) {padding-right:15px;} | ||
8 | +</style> | ||
9 | +<div class="panel panel-default panel-intro"> | ||
10 | + <div class="panel-heading"> | ||
11 | + <ul class="nav nav-tabs"> | ||
12 | + <li class="active"><a href="#crud" data-toggle="tab">{:__('一键生成CRUD')}</a></li> | ||
13 | + <li><a href="#menu" data-toggle="tab">{:__('一键生成菜单')}</a></li> | ||
14 | + <li><a href="#min" data-toggle="tab">{:__('一键压缩打包')}</a></li> | ||
15 | + <li><a href="#api" data-toggle="tab">{:__('一键生成API文档')}</a></li> | ||
16 | + </ul> | ||
17 | + </div> | ||
18 | + <div class="panel-body"> | ||
19 | + <div id="myTabContent" class="tab-content"> | ||
20 | + <div class="tab-pane fade active in" id="crud"> | ||
21 | + <div class="row"> | ||
22 | + <div class="col-xs-12"> | ||
23 | + <form role="form"> | ||
24 | + <input type="hidden" name="commandtype" value="crud" /> | ||
25 | + <div class="form-group"> | ||
26 | + <div class="row"> | ||
27 | + <div class="col-xs-3"> | ||
28 | + <input checked="" name="isrelation" type="hidden" value="0"> | ||
29 | + <label class="control-label" data-toggle="tooltip" title="当前只支持生成1对1关联模型,选中后请配置关联表和字段"> | ||
30 | + <input name="isrelation" type="checkbox" value="1"> | ||
31 | + 关联模型 | ||
32 | + </label> | ||
33 | + </div> | ||
34 | + <div class="col-xs-3"> | ||
35 | + <input checked="" name="local" type="hidden" value="1"> | ||
36 | + <label class="control-label" data-toggle="tooltip" title="默认模型生成在application/admin/model目录下,选中后将生成在application/common/model目录下"> | ||
37 | + <input name="local" type="checkbox" value="0"> 全局模型类 | ||
38 | + </label> | ||
39 | + </div> | ||
40 | + <div class="col-xs-3"> | ||
41 | + <input checked="" name="delete" type="hidden" value="0"> | ||
42 | + <label class="control-label" data-toggle="tooltip" title="删除CRUD生成的相关文件"> | ||
43 | + <input name="delete" type="checkbox" value="1"> 删除模式 | ||
44 | + </label> | ||
45 | + </div> | ||
46 | + <div class="col-xs-3"> | ||
47 | + <input checked="" name="force" type="hidden" value="0"> | ||
48 | + <label class="control-label" data-toggle="tooltip" title="选中后,如果已经存在同名文件将被覆盖。如果是删除将不再提醒"> | ||
49 | + <input name="force" type="checkbox" value="1"> | ||
50 | + 强制覆盖模式 | ||
51 | + </label> | ||
52 | + </div> | ||
53 | + <!-- | ||
54 | + <div class="col-xs-3"> | ||
55 | + <input checked="" name="menu" type="hidden" value="0"> | ||
56 | + <label class="control-label" data-toggle="tooltip" title="选中后,将同时生成后台菜单规则"> | ||
57 | + <input name="menu" type="checkbox" value="1"> | ||
58 | + 生成菜单 | ||
59 | + </label> | ||
60 | + </div> | ||
61 | + --> | ||
62 | + </div> | ||
63 | + </div> | ||
64 | + <div class="form-group"> | ||
65 | + <legend>主表设置</legend> | ||
66 | + <div class="row"> | ||
67 | + <div class="col-xs-3"> | ||
68 | + <label>请选择主表</label> | ||
69 | + {:build_select('table',$tableList,null,['class'=>'form-control selectpicker', 'data-live-search'=>'true']);} | ||
70 | + </div> | ||
71 | + <div class="col-xs-3"> | ||
72 | + <label>自定义控制器名</label> | ||
73 | + <input type="text" class="form-control" name="controller" data-toggle="tooltip" title="默认根据表名自动生成,如果需要放在二级目录请手动填写" placeholder="支持目录层级,以/分隔"> | ||
74 | + </div> | ||
75 | + <div class="col-xs-3"> | ||
76 | + <label>自定义模型名</label> | ||
77 | + <input type="text" class="form-control" name="model" data-toggle="tooltip" title="默认根据表名自动生成" placeholder="不支持目录层级"> | ||
78 | + </div> | ||
79 | + <div class="col-xs-3"> | ||
80 | + <label>请选择显示字段(默认全部)</label> | ||
81 | + <select name="fields[]" id="fields" multiple style="height:30px;" class="form-control selectpicker"></select> | ||
82 | + </div> | ||
83 | + | ||
84 | + </div> | ||
85 | + | ||
86 | + </div> | ||
87 | + | ||
88 | + <div class="form-group hide" id="relation-zone"> | ||
89 | + <legend>关联表设置</legend> | ||
90 | + | ||
91 | + <div class="row" style="margin-top:15px;"> | ||
92 | + <div class="col-xs-12"> | ||
93 | + <a href="javascript:;" class="btn btn-primary btn-sm btn-newrelation" data-index="1">追加关联模型</a> | ||
94 | + </div> | ||
95 | + </div> | ||
96 | + </div> | ||
97 | + | ||
98 | + <hr> | ||
99 | + <div class="form-group" id="extend-zone"> | ||
100 | + <legend>字段识别设置 <span style="font-size:12px;font-weight: normal;">(与之匹配的字段都将生成相应组件)</span></legend> | ||
101 | + <div class="row"> | ||
102 | + <div class="col-xs-2"> | ||
103 | + <label>复选框后缀</label> | ||
104 | + <input type="text" class="form-control" name="setcheckboxsuffix" placeholder="默认为set类型" /> | ||
105 | + </div> | ||
106 | + <div class="col-xs-2"> | ||
107 | + <label>单选框后缀</label> | ||
108 | + <input type="text" class="form-control" name="enumradiosuffix" placeholder="默认为enum类型" /> | ||
109 | + </div> | ||
110 | + <div class="col-xs-2"> | ||
111 | + <label>图片类型后缀</label> | ||
112 | + <input type="text" class="form-control" name="imagefield" placeholder="默认为image,images,avatar,avatars" /> | ||
113 | + </div> | ||
114 | + <div class="col-xs-2"> | ||
115 | + <label>文件类型后缀</label> | ||
116 | + <input type="text" class="form-control" name="filefield" placeholder="默认为file,files" /> | ||
117 | + </div> | ||
118 | + <div class="col-xs-2"> | ||
119 | + <label>日期时间后缀</label> | ||
120 | + <input type="text" class="form-control" name="intdatesuffix" placeholder="默认为time" /> | ||
121 | + </div> | ||
122 | + <div class="col-xs-2"> | ||
123 | + <label>开关后缀</label> | ||
124 | + <input type="text" class="form-control" name="switchsuffix" placeholder="默认为switch" /> | ||
125 | + </div> | ||
126 | + <div class="col-xs-2"> | ||
127 | + <label>城市选择后缀</label> | ||
128 | + <input type="text" class="form-control" name="citysuffix" placeholder="默认为city" /> | ||
129 | + </div> | ||
130 | + <div class="col-xs-2"> | ||
131 | + <label>动态下拉后缀(单)</label> | ||
132 | + <input type="text" class="form-control" name="selectpagesuffix" placeholder="默认为_id" /> | ||
133 | + </div> | ||
134 | + <div class="col-xs-2"> | ||
135 | + <label>动态下拉后缀(多)</label> | ||
136 | + <input type="text" class="form-control" name="selectpagessuffix" placeholder="默认为_ids" /> | ||
137 | + </div> | ||
138 | + <div class="col-xs-2"> | ||
139 | + <label>忽略的字段</label> | ||
140 | + <input type="text" class="form-control" name="ignorefields" placeholder="默认无" /> | ||
141 | + </div> | ||
142 | + <div class="col-xs-2"> | ||
143 | + <label>排序字段</label> | ||
144 | + <input type="text" class="form-control" name="sortfield" placeholder="默认为weigh" /> | ||
145 | + </div> | ||
146 | + <div class="col-xs-2"> | ||
147 | + <label>富文本编辑器</label> | ||
148 | + <input type="text" class="form-control" name="editorsuffix" placeholder="默认为content" /> | ||
149 | + </div> | ||
150 | + <div class="col-xs-2"> | ||
151 | + <label>选项卡过滤字段</label> | ||
152 | + <input type="text" class="form-control" name="headingfilterfield" placeholder="默认为status" /> | ||
153 | + </div> | ||
154 | + | ||
155 | + </div> | ||
156 | + | ||
157 | + </div> | ||
158 | + | ||
159 | + <div class="form-group"> | ||
160 | + <legend>生成命令行</legend> | ||
161 | + <textarea class="form-control" data-toggle="tooltip" title="如果在线执行命令失败,可以将命令复制到命令行进行执行" rel="command" rows="1" placeholder="请点击生成命令行"></textarea> | ||
162 | + </div> | ||
163 | + | ||
164 | + <div class="form-group"> | ||
165 | + <legend>返回结果</legend> | ||
166 | + <textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea> | ||
167 | + </div> | ||
168 | + | ||
169 | + <div class="form-group"> | ||
170 | + <button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button> | ||
171 | + <button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button> | ||
172 | + </div> | ||
173 | + | ||
174 | + </form> | ||
175 | + </div> | ||
176 | + </div> | ||
177 | + </div> | ||
178 | + <div class="tab-pane fade" id="menu"> | ||
179 | + <div class="row"> | ||
180 | + <div class="col-xs-12"> | ||
181 | + <form role="form"> | ||
182 | + <input type="hidden" name="commandtype" value="menu" /> | ||
183 | + <div class="form-group"> | ||
184 | + <div class="row"> | ||
185 | + <div class="col-xs-3"> | ||
186 | + <input checked="" name="allcontroller" type="hidden" value="0"> | ||
187 | + <label class="control-label"> | ||
188 | + <input name="allcontroller" data-toggle="collapse" data-target="#controller" type="checkbox" value="1"> 一键生成全部控制器 | ||
189 | + </label> | ||
190 | + </div> | ||
191 | + <div class="col-xs-3"> | ||
192 | + <input checked="" name="delete" type="hidden" value="0"> | ||
193 | + <label class="control-label"> | ||
194 | + <input name="delete" type="checkbox" value="1"> 删除模式 | ||
195 | + </label> | ||
196 | + </div> | ||
197 | + <div class="col-xs-3"> | ||
198 | + <input checked="" name="force" type="hidden" value="0"> | ||
199 | + <label class="control-label"> | ||
200 | + <input name="force" type="checkbox" value="1"> 强制覆盖模式 | ||
201 | + </label> | ||
202 | + </div> | ||
203 | + </div> | ||
204 | + </div> | ||
205 | + | ||
206 | + <div class="form-group in" id="controller"> | ||
207 | + <legend>控制器设置</legend> | ||
208 | + | ||
209 | + <div class="row" style="margin-top:15px;"> | ||
210 | + <div class="col-xs-12"> | ||
211 | + <input type="text" name="controllerfile" class="form-control selectpage" style="width:720px;" data-source="command/get_controller_list" data-multiple="true" name="controller" placeholder="请选择控制器" /> | ||
212 | + </div> | ||
213 | + </div> | ||
214 | + </div> | ||
215 | + | ||
216 | + <div class="form-group"> | ||
217 | + <legend>生成命令行</legend> | ||
218 | + <textarea class="form-control" rel="command" rows="1" placeholder="请点击生成命令行"></textarea> | ||
219 | + </div> | ||
220 | + | ||
221 | + <div class="form-group"> | ||
222 | + <legend>返回结果</legend> | ||
223 | + <textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea> | ||
224 | + </div> | ||
225 | + | ||
226 | + <div class="form-group"> | ||
227 | + <button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button> | ||
228 | + <button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button> | ||
229 | + </div> | ||
230 | + | ||
231 | + </form> | ||
232 | + </div> | ||
233 | + </div> | ||
234 | + </div> | ||
235 | + <div class="tab-pane fade" id="min"> | ||
236 | + <div class="row"> | ||
237 | + <div class="col-xs-12"> | ||
238 | + <form role="form"> | ||
239 | + <input type="hidden" name="commandtype" value="min" /> | ||
240 | + <div class="form-group"> | ||
241 | + <legend>基础设置</legend> | ||
242 | + <div class="row"> | ||
243 | + <div class="col-xs-3"> | ||
244 | + <label>请选择压缩模块</label> | ||
245 | + <select name="module" class="form-control selectpicker"> | ||
246 | + <option value="all" selected>全部</option> | ||
247 | + <option value="backend">后台Backend</option> | ||
248 | + <option value="frontend">前台Frontend</option> | ||
249 | + </select> | ||
250 | + </div> | ||
251 | + <div class="col-xs-3"> | ||
252 | + <label>请选择压缩资源</label> | ||
253 | + <select name="resource" class="form-control selectpicker"> | ||
254 | + <option value="all" selected>全部</option> | ||
255 | + <option value="js">JS</option> | ||
256 | + <option value="css">CSS</option> | ||
257 | + </select> | ||
258 | + </div> | ||
259 | + <div class="col-xs-3"> | ||
260 | + <label>请选择压缩模式</label> | ||
261 | + <select name="optimize" class="form-control selectpicker"> | ||
262 | + <option value="">无</option> | ||
263 | + <option value="uglify">uglify</option> | ||
264 | + <option value="closure">closure</option> | ||
265 | + </select> | ||
266 | + </div> | ||
267 | + </div> | ||
268 | + </div> | ||
269 | + | ||
270 | + <div class="form-group in"> | ||
271 | + <legend>控制器设置</legend> | ||
272 | + | ||
273 | + <div class="row" style="margin-top:15px;"> | ||
274 | + <div class="col-xs-12"> | ||
275 | + | ||
276 | + </div> | ||
277 | + </div> | ||
278 | + </div> | ||
279 | + | ||
280 | + <div class="form-group"> | ||
281 | + <legend>生成命令行</legend> | ||
282 | + <textarea class="form-control" rel="command" rows="1" placeholder="请点击生成命令行"></textarea> | ||
283 | + </div> | ||
284 | + | ||
285 | + <div class="form-group"> | ||
286 | + <legend>返回结果</legend> | ||
287 | + <textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea> | ||
288 | + </div> | ||
289 | + | ||
290 | + <div class="form-group"> | ||
291 | + <button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button> | ||
292 | + <button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button> | ||
293 | + </div> | ||
294 | + | ||
295 | + </form> | ||
296 | + </div> | ||
297 | + </div> | ||
298 | + </div> | ||
299 | + <div class="tab-pane fade" id="api"> | ||
300 | + <div class="row"> | ||
301 | + <div class="col-xs-12"> | ||
302 | + <form role="form"> | ||
303 | + <input type="hidden" name="commandtype" value="api" /> | ||
304 | + <div class="form-group"> | ||
305 | + <div class="row"> | ||
306 | + <div class="col-xs-3"> | ||
307 | + <input checked="" name="force" type="hidden" value="0"> | ||
308 | + <label class="control-label"> | ||
309 | + <input name="force" type="checkbox" value="1"> | ||
310 | + 覆盖模式 | ||
311 | + </label> | ||
312 | + </div> | ||
313 | + </div> | ||
314 | + </div> | ||
315 | + <div class="form-group"> | ||
316 | + <legend>文档设置</legend> | ||
317 | + <div class="row"> | ||
318 | + <div class="col-xs-3"> | ||
319 | + <label>请输入接口URL</label> | ||
320 | + <input type="text" name="url" class="form-control" placeholder="API URL,可留空" /> | ||
321 | + </div> | ||
322 | + <div class="col-xs-3"> | ||
323 | + <label>接口生成文件</label> | ||
324 | + <input type="text" name="output" class="form-control" placeholder="留空则使用api.html" /> | ||
325 | + </div> | ||
326 | + <div class="col-xs-3"> | ||
327 | + <label>模板文件</label> | ||
328 | + <input type="text" name="template" class="form-control" placeholder="如果不清楚请留空" /> | ||
329 | + </div> | ||
330 | + </div> | ||
331 | + <div class="row" style="margin-top:10px;"> | ||
332 | + <div class="col-xs-3"> | ||
333 | + <label>文档标题</label> | ||
334 | + <input type="text" name="title" class="form-control" placeholder="默认为FastAdmin" /> | ||
335 | + </div> | ||
336 | + <div class="col-xs-3"> | ||
337 | + <label>文档作者</label> | ||
338 | + <input type="text" name="author" class="form-control" placeholder="默认为FastAdmin" /> | ||
339 | + </div> | ||
340 | + <div class="col-xs-3"> | ||
341 | + <label>文档语言</label> | ||
342 | + <select name="language" class="form-control"> | ||
343 | + <option value="" selected>请选择语言</option> | ||
344 | + <option value="zh-cn">中文</option> | ||
345 | + <option value="en">英文</option> | ||
346 | + </select> | ||
347 | + </div> | ||
348 | + </div> | ||
349 | + </div> | ||
350 | + | ||
351 | + <div class="form-group"> | ||
352 | + <legend>生成命令行</legend> | ||
353 | + <textarea class="form-control" rel="command" rows="1" placeholder="请点击生成命令行"></textarea> | ||
354 | + </div> | ||
355 | + | ||
356 | + <div class="form-group"> | ||
357 | + <legend>返回结果</legend> | ||
358 | + <textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea> | ||
359 | + </div> | ||
360 | + | ||
361 | + <div class="form-group"> | ||
362 | + <button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button> | ||
363 | + <button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button> | ||
364 | + </div> | ||
365 | + | ||
366 | + </form> | ||
367 | + </div> | ||
368 | + </div> | ||
369 | + </div> | ||
370 | + </div> | ||
371 | + </div> | ||
372 | +</div> | ||
373 | +<script id="relationtpl" type="text/html"> | ||
374 | + <div class="row relation-item"> | ||
375 | + <div class="col-xs-2"> | ||
376 | + <label>请选择关联表</label> | ||
377 | + <select name="relation[<%=index%>][relation]" class="form-control relationtable" data-live-search="true"></select> | ||
378 | + </div> | ||
379 | + <div class="col-xs-2"> | ||
380 | + <label>请选择关联类型</label> | ||
381 | + <select name="relation[<%=index%>][relationmode]" class="form-control relationmode"></select> | ||
382 | + </div> | ||
383 | + <div class="col-xs-2"> | ||
384 | + <label>关联外键</label> | ||
385 | + <select name="relation[<%=index%>][relationforeignkey]" class="form-control relationforeignkey"></select> | ||
386 | + </div> | ||
387 | + <div class="col-xs-2"> | ||
388 | + <label>关联主键</label> | ||
389 | + <select name="relation[<%=index%>][relationprimarykey]" class="form-control relationprimarykey"></select> | ||
390 | + </div> | ||
391 | + <div class="col-xs-2"> | ||
392 | + <label>请选择显示字段</label> | ||
393 | + <select name="relation[<%=index%>][relationfields][]" multiple class="form-control relationfields"></select> | ||
394 | + </div> | ||
395 | + <div class="col-xs-2"> | ||
396 | + <label> </label> | ||
397 | + <a href="javascript:;" class="btn btn-danger btn-block btn-removerelation">移除</a> | ||
398 | + </div> | ||
399 | + </div> | ||
400 | +</script> |
application/admin/view/command/detail.html
0 → 100644
1 | +<table class="table table-striped"> | ||
2 | + <thead> | ||
3 | + <tr> | ||
4 | + <th>{:__('Title')}</th> | ||
5 | + <th>{:__('Content')}</th> | ||
6 | + </tr> | ||
7 | + </thead> | ||
8 | + <tbody> | ||
9 | + <tr> | ||
10 | + <td>{:__('Type')}</td> | ||
11 | + <td>{$row.type}({$row.type_text})</td> | ||
12 | + </tr> | ||
13 | + <tr> | ||
14 | + <td>{:__('Params')}</td> | ||
15 | + <td>{$row.params}</td> | ||
16 | + </tr> | ||
17 | + <tr> | ||
18 | + <td>{:__('Command')}</td> | ||
19 | + <td>{$row.command}</td> | ||
20 | + </tr> | ||
21 | + <tr> | ||
22 | + <td>{:__('Content')}</td> | ||
23 | + <td> | ||
24 | + <textarea class="form-control" name="" id="" cols="60" rows="10">{$row.content}</textarea> | ||
25 | + </td> | ||
26 | + </tr> | ||
27 | + <tr> | ||
28 | + <td>{:__('Executetime')}</td> | ||
29 | + <td>{$row.executetime|datetime}</td> | ||
30 | + </tr> | ||
31 | + <tr> | ||
32 | + <td>{:__('Status')}</td> | ||
33 | + <td>{$row.status_text}</td> | ||
34 | + </tr> | ||
35 | + </tbody> | ||
36 | +</table> | ||
37 | +<div class="hide layer-footer"> | ||
38 | + <label class="control-label col-xs-12 col-sm-2"></label> | ||
39 | + <div class="col-xs-12 col-sm-8"> | ||
40 | + <button type="reset" class="btn btn-primary btn-embossed btn-close" onclick="Layer.closeAll();">{:__('Close')}</button> | ||
41 | + </div> | ||
42 | +</div> |
application/admin/view/command/index.html
0 → 100644
1 | +<div class="panel panel-default panel-intro"> | ||
2 | + {:build_heading()} | ||
3 | + | ||
4 | + <div class="panel-body"> | ||
5 | + <div id="myTabContent" class="tab-content"> | ||
6 | + <div class="tab-pane fade active in" id="one"> | ||
7 | + <div class="widget-body no-padding"> | ||
8 | + <div id="toolbar" class="toolbar"> | ||
9 | + <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a> | ||
10 | + <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('command/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a> | ||
11 | + <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('command/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a> | ||
12 | + | ||
13 | + </div> | ||
14 | + <table id="table" class="table table-striped table-bordered table-hover" | ||
15 | + data-operate-detail="{:$auth->check('command/detail')}" | ||
16 | + data-operate-execute="{:$auth->check('command/execute')}" | ||
17 | + data-operate-del="{:$auth->check('command/del')}" | ||
18 | + width="100%"> | ||
19 | + </table> | ||
20 | + </div> | ||
21 | + </div> | ||
22 | + | ||
23 | + </div> | ||
24 | + </div> | ||
25 | +</div> |
application/admin/view/timeslot/add.html
0 → 100644
1 | +<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""> | ||
2 | + | ||
3 | + <div class="form-group"> | ||
4 | + <label class="control-label col-xs-12 col-sm-2">{:__('Time')}:</label> | ||
5 | + <div class="col-xs-12 col-sm-8"> | ||
6 | + <input id="c-time" class="form-control datetimepicker" data-date-format="HH:mm" data-use-current="true" name="row[time]" type="text" value="{:date('H:i')}"> | ||
7 | + </div> | ||
8 | + </div> | ||
9 | + <div class="form-group layer-footer"> | ||
10 | + <label class="control-label col-xs-12 col-sm-2"></label> | ||
11 | + <div class="col-xs-12 col-sm-8"> | ||
12 | + <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button> | ||
13 | + <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> | ||
14 | + </div> | ||
15 | + </div> | ||
16 | +</form> |
application/admin/view/timeslot/edit.html
0 → 100644
1 | +<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""> | ||
2 | + | ||
3 | + <div class="form-group"> | ||
4 | + <label class="control-label col-xs-12 col-sm-2">{:__('Time')}:</label> | ||
5 | + <div class="col-xs-12 col-sm-8"> | ||
6 | + <input id="c-time" class="form-control datetimepicker" data-date-format="HH:mm" data-use-current="true" name="row[time]" type="text" value="{:$row.time?datetime('H:i',$row.time):''}"> | ||
7 | + </div> | ||
8 | + </div> | ||
9 | + <div class="form-group layer-footer"> | ||
10 | + <label class="control-label col-xs-12 col-sm-2"></label> | ||
11 | + <div class="col-xs-12 col-sm-8"> | ||
12 | + <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button> | ||
13 | + <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> | ||
14 | + </div> | ||
15 | + </div> | ||
16 | +</form> |
application/admin/view/timeslot/index.html
0 → 100644
1 | +<div class="panel panel-default panel-intro"> | ||
2 | + {:build_heading()} | ||
3 | + | ||
4 | + <div class="panel-body"> | ||
5 | + <div id="myTabContent" class="tab-content"> | ||
6 | + <div class="tab-pane fade active in" id="one"> | ||
7 | + <div class="widget-body no-padding"> | ||
8 | + <div id="toolbar" class="toolbar"> | ||
9 | + <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a> | ||
10 | +<!-- <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('timeslot/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>--> | ||
11 | + <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('timeslot/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a> | ||
12 | +<!-- <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('timeslot/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>--> | ||
13 | +<!-- <a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('timeslot/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>--> | ||
14 | + | ||
15 | +<!-- <div class="dropdown btn-group {:$auth->check('timeslot/multi')?'':'hide'}">--> | ||
16 | +<!-- <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>--> | ||
17 | +<!-- <ul class="dropdown-menu text-left" role="menu">--> | ||
18 | +<!-- <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>--> | ||
19 | +<!-- <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>--> | ||
20 | +<!-- </ul>--> | ||
21 | +<!-- </div>--> | ||
22 | + | ||
23 | + | ||
24 | + </div> | ||
25 | + <table id="table" class="table table-striped table-bordered table-hover table-nowrap" | ||
26 | + data-operate-edit="{:$auth->check('timeslot/edit')}" | ||
27 | + data-operate-del="{:$auth->check('timeslot/del')}" | ||
28 | + width="100%"> | ||
29 | + </table> | ||
30 | + </div> | ||
31 | + </div> | ||
32 | + | ||
33 | + </div> | ||
34 | + </div> | ||
35 | +</div> |
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace app\api\controller; | ||
5 | + | ||
6 | + | ||
7 | +use app\api\model\Category; | ||
8 | +use app\api\model\Goods; | ||
9 | +use app\api\model\GoodsSpec; | ||
10 | +use app\api\model\GoodsSpecRel; | ||
11 | +use app\common\controller\Api; | ||
12 | +use think\Config; | ||
13 | +use think\Db; | ||
14 | + | ||
15 | +/** | ||
16 | + * 分类页面 | ||
17 | + */ | ||
18 | +class Classification extends Api | ||
19 | +{ | ||
20 | + protected $noNeedLogin = ['*']; | ||
21 | + protected $noNeedRight = ['*']; | ||
22 | + | ||
23 | + /** | ||
24 | + * @ApiTitle (分类列表) | ||
25 | + * @ApiSummary (分类按钮页面左侧分类列表 其他页面切换到分类页面id不传值 分类页面点击分类id传值 后台返回高亮显示) | ||
26 | + * @ApiMethod (POST) | ||
27 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
28 | + * @ApiParams (name=id, type=integer, required=false, description="分类id") | ||
29 | + * @ApiReturn ({ | ||
30 | + 'code':'1', | ||
31 | + 'msg':'返回成功' | ||
32 | + 'data':[ | ||
33 | + { | ||
34 | + "id": 4, | ||
35 | + "name": "电子产品", | ||
36 | + "is_myself": "0", 0不高亮1高亮 | ||
37 | + "image_text": "" | ||
38 | + }, | ||
39 | + { | ||
40 | + "id": 6, | ||
41 | + "name": "水果", | ||
42 | + "is_myself": "0", | ||
43 | + "image_text": "" | ||
44 | + } | ||
45 | + ] | ||
46 | + }) | ||
47 | + */ | ||
48 | + public function sort() | ||
49 | + { | ||
50 | + $id = $this->request->post('id',0); | ||
51 | + $model = new Category(); | ||
52 | + $list = $model->field('id,name')->select(); | ||
53 | + foreach ($list as $key => &$value){ | ||
54 | + $value['is_myself'] = $value['id']==$id?'1':'0'; | ||
55 | + } | ||
56 | + $this->success('分类列表',$list); | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * @ApiTitle (分类列表商品) | ||
61 | + * @ApiSummary (分类按钮页面右侧商品列表 初次点击分类页面可不传分类id值) | ||
62 | + * @ApiMethod (POST) | ||
63 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
64 | + * @ApiParams (name=sort_id, type=integer, required=false, description="分类id") | ||
65 | + * @ApiParams (name=page, type=integer, required=false, description="页数") | ||
66 | + * @ApiReturn ({ | ||
67 | + 'code':'1', | ||
68 | + 'msg':'返回成功' | ||
69 | + 'data':{ | ||
70 | + "list": { | ||
71 | + "total": 4, 总条数 | ||
72 | + "per_page": 10,每页数量 | ||
73 | + "current_page": 1,当前页 | ||
74 | + "last_page": 1,最后一页 | ||
75 | + "data": [ | ||
76 | + { | ||
77 | + "goods_id": 21, | ||
78 | + "goods_name": "小米Mix3", | ||
79 | + "price": "100.00", | ||
80 | + "line_price": "1000.00",划线价 | ||
81 | + "image_text": "图片路径" | ||
82 | + } | ||
83 | + ] | ||
84 | + }, | ||
85 | + "image": "广告图" | ||
86 | + } | ||
87 | + }) | ||
88 | + */ | ||
89 | + public function sortGoodsList() | ||
90 | + { | ||
91 | + $sort_id = $this->request->post('sort_id',0); | ||
92 | + $page = $this->request->post('page',1); | ||
93 | + $model = new Goods(); | ||
94 | + if ($sort_id > 0){ | ||
95 | + $list = $model->where('is_index','1') | ||
96 | + ->where('is_delete','0') | ||
97 | + ->where('goods_status','10') | ||
98 | + ->field('goods_id,goods_name,image') | ||
99 | + ->paginate(10,false,['page'=>$page]) | ||
100 | + ->each(function ($item,$key){ | ||
101 | + $goods_spec = Db::name('litestore_goods_spec') | ||
102 | + ->where('goods_id',$item['goods_id']) | ||
103 | + ->find(); | ||
104 | + $item['price'] = $goods_spec['goods_price']; | ||
105 | + $item['line_price'] = $goods_spec['line_price']; | ||
106 | + }); | ||
107 | + }else{ | ||
108 | + $list = $model | ||
109 | + ->field('goods_id,goods_name,image') | ||
110 | + ->paginate(10,false,['page'=>$page]) | ||
111 | + ->each(function ($item,$key){ | ||
112 | + $goods_spec = Db::name('litestore_goods_spec') | ||
113 | + ->where('goods_id',$item['goods_id']) | ||
114 | + ->find(); | ||
115 | + $item['price'] = $goods_spec['goods_price']; | ||
116 | + $item['line_price'] = $goods_spec['line_price']; | ||
117 | + }); | ||
118 | + } | ||
119 | + $this->success('分类商品列表',['list'=>$list,'image'=>cdnurl(Config::get('site.advert'),true)]); | ||
120 | + } | ||
121 | + | ||
122 | + /** | ||
123 | + * @ApiTitle (商品规格) | ||
124 | + * @ApiSummary (分类按钮页面右侧商品列表 初次点击分类页面可不传分类id值) | ||
125 | + * @ApiMethod (POST) | ||
126 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
127 | + * @ApiParams (name=goods_id, type=integer, required=true, description="商品id") | ||
128 | + * @ApiReturn ({ | ||
129 | + 'code':'1', | ||
130 | + 'msg':'返回成功' | ||
131 | + 'data':{ | ||
132 | + // 规格组合完毕的列表 | ||
133 | + "list": [ | ||
134 | + { | ||
135 | + "goods_spec_id": 103, | ||
136 | + "goods_id": 22, | ||
137 | + "goods_no": "SNHW001", | ||
138 | + "goods_price": "4499.00", | ||
139 | + "line_price": "0.00", | ||
140 | + "stock_num": 941, | ||
141 | + "goods_sales": 58, | ||
142 | + "goods_weight": 500, | ||
143 | + "spec_sku_id": "44_46", // 搜索字段 组合sku里面的id搜索 从小到大排序 | ||
144 | + "spec_image": "", | ||
145 | + "create_time": 1542784591, | ||
146 | + "update_time": 1543242861 | ||
147 | + } | ||
148 | + ], | ||
149 | + // 规格展示的列表 | ||
150 | + "sku": [ | ||
151 | + { | ||
152 | + "name": "颜色", | ||
153 | + "second": [ | ||
154 | + { | ||
155 | + "id": 44, | ||
156 | + "name": "亮黑色" | ||
157 | + } | ||
158 | + ] | ||
159 | + }, | ||
160 | + { | ||
161 | + "name": "内存", | ||
162 | + "second": [ | ||
163 | + { | ||
164 | + "id": 46, | ||
165 | + "name": "6GB+64GB" | ||
166 | + } | ||
167 | + ] | ||
168 | + } | ||
169 | + ] | ||
170 | + } | ||
171 | + }) | ||
172 | + */ | ||
173 | + public function goodsSku() | ||
174 | + { | ||
175 | + $goods_id = $this->request->post('goods_id'); | ||
176 | + $goodsspecrelmodel = new GoodsSpecRel(); | ||
177 | + $list = $goodsspecrelmodel | ||
178 | + ->where('goods_id',$goods_id) | ||
179 | + ->select(); | ||
180 | + $array = []; | ||
181 | + foreach ($list as $key => $value){ | ||
182 | + if (!isset($array[$value['spec_id']])){ | ||
183 | + $array[$value['spec_id']]['name'] = Db::name('litestore_spec') | ||
184 | + ->where('id',$value['spec_id']) | ||
185 | + ->value('spec_name'); | ||
186 | + } | ||
187 | + $spec_value =Db::name('litestore_spec_value') | ||
188 | + ->where('id',$value['spec_value_id']) | ||
189 | + ->value('spec_value'); | ||
190 | + $array[$value['spec_id']]['second'][] = [ | ||
191 | + 'id' => $value['spec_value_id'], | ||
192 | + 'name' => $spec_value | ||
193 | + ]; | ||
194 | + } | ||
195 | + $array = array_values($array); | ||
196 | + $goods_spec = GoodsSpec::all(['goods_id'=>$goods_id]); | ||
197 | + $this->success('商品规格',['list'=>$goods_spec,'sku'=>$array]); | ||
198 | + } | ||
199 | + | ||
200 | +} |
application/api/controller/Goods.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace app\api\controller; | ||
5 | + | ||
6 | + | ||
7 | +use app\api\model\GoodsComment; | ||
8 | +use app\api\model\GoodsSpec; | ||
9 | +use app\api\model\GoodsSpecRel; | ||
10 | +use app\common\controller\Api; | ||
11 | +use think\Db; | ||
12 | + | ||
13 | +/** | ||
14 | + * 商品页面 | ||
15 | + */ | ||
16 | +class Goods extends Api | ||
17 | +{ | ||
18 | + protected $noNeedRight = ['*']; | ||
19 | + protected $noNeedLogin = ['*']; | ||
20 | + | ||
21 | + | ||
22 | + /** | ||
23 | + * @ApiTitle (商品详情) | ||
24 | + * @ApiMethod (POST) | ||
25 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
26 | + * @ApiParams (name=goods_id, type=integer, required=true, description="商品id") | ||
27 | + * @ApiReturn ({ | ||
28 | + 'code':'1', | ||
29 | + 'msg':'商品详情' | ||
30 | + 'data':{ | ||
31 | + "goods_id": 22,商品id | ||
32 | + "goods_name": "Mate 20 华为 HUAWEI ", | ||
33 | + "spec_type": "20", 10=单规格20=多规格 | ||
34 | + "brand": null, 品牌 | ||
35 | + "makefor": null, 进口国产 | ||
36 | + "packing": null, 包装方式 | ||
37 | + "keep": null, 保存条件 | ||
38 | + "number": null, 编号 | ||
39 | + "price_description": null, 价格说明 | ||
40 | + "sales_actual": 64, 销量 | ||
41 | + "price": "4499.00", 价格 | ||
42 | + "line_price": "0.00", 划线价 | ||
43 | + "images_text": [ | ||
44 | + 轮播图 | ||
45 | + ], | ||
46 | + "down_image_text": "底部图", | ||
47 | + "four_image_text": [ | ||
48 | + 四宫格图 | ||
49 | + ] | ||
50 | + } | ||
51 | + }) | ||
52 | + */ | ||
53 | + public function goodsDetail() | ||
54 | + { | ||
55 | + $goods_id = $this->request->post('goods_id'); | ||
56 | + $goodsmodel = new \app\api\model\Goods(); | ||
57 | + if (!is_numeric($goods_id)){ | ||
58 | + $this->error('商品id不合法'); | ||
59 | + } | ||
60 | + $goods = $goodsmodel::get($goods_id); | ||
61 | + $goods_spec = Db::name('litestore_goods_spec')->where('goods_id',$goods['goods_id'])->find(); | ||
62 | + $goods['price'] = $goods_spec['goods_price']; | ||
63 | + $goods['line_price'] = $goods_spec['line_price']; | ||
64 | + $this->success('商品详情',$goods); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * @ApiTitle (商品详情页评价) | ||
69 | + * @ApiMethod (POST) | ||
70 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
71 | + * @ApiParams (name=goods_id, type=integer, required=true, description="商品id") | ||
72 | + * @ApiReturn ({ | ||
73 | + 'code':'1', | ||
74 | + 'msg':'商品详情页评价' | ||
75 | + 'data':{ | ||
76 | + "comment_number": 1, 评价数量 | ||
77 | + "comment": { | ||
78 | + "id": 1, | ||
79 | + "user_id": null, | ||
80 | + "goods_id": 22, | ||
81 | + "comment": "12121212", 评论内容 | ||
82 | + "images": "1asdasd", | ||
83 | + "score": null, | ||
84 | + "createtime": null, | ||
85 | + "status": "normal", | ||
86 | + "images_text": [ | ||
87 | + 评价图片数组 | ||
88 | + "http://temporaryfood.com1asdasd" | ||
89 | + ] | ||
90 | + } | ||
91 | + "user": { | ||
92 | + "id": 1, | ||
93 | + "nickname": "admin", | ||
94 | + "avatar_text": "用户头像", | ||
95 | + } | ||
96 | + } | ||
97 | + }) | ||
98 | + */ | ||
99 | + public function goodsDetailComment() | ||
100 | + { | ||
101 | + $goods_id = $this->request->post('goods_id'); | ||
102 | + if (!is_numeric($goods_id)){ | ||
103 | + $this->error('商品id不合法'); | ||
104 | + } | ||
105 | + $model = new GoodsComment(); | ||
106 | + $goods = []; | ||
107 | + $goods['comment_number'] = $model->where('status','normal')->count(); | ||
108 | + $goods['comment'] = $model | ||
109 | + ->with(['user']) | ||
110 | + ->where('goods_id',$goods_id) | ||
111 | + ->where('status','normal') | ||
112 | + ->order('id','desc') | ||
113 | + ->find(); | ||
114 | + $goods['comment']->getRelation('user')->visible(['id','nickname']); | ||
115 | + $this->success('商品详情页评价',$goods); | ||
116 | + } | ||
117 | + | ||
118 | + | ||
119 | + /** | ||
120 | + * @ApiTitle (商品评价列表) | ||
121 | + * @ApiMethod (POST) | ||
122 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
123 | + * @ApiParams (name=goods_id, type=integer, required=true, description="商品id") | ||
124 | + * @ApiParams (name=page, type=integer, required=false, description="页数") | ||
125 | + * @ApiReturn ({ | ||
126 | + 'code':'1', | ||
127 | + 'msg':'返回成功' | ||
128 | + 'data':{ | ||
129 | + "total": 1, | ||
130 | + "per_page": 10, | ||
131 | + "current_page": 1, | ||
132 | + "last_page": 1, | ||
133 | + "data": [ | ||
134 | + { | ||
135 | + "id": 1, | ||
136 | + "user_id": 1, | ||
137 | + "goods_id": 22, | ||
138 | + "comment": "12121212", | ||
139 | + "images": "1asdasd", | ||
140 | + "score": null, | ||
141 | + "createtime": null, | ||
142 | + "status": "normal", | ||
143 | + "user": { | ||
144 | + "id": 1, | ||
145 | + "nickname": "admin", | ||
146 | + "avatar_text": "" | ||
147 | + }, | ||
148 | + "images_text": [ | ||
149 | + "http://temporaryfood.com1asdasd" | ||
150 | + ], | ||
151 | + "createtime_text": "" | ||
152 | + } | ||
153 | + ] | ||
154 | + } | ||
155 | + }) | ||
156 | + */ | ||
157 | + public function goodsComment() | ||
158 | + { | ||
159 | + $goods_id = $this->request->post('goods_id'); | ||
160 | + $page = $this->request->post('page'); | ||
161 | + $model = new \app\api\model\GoodsComment(); | ||
162 | + if (!is_numeric($goods_id)){ | ||
163 | + $this->error('商品id不合法'); | ||
164 | + } | ||
165 | + $lists = $model | ||
166 | + ->with(['user']) | ||
167 | + ->where('goods_id',$goods_id) | ||
168 | + ->order('id','desc') | ||
169 | + ->paginate(10,false,['page'=>$page]) | ||
170 | + ->each(function ($item,$key){ | ||
171 | + $item->getRelation('user')->visible(['id','nickname']); | ||
172 | + }); | ||
173 | + $this->success('商品规格',$lists); | ||
174 | + } | ||
175 | +} |
@@ -2,11 +2,15 @@ | @@ -2,11 +2,15 @@ | ||
2 | 2 | ||
3 | namespace app\api\controller; | 3 | namespace app\api\controller; |
4 | 4 | ||
5 | +use app\api\model\Category; | ||
6 | +use app\api\model\Goods; | ||
5 | use app\api\model\News; | 7 | use app\api\model\News; |
6 | use app\common\controller\Api; | 8 | use app\common\controller\Api; |
9 | +use think\Config; | ||
10 | +use think\Db; | ||
7 | 11 | ||
8 | /** | 12 | /** |
9 | - * 首页接口 | 13 | + * 首页 |
10 | */ | 14 | */ |
11 | class Index extends Api | 15 | class Index extends Api |
12 | { | 16 | { |
@@ -38,14 +42,122 @@ class Index extends Api | @@ -38,14 +42,122 @@ class Index extends Api | ||
38 | * @ApiReturn ({ | 42 | * @ApiReturn ({ |
39 | 'code':'1', | 43 | 'code':'1', |
40 | 'msg':'返回成功' | 44 | 'msg':'返回成功' |
41 | - 'data':'轮播图数组' | 45 | + 'data':[ |
46 | + { | ||
47 | + "id": 4, | ||
48 | + "name": "电子产品", | ||
49 | + "image": "https://her-family.oss-cn-qingdao.aliyuncs.com/addons_store_uploads/20181105/509af801726984aaa359b4bf249f5716.png", | ||
50 | + "image_text": "图片地址" | ||
51 | + }, | ||
52 | + { | ||
53 | + "id": 6, | ||
54 | + "name": "水果", | ||
55 | + "image": "https://her-family.oss-cn-qingdao.aliyuncs.com/addons_store_uploads/20181105/c83a0019dfa7a768037e98f02b70efd5.jpg", | ||
56 | + "image_text": "图片地址" | ||
57 | + } | ||
58 | + ] | ||
42 | }) | 59 | }) |
43 | */ | 60 | */ |
44 | public function category() | 61 | public function category() |
45 | { | 62 | { |
46 | 63 | ||
47 | - $model = new Cat(); | ||
48 | - $list = $model->where('status','normal')->column('image'); | ||
49 | - $this->success('banner',$list); | 64 | + $model = new Category(); |
65 | + $list = $model->where('is_index','1')->field('id,name,image')->limit(10)->select(); | ||
66 | + $this->success('首页分类',$list); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * @ApiTitle (首页活动&&通知文本) | ||
71 | + * @ApiMethod (POST) | ||
72 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
73 | + * @ApiReturn ({ | ||
74 | + 'code':'1', | ||
75 | + 'msg':'返回成功' | ||
76 | + 'data':{ | ||
77 | + "left": { | ||
78 | + "id": 1, | ||
79 | + "name": "新人用户", | ||
80 | + "place": "left" | ||
81 | + }, | ||
82 | + "rightTop": { | ||
83 | + "id": 2, | ||
84 | + "name": "限时秒杀", | ||
85 | + "place": "rightTop" | ||
86 | + }, | ||
87 | + "rightDown": { | ||
88 | + "id": 3, | ||
89 | + "name": "进口商品", | ||
90 | + "place": "rightDown" | ||
91 | + } | ||
92 | + "content": "首页通知文本" | ||
93 | + } | ||
94 | + }) | ||
95 | + */ | ||
96 | + public function activity() | ||
97 | + { | ||
98 | + $list = Db::name('activity')->select(); | ||
99 | + $data = []; | ||
100 | + foreach ($list as $key => $value){ | ||
101 | + if ($value['place'] == 'left'){ | ||
102 | + $data['left'] = $value; | ||
103 | + }elseif ($value['place'] == 'rightTop'){ | ||
104 | + $data['rightTop'] = $value; | ||
105 | + }else{ | ||
106 | + $data['rightDown'] = $value; | ||
107 | + } | ||
108 | + } | ||
109 | + $data['content'] = Config::get('site.notice'); | ||
110 | + $this->success('首页活动标题',$data); | ||
111 | + } | ||
112 | + | ||
113 | + | ||
114 | + /** | ||
115 | + * @ApiTitle (猜你喜欢) | ||
116 | + * @ApiMethod (POST) | ||
117 | + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") | ||
118 | + * @ApiParams (name=page, type=integer, required=false, description="页数 默认1") | ||
119 | + * @ApiReturn ({ | ||
120 | + 'code':'1', | ||
121 | + 'msg':'返回成功' | ||
122 | + 'data':{ | ||
123 | + "total": 4, | ||
124 | + "per_page": 10, | ||
125 | + "current_page": 1, | ||
126 | + "last_page": 1, | ||
127 | + "data": [ | ||
128 | + { | ||
129 | + "goods_id": 21, | ||
130 | + "goods_name": "小米Mix3", | ||
131 | + "image": null, | ||
132 | + "cart_number": 10, 购物车数量 | ||
133 | + "price": "100.00", 价格 | ||
134 | + "line_price": "1000.00", 划线价 | ||
135 | + "image_text": "图片地址" | ||
50 | } | 136 | } |
137 | + ] | ||
138 | + }) | ||
139 | + */ | ||
140 | + public function userLike() | ||
141 | + { | ||
142 | + $page = $this->request->post('page',1); | ||
143 | + $model = new Goods(); | ||
144 | + $list = $model->where('is_index','1') | ||
145 | + ->where('is_delete','0') | ||
146 | + ->where('goods_status','10') | ||
147 | + ->field('goods_id,goods_name,image') | ||
148 | + ->paginate(10,false,['page'=>$page]) | ||
149 | + ->each(function ($item,$key){ | ||
150 | + $item['cart_number'] = Db::name('cart') | ||
151 | + ->where('user_id',$this->auth->id) | ||
152 | + ->where('goods_id',$item['goods_id']) | ||
153 | + ->sum('number'); | ||
154 | + $goods_spec = Db::name('litestore_goods_spec') | ||
155 | + ->where('goods_id',$item['goods_id']) | ||
156 | + ->find(); | ||
157 | + $item['price'] = $goods_spec['goods_price']; | ||
158 | + $item['line_price'] = $goods_spec['line_price']; | ||
159 | + }); | ||
160 | + $this->success('猜你喜欢',$list); | ||
161 | + } | ||
162 | + | ||
51 | } | 163 | } |
application/api/model/Goods.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace app\api\model; | ||
5 | + | ||
6 | + | ||
7 | +use think\Model; | ||
8 | + | ||
9 | +class Goods extends Model | ||
10 | +{ | ||
11 | + protected $name = 'litestore_goods'; | ||
12 | + protected $append = [ | ||
13 | + 'image_text', | ||
14 | + 'images_text', | ||
15 | + 'down_image_text', | ||
16 | + 'four_image_text' | ||
17 | + ]; | ||
18 | + | ||
19 | + public function getImageTextAttr($value,$data) | ||
20 | + { | ||
21 | + $value = !empty($data['image']) ? cdnurl($data['image'],true):''; | ||
22 | + return $value; | ||
23 | + } | ||
24 | + | ||
25 | + public function getFourImageTextAttr($value,$data) | ||
26 | + { | ||
27 | + $value = !empty($data['four_image']) ? explode(',',$data['four_image']):[]; | ||
28 | + foreach ($value as $key => &$val){ | ||
29 | + $val = cdnurl($val,true); | ||
30 | + } | ||
31 | + return $value; | ||
32 | + } | ||
33 | + | ||
34 | + public function getImagesTextAttr($value,$data) | ||
35 | + { | ||
36 | + $value = !empty($data['images']) ? explode(',',$data['images']):[]; | ||
37 | + foreach ($value as $key => &$val){ | ||
38 | + $val = cdnurl($val,true); | ||
39 | + } | ||
40 | + return $value; | ||
41 | + } | ||
42 | + | ||
43 | + public function getDownImageTextAttr($value,$data) | ||
44 | + { | ||
45 | + $value = !empty($data['down_image']) ? cdnurl($data['down_image'],true):''; | ||
46 | + return $value; | ||
47 | + } | ||
48 | +} |
application/api/model/GoodsComment.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace app\api\model; | ||
5 | + | ||
6 | + | ||
7 | +use think\Model; | ||
8 | + | ||
9 | +class GoodsComment extends Model | ||
10 | +{ | ||
11 | + protected $append = [ | ||
12 | + 'images_text', | ||
13 | + 'createtime_text' | ||
14 | + ]; | ||
15 | + | ||
16 | + public function getImagesTextAttr($value,$data) | ||
17 | + { | ||
18 | + $value = !empty($data['images'])?explode(',',$data['images']):[]; | ||
19 | + foreach ($value as $key => &$val){ | ||
20 | + $val = cdnurl($val,true); | ||
21 | + } | ||
22 | + return $value; | ||
23 | + } | ||
24 | + | ||
25 | + public function getCreatetimeTextAttr($value,$data) | ||
26 | + { | ||
27 | + $value = !empty($data['createtime'])?date('Y-m-d',$data['createtime']):''; | ||
28 | + return $value; | ||
29 | + } | ||
30 | + | ||
31 | + public function user() | ||
32 | + { | ||
33 | + return $this->belongsTo('User','user_id','id'); | ||
34 | + } | ||
35 | +} |
application/api/model/GoodsSpec.php
0 → 100644
application/api/model/GoodsSpecRel.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace app\api\model; | ||
5 | + | ||
6 | + | ||
7 | +use think\Model; | ||
8 | + | ||
9 | +class GoodsSpecRel extends Model | ||
10 | +{ | ||
11 | + protected $name = 'litestore_goods_spec_rel'; | ||
12 | + | ||
13 | + public function spec() | ||
14 | + { | ||
15 | + return $this->belongsTo('Spec','spec_id','id'); | ||
16 | + } | ||
17 | + | ||
18 | + public function specvalue() | ||
19 | + { | ||
20 | + return $this->belongsTo('SpecValue','spec_value_id','id'); | ||
21 | + } | ||
22 | +} |
application/api/model/Spec.php
0 → 100644
application/api/model/SpecValue.php
0 → 100644
application/api/model/User.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | + | ||
4 | +namespace app\api\model; | ||
5 | + | ||
6 | + | ||
7 | +use think\Model; | ||
8 | + | ||
9 | +class User extends Model | ||
10 | +{ | ||
11 | + protected $append = [ | ||
12 | + 'avatar_text' | ||
13 | + ]; | ||
14 | + | ||
15 | + public function getAvatarTextAttr($value,$data) | ||
16 | + { | ||
17 | + $value = !empty($data['avatar'])?cdnurl($data['avatar'],true):''; | ||
18 | + return $value; | ||
19 | + } | ||
20 | +} |
@@ -4,6 +4,7 @@ namespace app\common\controller; | @@ -4,6 +4,7 @@ namespace app\common\controller; | ||
4 | 4 | ||
5 | use app\common\library\Auth; | 5 | use app\common\library\Auth; |
6 | use think\Config; | 6 | use think\Config; |
7 | +use think\Db; | ||
7 | use think\exception\HttpResponseException; | 8 | use think\exception\HttpResponseException; |
8 | use think\exception\ValidateException; | 9 | use think\exception\ValidateException; |
9 | use think\Hook; | 10 | use think\Hook; |
@@ -324,4 +325,55 @@ class Api | @@ -324,4 +325,55 @@ class Api | ||
324 | //刷新Token | 325 | //刷新Token |
325 | $this->request->token(); | 326 | $this->request->token(); |
326 | } | 327 | } |
328 | + | ||
329 | + /** | ||
330 | + * 获取秒杀时间段列表 | ||
331 | + * @return array | ||
332 | + */ | ||
333 | + protected function timeplot() | ||
334 | + { | ||
335 | + $time = time(); | ||
336 | + $data = Db::name('timeslot')->column('time'); | ||
337 | + foreach ($data as $key => $value){ | ||
338 | + $data[$key] = strtotime($value); | ||
339 | + } | ||
340 | + asort($data); | ||
341 | + $count = count($data); | ||
342 | + for ($i = 0,$j = 1;$i<$count-1,$j<$count;$i++,$j++){ | ||
343 | + if ($data[$i] <= $time && $data[$j] > $time){ | ||
344 | + $data[$i] = [ | ||
345 | + 'time'=>date('H:i',$data[$i]), | ||
346 | + 'status' => 'begin' | ||
347 | + ]; | ||
348 | + $data[$j] = [ | ||
349 | + 'time'=>date('H:i',$data[$j]), | ||
350 | + 'status' => 'will' | ||
351 | + ]; | ||
352 | + $i++;$j++; | ||
353 | + }elseif($data[$i] < $time){ | ||
354 | + $data[$i] = [ | ||
355 | + 'time'=>date('H:i',$data[$i]), | ||
356 | + 'status' => 'over' | ||
357 | + ]; | ||
358 | + }elseif($i==0&&$data[$i] > $time){ | ||
359 | + $data[$i] = [ | ||
360 | + 'time'=>date('H:i',$data[$i]), | ||
361 | + 'status' => 'will' | ||
362 | + ]; | ||
363 | + }else{ | ||
364 | + $data[$i] = [ | ||
365 | + 'time'=>date('H:i',$data[$i]), | ||
366 | + 'status' => 'not' | ||
367 | + ]; | ||
368 | + } | ||
369 | + if ($count-$j == 1){ | ||
370 | + $data[$j] = [ | ||
371 | + 'time'=>date('H:i',$data[$j]), | ||
372 | + 'status' => $data[$j] > $time ? 'not':'begin' | ||
373 | + ]; | ||
374 | + } | ||
375 | + } | ||
376 | + var_dump($data);exit(); | ||
377 | + return array_values($data); | ||
378 | + } | ||
327 | } | 379 | } |
@@ -43,4 +43,6 @@ return array ( | @@ -43,4 +43,6 @@ return array ( | ||
43 | ), | 43 | ), |
44 | 'user_agreement' => '<p>64645646564公开警告</p><p>;回来了框架</p>', | 44 | 'user_agreement' => '<p>64645646564公开警告</p><p>;回来了框架</p>', |
45 | 'privacy_agreement' => '<p>45315448</p><p>他房间后</p>', | 45 | 'privacy_agreement' => '<p>45315448</p><p>他房间后</p>', |
46 | + 'notice' => '阿达萨达萨达撒旦撒旦', | ||
47 | + 'advert' => '/assets/img/qrcode.png', | ||
46 | ); | 48 | ); |
public/assets/js/backend/command.js
0 → 100644
1 | +define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) { | ||
2 | + | ||
3 | + var Controller = { | ||
4 | + index: function () { | ||
5 | + // 初始化表格参数配置 | ||
6 | + Table.api.init({ | ||
7 | + extend: { | ||
8 | + index_url: 'command/index', | ||
9 | + add_url: 'command/add', | ||
10 | + edit_url: '', | ||
11 | + del_url: 'command/del', | ||
12 | + multi_url: 'command/multi', | ||
13 | + table: 'command', | ||
14 | + } | ||
15 | + }); | ||
16 | + | ||
17 | + var table = $("#table"); | ||
18 | + | ||
19 | + // 初始化表格 | ||
20 | + table.bootstrapTable({ | ||
21 | + url: $.fn.bootstrapTable.defaults.extend.index_url, | ||
22 | + pk: 'id', | ||
23 | + sortName: 'id', | ||
24 | + columns: [ | ||
25 | + [ | ||
26 | + {checkbox: true}, | ||
27 | + {field: 'id', title: __('Id')}, | ||
28 | + {field: 'type', title: __('Type'), formatter: Table.api.formatter.search}, | ||
29 | + {field: 'type_text', title: __('Type')}, | ||
30 | + { | ||
31 | + field: 'command', title: __('Command'), formatter: function (value, row, index) { | ||
32 | + return '<input type="text" class="form-control" value="' + value + '">'; | ||
33 | + } | ||
34 | + }, | ||
35 | + { | ||
36 | + field: 'executetime', | ||
37 | + title: __('Executetime'), | ||
38 | + operate: 'RANGE', | ||
39 | + addclass: 'datetimerange', | ||
40 | + formatter: Table.api.formatter.datetime | ||
41 | + }, | ||
42 | + { | ||
43 | + field: 'createtime', | ||
44 | + title: __('Createtime'), | ||
45 | + operate: 'RANGE', | ||
46 | + addclass: 'datetimerange', | ||
47 | + formatter: Table.api.formatter.datetime | ||
48 | + }, | ||
49 | + { | ||
50 | + field: 'updatetime', | ||
51 | + title: __('Updatetime'), | ||
52 | + operate: 'RANGE', | ||
53 | + addclass: 'datetimerange', | ||
54 | + formatter: Table.api.formatter.datetime | ||
55 | + }, | ||
56 | + { | ||
57 | + field: 'status', | ||
58 | + title: __('Status'), | ||
59 | + table: table, | ||
60 | + custom: {"successed": 'success', "failured": 'danger'}, | ||
61 | + searchList: {"successed": __('Successed'), "failured": __('Failured')}, | ||
62 | + formatter: Table.api.formatter.status | ||
63 | + }, | ||
64 | + { | ||
65 | + field: 'operate', | ||
66 | + title: __('Operate'), | ||
67 | + buttons: [ | ||
68 | + { | ||
69 | + name: 'execute', | ||
70 | + title: __('Execute again'), | ||
71 | + text: __('Execute again'), | ||
72 | + url: 'command/execute', | ||
73 | + icon: 'fa fa-repeat', | ||
74 | + classname: 'btn btn-success btn-xs btn-execute btn-ajax', | ||
75 | + success: function (data) { | ||
76 | + Layer.alert("<textarea class='form-control' cols='60' rows='5'>" + data.result + "</textarea>", { | ||
77 | + title: __("执行结果"), | ||
78 | + shadeClose: true | ||
79 | + }); | ||
80 | + table.bootstrapTable('refresh'); | ||
81 | + return false; | ||
82 | + } | ||
83 | + }, | ||
84 | + { | ||
85 | + name: 'execute', | ||
86 | + title: __('Detail'), | ||
87 | + text: __('Detail'), | ||
88 | + url: 'command/detail', | ||
89 | + icon: 'fa fa-list', | ||
90 | + classname: 'btn btn-info btn-xs btn-execute btn-dialog' | ||
91 | + } | ||
92 | + ], | ||
93 | + table: table, | ||
94 | + events: Table.api.events.operate, | ||
95 | + formatter: Table.api.formatter.operate | ||
96 | + } | ||
97 | + ] | ||
98 | + ] | ||
99 | + }); | ||
100 | + | ||
101 | + // 为表格绑定事件 | ||
102 | + Table.api.bindevent(table); | ||
103 | + }, | ||
104 | + add: function () { | ||
105 | + require(['bootstrap-select', 'bootstrap-select-lang']); | ||
106 | + var mainfields = []; | ||
107 | + var relationfields = {}; | ||
108 | + var maintable = []; | ||
109 | + var relationtable = []; | ||
110 | + var relationmode = ["belongsto", "hasone"]; | ||
111 | + | ||
112 | + var renderselect = function (select, data) { | ||
113 | + var html = []; | ||
114 | + for (var i = 0; i < data.length; i++) { | ||
115 | + html.push("<option value='" + data[i] + "'>" + data[i] + "</option>"); | ||
116 | + } | ||
117 | + $(select).html(html.join("")); | ||
118 | + select.trigger("change"); | ||
119 | + if (select.data("selectpicker")) { | ||
120 | + select.selectpicker('refresh'); | ||
121 | + } | ||
122 | + return select; | ||
123 | + }; | ||
124 | + | ||
125 | + $("select[name=table] option").each(function () { | ||
126 | + maintable.push($(this).val()); | ||
127 | + }); | ||
128 | + $(document).on('change', "input[name='isrelation']", function () { | ||
129 | + $("#relation-zone").toggleClass("hide", !$(this).prop("checked")); | ||
130 | + }); | ||
131 | + $(document).on('change', "select[name='table']", function () { | ||
132 | + var that = this; | ||
133 | + Fast.api.ajax({ | ||
134 | + url: "command/get_field_list", | ||
135 | + data: {table: $(that).val()}, | ||
136 | + }, function (data, ret) { | ||
137 | + mainfields = data.fieldlist; | ||
138 | + $("#relation-zone .relation-item").remove(); | ||
139 | + renderselect($("#fields"), mainfields); | ||
140 | + return false; | ||
141 | + }); | ||
142 | + return false; | ||
143 | + }); | ||
144 | + $(document).on('click', "a.btn-newrelation", function () { | ||
145 | + var that = this; | ||
146 | + var index = parseInt($(that).data("index")) + 1; | ||
147 | + var content = Template("relationtpl", {index: index}); | ||
148 | + content = $(content.replace(/\[index\]/, index)); | ||
149 | + $(this).data("index", index); | ||
150 | + $(content).insertBefore($(that).closest(".row")); | ||
151 | + $('select', content).selectpicker(); | ||
152 | + var exists = [$("select[name='table']").val()]; | ||
153 | + $("select.relationtable").each(function () { | ||
154 | + exists.push($(this).val()); | ||
155 | + }); | ||
156 | + relationtable = []; | ||
157 | + $.each(maintable, function (i, j) { | ||
158 | + if ($.inArray(j, exists) < 0) { | ||
159 | + relationtable.push(j); | ||
160 | + } | ||
161 | + }); | ||
162 | + renderselect($("select.relationtable", content), relationtable); | ||
163 | + $("select.relationtable", content).trigger("change"); | ||
164 | + }); | ||
165 | + $(document).on('click', "a.btn-removerelation", function () { | ||
166 | + $(this).closest(".row").remove(); | ||
167 | + }); | ||
168 | + $(document).on('change', "#relation-zone select.relationmode", function () { | ||
169 | + var table = $("select.relationtable", $(this).closest(".row")).val(); | ||
170 | + var that = this; | ||
171 | + Fast.api.ajax({ | ||
172 | + url: "command/get_field_list", | ||
173 | + data: {table: table}, | ||
174 | + }, function (data, ret) { | ||
175 | + renderselect($(that).closest(".row").find("select.relationprimarykey"), $(that).val() == 'belongsto' ? data.fieldlist : mainfields); | ||
176 | + renderselect($(that).closest(".row").find("select.relationforeignkey"), $(that).val() == 'hasone' ? data.fieldlist : mainfields); | ||
177 | + return false; | ||
178 | + }); | ||
179 | + }); | ||
180 | + $(document).on('change', "#relation-zone select.relationtable", function () { | ||
181 | + var that = this; | ||
182 | + Fast.api.ajax({ | ||
183 | + url: "command/get_field_list", | ||
184 | + data: {table: $(that).val()}, | ||
185 | + }, function (data, ret) { | ||
186 | + renderselect($(that).closest(".row").find("select.relationmode"), relationmode); | ||
187 | + renderselect($(that).closest(".row").find("select.relationfields"), mainfields) | ||
188 | + renderselect($(that).closest(".row").find("select.relationforeignkey"), data.fieldlist) | ||
189 | + renderselect($(that).closest(".row").find("select.relationfields"), data.fieldlist) | ||
190 | + return false; | ||
191 | + }); | ||
192 | + }); | ||
193 | + $(document).on('click', ".btn-command", function () { | ||
194 | + var form = $(this).closest("form"); | ||
195 | + var textarea = $("textarea[rel=command]", form); | ||
196 | + textarea.val(''); | ||
197 | + Fast.api.ajax({ | ||
198 | + url: "command/command/action/command", | ||
199 | + data: form.serialize(), | ||
200 | + }, function (data, ret) { | ||
201 | + textarea.val(data.command); | ||
202 | + return false; | ||
203 | + }); | ||
204 | + }); | ||
205 | + $(document).on('click', ".btn-execute", function () { | ||
206 | + var form = $(this).closest("form"); | ||
207 | + var textarea = $("textarea[rel=result]", form); | ||
208 | + textarea.val(''); | ||
209 | + Fast.api.ajax({ | ||
210 | + url: "command/command/action/execute", | ||
211 | + data: form.serialize(), | ||
212 | + }, function (data, ret) { | ||
213 | + textarea.val(data.result); | ||
214 | + window.parent.$(".toolbar .btn-refresh").trigger('click'); | ||
215 | + top.window.Fast.api.refreshmenu(); | ||
216 | + return false; | ||
217 | + }, function () { | ||
218 | + window.parent.$(".toolbar .btn-refresh").trigger('click'); | ||
219 | + }); | ||
220 | + }); | ||
221 | + $("select[name='table']").trigger("change"); | ||
222 | + Controller.api.bindevent(); | ||
223 | + }, | ||
224 | + edit: function () { | ||
225 | + Controller.api.bindevent(); | ||
226 | + }, | ||
227 | + api: { | ||
228 | + bindevent: function () { | ||
229 | + Form.api.bindevent($("form[role=form]")); | ||
230 | + } | ||
231 | + } | ||
232 | + }; | ||
233 | + return Controller; | ||
234 | +}); |
public/assets/js/backend/timeslot.js
0 → 100644
1 | +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { | ||
2 | + | ||
3 | + var Controller = { | ||
4 | + index: function () { | ||
5 | + // 初始化表格参数配置 | ||
6 | + Table.api.init({ | ||
7 | + extend: { | ||
8 | + index_url: 'timeslot/index' + location.search, | ||
9 | + add_url: 'timeslot/add', | ||
10 | + edit_url: 'timeslot/edit', | ||
11 | + // del_url: 'timeslot/del', | ||
12 | + multi_url: 'timeslot/multi', | ||
13 | + import_url: 'timeslot/import', | ||
14 | + table: 'timeslot', | ||
15 | + } | ||
16 | + }); | ||
17 | + | ||
18 | + var table = $("#table"); | ||
19 | + | ||
20 | + // 初始化表格 | ||
21 | + table.bootstrapTable({ | ||
22 | + url: $.fn.bootstrapTable.defaults.extend.index_url, | ||
23 | + pk: 'id', | ||
24 | + sortName: 'id', | ||
25 | + search:false, | ||
26 | + showSearch:false, | ||
27 | + showExport:false, | ||
28 | + columns: [ | ||
29 | + [ | ||
30 | + // {checkbox: true}, | ||
31 | + // {field: 'id', title: __('Id')}, | ||
32 | + {field: 'time', title: __('Time'), operate: 'LIKE'}, | ||
33 | + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} | ||
34 | + ] | ||
35 | + ] | ||
36 | + }); | ||
37 | + | ||
38 | + // 为表格绑定事件 | ||
39 | + Table.api.bindevent(table); | ||
40 | + }, | ||
41 | + add: function () { | ||
42 | + Controller.api.bindevent(); | ||
43 | + }, | ||
44 | + edit: function () { | ||
45 | + Controller.api.bindevent(); | ||
46 | + }, | ||
47 | + api: { | ||
48 | + bindevent: function () { | ||
49 | + Form.api.bindevent($("form[role=form]")); | ||
50 | + } | ||
51 | + } | ||
52 | + }; | ||
53 | + return Controller; | ||
54 | +}); |
-
请 注册 或 登录 后发表评论