From 5e17d3025b11112491b1128ad040d4968b3750df Mon Sep 17 00:00:00 2001 From: hant Date: Fri, 28 Feb 2025 20:24:38 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/command/.addonrc | 1 + addons/command/Command.php | 70 ++++ addons/command/config.php | 4 + addons/command/controller/Index.php | 15 + addons/command/info.ini | 10 + addons/command/install.sql | 12 + addons/command/library/Output.php | 28 ++ application/admin/controller/Command.php | 248 ++++++++++++ application/admin/controller/Order.php | 97 +++++ application/admin/lang/zh-cn/command.php | 16 + application/admin/lang/zh-cn/order.php | 61 +++ application/admin/model/Command.php | 59 +++ application/admin/model/Order.php | 77 ++++ application/admin/validate/Command.php | 27 ++ application/admin/validate/Order.php | 27 ++ application/admin/view/command/add.html | 420 +++++++++++++++++++++ application/admin/view/command/detail.html | 42 +++ application/admin/view/command/index.html | 25 ++ application/admin/view/order/add.html | 83 ++++ application/admin/view/order/edit.html | 245 ++++++++++++ application/admin/view/order/index.html | 46 +++ public/assets/js/backend/command.js | 234 ++++++++++++ public/assets/js/backend/order.js | 87 +++++ 23 files changed, 1934 insertions(+) create mode 100644 addons/command/.addonrc create mode 100755 addons/command/Command.php create mode 100755 addons/command/config.php create mode 100755 addons/command/controller/Index.php create mode 100644 addons/command/info.ini create mode 100755 addons/command/install.sql create mode 100755 addons/command/library/Output.php create mode 100644 application/admin/controller/Command.php create mode 100644 application/admin/controller/Order.php create mode 100644 application/admin/lang/zh-cn/command.php create mode 100644 application/admin/lang/zh-cn/order.php create mode 100644 application/admin/model/Command.php create mode 100644 application/admin/model/Order.php create mode 100644 application/admin/validate/Command.php create mode 100644 application/admin/validate/Order.php create mode 100644 application/admin/view/command/add.html create mode 100644 application/admin/view/command/detail.html create mode 100644 application/admin/view/command/index.html create mode 100644 application/admin/view/order/add.html create mode 100644 application/admin/view/order/edit.html create mode 100644 application/admin/view/order/index.html create mode 100644 public/assets/js/backend/command.js create mode 100644 public/assets/js/backend/order.js diff --git a/addons/command/.addonrc b/addons/command/.addonrc new file mode 100644 index 0000000..426decf --- /dev/null +++ b/addons/command/.addonrc @@ -0,0 +1 @@ +{"files":["application\/admin\/validate\/Command.php","application\/admin\/controller\/Command.php","application\/admin\/lang\/zh-cn\/command.php","application\/admin\/model\/Command.php","application\/admin\/view\/command\/index.html","application\/admin\/view\/command\/add.html","application\/admin\/view\/command\/detail.html","public\/assets\/js\/backend\/command.js"],"license":"regular","licenseto":"98870","licensekey":"z9dMrLGQoCK7qN0T mJHxiy1bfG0ZfYKrR3mi7w==","domains":["0.1"],"licensecodes":[],"validations":["cbeddc9996d1ba6c230fc0319ab4d521"],"menus":["command","command\/index","command\/add","command\/detail","command\/command","command\/execute","command\/del","command\/multi"]} \ No newline at end of file diff --git a/addons/command/Command.php b/addons/command/Command.php new file mode 100755 index 0000000..1bbb1e2 --- /dev/null +++ b/addons/command/Command.php @@ -0,0 +1,70 @@ + 'command', + 'title' => '在线命令管理', + 'icon' => 'fa fa-terminal', + 'sublist' => [ + ['name' => 'command/index', 'title' => '查看'], + ['name' => 'command/add', 'title' => '添加'], + ['name' => 'command/detail', 'title' => '详情'], + ['name' => 'command/command', 'title' => '生成并执行命令'], + ['name' => 'command/execute', 'title' => '再次执行命令'], + ['name' => 'command/del', 'title' => '删除'], + ['name' => 'command/multi', 'title' => '批量更新'], + ] + ] + ]; + Menu::create($menu); + return true; + } + + /** + * 插件卸载方法 + * @return bool + */ + public function uninstall() + { + Menu::delete('command'); + return true; + } + + /** + * 插件启用方法 + * @return bool + */ + public function enable() + { + Menu::enable('command'); + return true; + } + + /** + * 插件禁用方法 + * @return bool + */ + public function disable() + { + Menu::disable('command'); + return true; + } + +} diff --git a/addons/command/config.php b/addons/command/config.php new file mode 100755 index 0000000..b625128 --- /dev/null +++ b/addons/command/config.php @@ -0,0 +1,4 @@ +error("当前插件暂无前台页面"); + } + +} diff --git a/addons/command/info.ini b/addons/command/info.ini new file mode 100644 index 0000000..65cf366 --- /dev/null +++ b/addons/command/info.ini @@ -0,0 +1,10 @@ +name = command +title = 在线命令 +intro = 可在线执行一键生成CRUD、一键生成菜单等相关命令 +author = FastAdmin +website = https://www.fastadmin.net +version = 1.1.2 +state = 1 +url = http://127.0.0.1:8088/addons/command +license = regular +licenseto = 98870 diff --git a/addons/command/install.sql b/addons/command/install.sql new file mode 100755 index 0000000..c584dbc --- /dev/null +++ b/addons/command/install.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS `__PREFIX__command` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID', + `type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型', + `params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '参数', + `command` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '命令', + `content` text COMMENT '返回结果', + `executetime` bigint(16) UNSIGNED DEFAULT NULL COMMENT '执行时间', + `createtime` bigint(16) UNSIGNED DEFAULT NULL COMMENT '创建时间', + `updatetime` bigint(16) UNSIGNED DEFAULT NULL COMMENT '更新时间', + `status` enum('successed','failured') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'failured' COMMENT '状态', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '在线命令表'; diff --git a/addons/command/library/Output.php b/addons/command/library/Output.php new file mode 100755 index 0000000..aba7982 --- /dev/null +++ b/addons/command/library/Output.php @@ -0,0 +1,28 @@ +message[] = $message; + } + + public function getMessage() + { + return $this->message; + } + +} diff --git a/application/admin/controller/Command.php b/application/admin/controller/Command.php new file mode 100644 index 0000000..9c4cf45 --- /dev/null +++ b/application/admin/controller/Command.php @@ -0,0 +1,248 @@ +model = new \app\admin\model\Command; + $this->view->assign("statusList", $this->model->getStatusList()); + } + + /** + * 添加 + */ + public function add() + { + + $tableList = []; + $list = \think\Db::query("SHOW TABLES"); + foreach ($list as $key => $row) { + $tableList[reset($row)] = reset($row); + } + + $this->view->assign("tableList", $tableList); + return $this->view->fetch(); + } + + /** + * 获取字段列表 + * @internal + */ + public function get_field_list() + { + $dbname = Config::get('database.database'); + $prefix = Config::get('database.prefix'); + $table = $this->request->request('table'); + //从数据库中获取表字段信息 + $sql = "SELECT * FROM `information_schema`.`columns` " + . "WHERE TABLE_SCHEMA = ? AND table_name = ? " + . "ORDER BY ORDINAL_POSITION"; + //加载主表的列 + $columnList = Db::query($sql, [$dbname, $table]); + $fieldlist = []; + foreach ($columnList as $index => $item) { + $fieldlist[] = $item['COLUMN_NAME']; + } + $this->success("", null, ['fieldlist' => $fieldlist]); + } + + /** + * 获取控制器列表 + * @internal + */ + public function get_controller_list() + { + //搜索关键词,客户端输入以空格分开,这里接收为数组 + $word = (array)$this->request->request("q_word/a"); + $word = implode('', $word); + + $adminPath = dirname(__DIR__) . DS; + $controllerDir = $adminPath . 'controller' . DS; + $files = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY + ); + $list = []; + foreach ($files as $name => $file) { + if (!$file->isDir()) { + $filePath = $file->getRealPath(); + $name = str_replace($controllerDir, '', $filePath); + $name = str_replace(DS, "/", $name); + if (!preg_match("/(.*)\.php\$/", $name)) { + continue; + } + if (!$word || stripos($name, $word) !== false) { + $list[] = ['id' => $name, 'name' => $name]; + } + } + } + $pageNumber = $this->request->request("pageNumber"); + $pageSize = $this->request->request("pageSize"); + return json(['list' => array_slice($list, ($pageNumber - 1) * $pageSize, $pageSize), 'total' => count($list)]); + } + + /** + * 详情 + */ + public function detail($ids) + { + $row = $this->model->get($ids); + if (!$row) { + $this->error(__('No Results were found')); + } + $this->view->assign("row", $row); + return $this->view->fetch(); + } + + /** + * 执行 + */ + public function execute($ids) + { + $row = $this->model->get($ids); + if (!$row) { + $this->error(__('No Results were found')); + } + $result = $this->doexecute($row['type'], json_decode($row['params'], true)); + $this->success("", null, ['result' => $result]); + } + + /** + * 生成命令 + */ + public function command($action = '') + { + $commandtype = $this->request->request("commandtype"); + $params = $this->request->request(); + $allowfields = [ + 'crud' => 'table,controller,model,fields,force,local,delete,menu', + 'menu' => 'controller,delete,force', + 'min' => 'module,resource,optimize', + 'api' => 'url,module,output,template,force,title,author,class,language,addon', + ]; + $argv = []; + $allowfields = isset($allowfields[$commandtype]) ? explode(',', $allowfields[$commandtype]) : []; + $allowfields = array_filter(array_intersect_key($params, array_flip($allowfields))); + if (isset($params['local']) && !$params['local']) { + $allowfields['local'] = $params['local']; + } else { + unset($allowfields['local']); + } + foreach ($allowfields as $key => $param) { + $argv[] = "--{$key}=" . (is_array($param) ? implode(',', $param) : $param); + } + if ($commandtype == 'crud') { + $extend = 'setcheckboxsuffix,enumradiosuffix,imagefield,filefield,intdatesuffix,switchsuffix,citysuffix,selectpagesuffix,selectpagessuffix,ignorefields,sortfield,editorsuffix,headingfilterfield,tagsuffix,jsonsuffix,fixedcolumns'; + $extendArr = explode(',', $extend); + foreach ($params as $index => $item) { + if (in_array($index, $extendArr)) { + foreach (explode(',', $item) as $key => $value) { + if ($value) { + $argv[] = "--{$index}={$value}"; + } + } + } + } + $isrelation = (int)$this->request->request('isrelation'); + if ($isrelation && isset($params['relation'])) { + foreach ($params['relation'] as $index => $relation) { + foreach ($relation as $key => $value) { + $argv[] = "--{$key}=" . (is_array($value) ? implode(',', $value) : $value); + } + } + } + } else { + if ($commandtype == 'menu') { + if (isset($params['allcontroller']) && $params['allcontroller']) { + $argv[] = "--controller=all-controller"; + } else { + foreach (explode(',', $params['controllerfile']) as $index => $param) { + if ($param) { + $argv[] = "--controller=" . substr($param, 0, -4); + } + } + } + } else { + if ($commandtype == 'min') { + + } else { + if ($commandtype == 'api') { + + } else { + + } + } + } + } + if ($action == 'execute') { + if (stripos(implode(' ', $argv), '--controller=all-controller') !== false) { + $this->error("只允许在命令行执行该命令,执行前请做好菜单规则备份!!!"); + } + if (config('app_debug')) { + $result = $this->doexecute($commandtype, $argv); + $this->success("", null, ['result' => $result]); + } else { + $this->error("只允许在开发环境下执行命令"); + } + } else { + $this->success("", null, ['command' => "php think {$commandtype} " . implode(' ', $argv)]); + } + + return; + } + + protected function doexecute($commandtype, $argv) + { + if (!config('app_debug')) { + $this->error("只允许在开发环境下执行命令"); + } + if (preg_match("/([;\|&]+)/", implode(' ', $argv))) { + $this->error("不支持的命令参数"); + } + $commandName = "\\app\\admin\\command\\" . ucfirst($commandtype); + $input = new Input($argv); + $output = new \addons\command\library\Output(); + $command = new $commandName($commandtype); + $data = [ + 'type' => $commandtype, + 'params' => json_encode($argv), + 'command' => "php think {$commandtype} " . implode(' ', $argv), + 'executetime' => time(), + ]; + $this->model->save($data); + try { + $command->run($input, $output); + $result = implode("\n", $output->getMessage()); + $this->model->status = 'successed'; + } catch (Exception $e) { + $result = implode("\n", $output->getMessage()) . "\n"; + $result .= $e->getMessage(); + $this->model->status = 'failured'; + } + $result = trim($result); + $this->model->content = $result; + $this->model->save(); + return $result; + } + +} diff --git a/application/admin/controller/Order.php b/application/admin/controller/Order.php new file mode 100644 index 0000000..94d7899 --- /dev/null +++ b/application/admin/controller/Order.php @@ -0,0 +1,97 @@ +model = new \app\admin\model\Order; + $this->view->assign("statusList", $this->model->getStatusList()); + $this->view->assign("collectList", $this->model->getCollectList()); + $this->view->assign("dispatchTypeList", $this->model->getDispatchTypeList()); + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + + + public function index() + { + $this->request->filter(['strip_tags', 'trim']); + if (false === $this->request->isAjax()) { + return $this->view->fetch(); + } + //如果发送的来源是 Selectpage,则转发到 Selectpage + if ($this->request->request('keyField')) { + return $this->selectpage(); + } + [$where, $sort, $order, $offset, $limit] = $this->buildparams(); + $list = $this->model + ->where($where) + ->order($sort, $order) + ->paginate($limit); + $result = ['total' => $list->total(), 'rows' => $list->items()]; + return json($result); + } + + public function add() + { + if (false === $this->request->isPost()) { + return $this->view->fetch(); + } + $params = $this->request->post('row/a'); + if (empty($params)) { + $this->error(__('Parameter %s can not be empty', '')); + } + $params = $this->preExcludeFields($params); + + if ($this->dataLimit && $this->dataLimitFieldAutoFill) { + $params[$this->dataLimitField] = $this->auth->id; + } + dd($params); + $result = false; + Db::startTrans(); + try { + //是否采用模型验证 + if ($this->modelValidate) { + $name = str_replace("\\model\\", "\\validate\\", get_class($this->model)); + $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate; + $this->model->validateFailException()->validate($validate); + } + $result = $this->model->allowField(true)->save($params); + Db::commit(); + } catch (ValidateException|PDOException|Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if ($result === false) { + $this->error(__('No rows were inserted')); + } + $this->success(); + } +} diff --git a/application/admin/lang/zh-cn/command.php b/application/admin/lang/zh-cn/command.php new file mode 100644 index 0000000..b010250 --- /dev/null +++ b/application/admin/lang/zh-cn/command.php @@ -0,0 +1,16 @@ + 'ID', + 'Type' => '类型', + 'Params' => '参数', + 'Command' => '命令', + 'Content' => '返回结果', + 'Executetime' => '执行时间', + 'Createtime' => '创建时间', + 'Updatetime' => '更新时间', + 'Execute again' => '再次执行', + 'Successed' => '成功', + 'Failured' => '失败', + 'Status' => '状态' +]; diff --git a/application/admin/lang/zh-cn/order.php b/application/admin/lang/zh-cn/order.php new file mode 100644 index 0000000..0b1eaaf --- /dev/null +++ b/application/admin/lang/zh-cn/order.php @@ -0,0 +1,61 @@ + 'ID', + 'Order_no' => '订单号', + 'Customer' => '客户姓名', + 'Tel' => '客户电话', + 'Status' => '订单状态', + 'Status 10' => '未派单', + 'Set status to 10' => '设为未派单', + 'Status 20' => '已派单', + 'Set status to 20' => '设为已派单', + 'Status 30' => '已接单', + 'Set status to 30' => '设为已接单', + 'Status 40' => '处理中', + 'Set status to 40' => '设为处理中', + 'Status 50' => '已完成', + 'Set status to 50' => '设为已完成', + 'Status -10' => '取消', + 'Set status to -10' => '设为取消', + 'Status -20' => '作废', + 'Set status to -20' => '设为作废', + 'Status -30' => '已拒接', + 'Set status to -30' => '设为已拒接', + 'Area_id' => '地域', + 'Address' => '详细地址', + 'Work_tel_id' => '工作机', + 'Worker_id' => '师傅ID', + 'Source' => '订单来源', + 'Source_uid' => '来源UID', + 'Service_id' => '服务ID', + 'Service_title' => '服务名称', + 'Detail' => '订单详情', + 'Remark' => '订单备注', + 'Images' => '图片', + 'Collect' => '是否收藏', + 'Collect 0' => '否', + 'Collect 1' => '是', + 'Collect_remark' => '收藏备注', + 'Enter_admin_id' => '录单员ID', + 'Dispatch_admin_id' => '派单员ID', + 'Dispatch_type' => '派单方式', + 'Dispatch_type 10' => '线上手动', + 'Dispatch_type 11' => '线上自动', + 'Dispatch_type 20' => '线下', + 'Total' => '总收款', + 'Cost' => '成本', + 'Performance' => '绩效', + 'Sb_amount' => '垫付', + 'Real_amount' => '实付', + 'Cancel_reason_id' => '取消原因', + 'Cancel_detail' => '取消详情', + 'Abolish_reason_id' => '作废原因', + 'Abolish_detail' => '作废详情', + 'Create_time' => '录单时间', + 'Update_time' => '更新时间', + 'Payment_time' => '付款时间', + 'Finishe_time' => '完成时间', + 'Dispatch_time' => '派单时间', + 'Delete_time' => '删除时间' +]; diff --git a/application/admin/model/Command.php b/application/admin/model/Command.php new file mode 100644 index 0000000..adede4d --- /dev/null +++ b/application/admin/model/Command.php @@ -0,0 +1,59 @@ + __('Successed'), 'failured' => __('Failured')]; + } + + + public function getExecutetimeTextAttr($value, $data) + { + $value = $value ? $value : $data['executetime']; + return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; + } + + public function getTypeTextAttr($value, $data) + { + $value = $value ? $value : $data['type']; + $list = ['crud' => '一键生成CRUD', 'menu' => '一键生成菜单', 'min' => '一键压缩打包', 'api' => '一键生成文档']; + return $list[$value] ?? ''; + } + + public function getStatusTextAttr($value, $data) + { + $value = $value ? $value : $data['status']; + $list = $this->getStatusList(); + return $list[$value] ?? ''; + } + + protected function setExecutetimeAttr($value) + { + return $value && !is_numeric($value) ? strtotime($value) : $value; + } + + +} diff --git a/application/admin/model/Order.php b/application/admin/model/Order.php new file mode 100644 index 0000000..dca32ee --- /dev/null +++ b/application/admin/model/Order.php @@ -0,0 +1,77 @@ + __('Status 10'), '20' => __('Status 20'), '30' => __('Status 30'), '40' => __('Status 40'), '50' => __('Status 50'), '-10' => __('Status -10'), '-20' => __('Status -20'), '-30' => __('Status -30')]; + } + + public function getCollectList() + { + return ['0' => __('Collect 0'), '1' => __('Collect 1')]; + } + + public function getDispatchTypeList() + { + return ['10' => __('Dispatch_type 10'), '11' => __('Dispatch_type 11'), '20' => __('Dispatch_type 20')]; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ?: ($data['status'] ?? ''); + $list = $this->getStatusList(); + return $list[$value] ?? ''; + } + + + public function getCollectTextAttr($value, $data) + { + $value = $value ?: ($data['collect'] ?? ''); + $list = $this->getCollectList(); + return $list[$value] ?? ''; + } + + + public function getDispatchTypeTextAttr($value, $data) + { + $value = $value ?: ($data['dispatch_type'] ?? ''); + $list = $this->getDispatchTypeList(); + return $list[$value] ?? ''; + } + + + + +} diff --git a/application/admin/validate/Command.php b/application/admin/validate/Command.php new file mode 100644 index 0000000..9da8fa6 --- /dev/null +++ b/application/admin/validate/Command.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/admin/validate/Order.php b/application/admin/validate/Order.php new file mode 100644 index 0000000..e0565c2 --- /dev/null +++ b/application/admin/validate/Order.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/admin/view/command/add.html b/application/admin/view/command/add.html new file mode 100644 index 0000000..9374529 --- /dev/null +++ b/application/admin/view/command/add.html @@ -0,0 +1,420 @@ + +
+ +
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ 主表设置 +
+
+ + {:build_select('table',$tableList,null,['class'=>'form-control selectpicker', 'data-live-search'=>'true']);} +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ +
+ 关联表设置 + + +
+ +
+
+ 字段识别设置 (与之匹配的字段都将生成相应组件) +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ +
+ +
+ 生成命令行 + +
+ +
+ 返回结果 + +
+ +
+ + +
+ +
+
+
+
+ +
+
+
+
+ +
+ 基础设置 +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ 生成命令行 + +
+ +
+ 返回结果 + +
+ +
+ + +
+ +
+
+
+
+
+
+
+
+ +
+
+
+ + +
+
+
+
+ 文档设置 +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ 生成命令行 + +
+ +
+ 返回结果 + +
+ +
+ + +
+ +
+
+
+
+
+
+
+ diff --git a/application/admin/view/command/detail.html b/application/admin/view/command/detail.html new file mode 100644 index 0000000..71ae036 --- /dev/null +++ b/application/admin/view/command/detail.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{:__('Title')}{:__('Content')}
{:__('Type')}{$row.type}({$row.type_text})
{:__('Params')}{$row.params|htmlentities}
{:__('Command')}{$row.command|htmlentities}
{:__('Content')} + +
{:__('Executetime')}{$row.executetime|datetime}
{:__('Status')}{$row.status_text}
+ \ No newline at end of file diff --git a/application/admin/view/command/index.html b/application/admin/view/command/index.html new file mode 100644 index 0000000..3b4f823 --- /dev/null +++ b/application/admin/view/command/index.html @@ -0,0 +1,25 @@ +
+ {:build_heading()} + +
+
+
+ +
+ +
+
+
diff --git a/application/admin/view/order/add.html b/application/admin/view/order/add.html new file mode 100644 index 0000000..19e2220 --- /dev/null +++ b/application/admin/view/order/add.html @@ -0,0 +1,83 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+ +
+ + +
+ +
+
    +
    +
    + +
    diff --git a/application/admin/view/order/edit.html b/application/admin/view/order/edit.html new file mode 100644 index 0000000..cbb1e00 --- /dev/null +++ b/application/admin/view/order/edit.html @@ -0,0 +1,245 @@ +
    + +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    + {foreach name="statusList" item="vo"} + + {/foreach} +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + +
    + + +
    + +
    +
      +
      +
      +
      + +
      + + + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + + + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      + +
      diff --git a/application/admin/view/order/index.html b/application/admin/view/order/index.html new file mode 100644 index 0000000..7209a05 --- /dev/null +++ b/application/admin/view/order/index.html @@ -0,0 +1,46 @@ +
      + +
      + {:build_heading(null,FALSE)} + +
      + + +
      +
      +
      +
      +
      + + {:__('Add')} + {:__('Edit')} + {:__('Delete')} + + + + + +
      + +
      +
      +
      + +
      +
      +
      diff --git a/public/assets/js/backend/command.js b/public/assets/js/backend/command.js new file mode 100644 index 0000000..3df5515 --- /dev/null +++ b/public/assets/js/backend/command.js @@ -0,0 +1,234 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'command/index', + add_url: 'command/add', + edit_url: '', + del_url: 'command/del', + multi_url: 'command/multi', + table: 'command', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'type', title: __('Type'), formatter: Table.api.formatter.search}, + {field: 'type_text', title: __('Type')}, + { + field: 'command', title: __('Command'), renderDefault: false, formatter: function (value, row, index) { + return ''; + } + }, + { + field: 'executetime', + title: __('Executetime'), + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'createtime', + title: __('Createtime'), + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'updatetime', + title: __('Updatetime'), + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'status', + title: __('Status'), + table: table, + custom: {"successed": 'success', "failured": 'danger'}, + searchList: {"successed": __('Successed'), "failured": __('Failured')}, + formatter: Table.api.formatter.status + }, + { + field: 'operate', + title: __('Operate'), + buttons: [ + { + name: 'execute', + title: __('Execute again'), + text: __('Execute again'), + url: 'command/execute', + icon: 'fa fa-repeat', + classname: 'btn btn-success btn-xs btn-execute btn-ajax', + success: function (data) { + Layer.alert("", { + title: __("执行结果"), + shadeClose: true + }); + table.bootstrapTable('refresh'); + return false; + } + }, + { + name: 'execute', + title: __('Detail'), + text: __('Detail'), + url: 'command/detail', + icon: 'fa fa-list', + classname: 'btn btn-info btn-xs btn-execute btn-dialog' + } + ], + table: table, + events: Table.api.events.operate, + formatter: Table.api.formatter.operate + } + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + require(['bootstrap-select', 'bootstrap-select-lang']); + var mainfields = []; + var relationfields = {}; + var maintable = []; + var relationtable = []; + var relationmode = ["belongsto", "hasone"]; + + var renderselect = function (select, data) { + var html = []; + for (var i = 0; i < data.length; i++) { + html.push(""); + } + $(select).html(html.join("")); + select.trigger("change"); + if (select.data("selectpicker")) { + select.selectpicker('refresh'); + } + return select; + }; + + $("select[name=table] option").each(function () { + maintable.push($(this).val()); + }); + $(document).on('change', "input[name='isrelation']", function () { + $("#relation-zone").toggleClass("hide", !$(this).prop("checked")); + }); + $(document).on('change', "select[name='table']", function () { + var that = this; + Fast.api.ajax({ + url: "command/get_field_list", + data: {table: $(that).val()}, + }, function (data, ret) { + mainfields = data.fieldlist; + $("#relation-zone .relation-item").remove(); + renderselect($("#fields"), mainfields); + return false; + }); + return false; + }); + $(document).on('click', "a.btn-newrelation", function () { + var that = this; + var index = parseInt($(that).data("index")) + 1; + var content = Template("relationtpl", {index: index}); + content = $(content.replace(/\[index\]/, index)); + $(this).data("index", index); + $(content).insertBefore($(that).closest(".row")); + $('select', content).selectpicker(); + var exists = [$("select[name='table']").val()]; + $("select.relationtable").each(function () { + exists.push($(this).val()); + }); + relationtable = []; + $.each(maintable, function (i, j) { + if ($.inArray(j, exists) < 0) { + relationtable.push(j); + } + }); + renderselect($("select.relationtable", content), relationtable); + $("select.relationtable", content).trigger("change"); + }); + $(document).on('click', "a.btn-removerelation", function () { + $(this).closest(".row").remove(); + }); + $(document).on('change', "#relation-zone select.relationmode", function () { + var table = $("select.relationtable", $(this).closest(".row")).val(); + var that = this; + Fast.api.ajax({ + url: "command/get_field_list", + data: {table: table}, + }, function (data, ret) { + renderselect($(that).closest(".row").find("select.relationprimarykey"), $(that).val() == 'belongsto' ? data.fieldlist : mainfields); + renderselect($(that).closest(".row").find("select.relationforeignkey"), $(that).val() == 'hasone' ? data.fieldlist : mainfields); + return false; + }); + }); + $(document).on('change', "#relation-zone select.relationtable", function () { + var that = this; + Fast.api.ajax({ + url: "command/get_field_list", + data: {table: $(that).val()}, + }, function (data, ret) { + renderselect($(that).closest(".row").find("select.relationmode"), relationmode); + renderselect($(that).closest(".row").find("select.relationfields"), mainfields) + renderselect($(that).closest(".row").find("select.relationforeignkey"), data.fieldlist) + renderselect($(that).closest(".row").find("select.relationfields"), data.fieldlist) + return false; + }); + }); + $(document).on('click', ".btn-command", function () { + var form = $(this).closest("form"); + var textarea = $("textarea[rel=command]", form); + textarea.val(''); + Fast.api.ajax({ + url: "command/command/action/command", + data: form.serialize(), + }, function (data, ret) { + textarea.val(data.command); + return false; + }); + }); + $(document).on('click', ".btn-execute", function () { + var form = $(this).closest("form"); + var textarea = $("textarea[rel=result]", form); + textarea.val(''); + Fast.api.ajax({ + url: "command/command/action/execute", + data: form.serialize(), + }, function (data, ret) { + textarea.val(data.result); + window.parent.$(".toolbar .btn-refresh").trigger('click'); + top.window.Fast.api.refreshmenu(); + return false; + }, function () { + window.parent.$(".toolbar .btn-refresh").trigger('click'); + }); + }); + $("select[name='table']").trigger("change"); + Controller.api.bindevent(); + }, + edit: function () { + Controller.api.bindevent(); + }, + api: { + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +}); diff --git a/public/assets/js/backend/order.js b/public/assets/js/backend/order.js new file mode 100644 index 0000000..b5d2144 --- /dev/null +++ b/public/assets/js/backend/order.js @@ -0,0 +1,87 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'order/index' + location.search, + add_url: 'order/add', + edit_url: 'order/edit', + del_url: 'order/del', + multi_url: 'order/multi', + import_url: 'order/import', + table: 'order', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + fixedColumns: true, + fixedRightNumber: 1, + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'order_no', title: __('Order_no'), operate: 'LIKE'}, + {field: 'customer', title: __('Customer'), operate: 'LIKE'}, + {field: 'tel', title: __('Tel'), operate: 'LIKE'}, + {field: 'status', title: __('Status'), searchList: {"10":__('Status 10'),"20":__('Status 20'),"30":__('Status 30'),"40":__('Status 40'),"50":__('Status 50'),"-10":__('Status -10'),"-20":__('Status -20'),"-30":__('Status -30')}, formatter: Table.api.formatter.status}, + {field: 'area_id', title: __('Area_id')}, + {field: 'address', title: __('Address'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'work_tel_id', title: __('Work_tel_id')}, + {field: 'worker_id', title: __('Worker_id')}, + {field: 'source', title: __('Source')}, + {field: 'source_uid', title: __('Source_uid'), operate: 'LIKE'}, + {field: 'service_id', title: __('Service_id')}, + {field: 'service_title', title: __('Service_title'), operate: 'LIKE'}, + {field: 'detail', title: __('Detail'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'remark', title: __('Remark'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'images', title: __('Images'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.images}, + {field: 'collect', title: __('Collect'), searchList: {"0":__('Collect 0'),"1":__('Collect 1')}, formatter: Table.api.formatter.normal}, + {field: 'collect_remark', title: __('Collect_remark'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'enter_admin_id', title: __('Enter_admin_id')}, + {field: 'dispatch_admin_id', title: __('Dispatch_admin_id')}, + {field: 'dispatch_type', title: __('Dispatch_type'), searchList: {"10":__('Dispatch_type 10'),"11":__('Dispatch_type 11'),"20":__('Dispatch_type 20')}, formatter: Table.api.formatter.normal}, + {field: 'total', title: __('Total'), operate:'BETWEEN'}, + {field: 'cost', title: __('Cost'), operate:'BETWEEN'}, + {field: 'performance', title: __('Performance'), operate:'BETWEEN'}, + {field: 'sb_amount', title: __('Sb_amount'), operate:'BETWEEN'}, + {field: 'real_amount', title: __('Real_amount'), operate:'BETWEEN'}, + {field: 'cancel_reason_id', title: __('Cancel_reason_id')}, + {field: 'cancel_detail', title: __('Cancel_detail'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'abolish_reason_id', title: __('Abolish_reason_id')}, + {field: 'abolish_detail', title: __('Abolish_detail'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'create_time', title: __('Create_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'update_time', title: __('Update_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'payment_time', title: __('Payment_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'finishe_time', title: __('Finishe_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'dispatch_time', title: __('Dispatch_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'delete_time', title: __('Delete_time'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + add: function () { + Controller.api.bindevent(); + }, + edit: function () { + Controller.api.bindevent(); + }, + api: { + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +});