diff --git a/application/admin/controller/Coupons.php b/application/admin/controller/Coupons.php new file mode 100644 index 0000000..98120a7 --- /dev/null +++ b/application/admin/controller/Coupons.php @@ -0,0 +1,38 @@ +model = new \app\admin\model\Coupons; + $this->view->assign("discountTypeList", $this->model->getDiscountTypeList()); + $this->view->assign("statusList", $this->model->getStatusList()); + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + +} diff --git a/application/admin/controller/Item.php b/application/admin/controller/Item.php index a81d21a..f841937 100644 --- a/application/admin/controller/Item.php +++ b/application/admin/controller/Item.php @@ -38,16 +38,37 @@ class Item extends Backend { if ($this->request->isAjax()) { // 必须将结果集转换为数组 - $ruleList = \think\Db::name("item") - ->where('status',1) - ->field('id,pid,level,title,key_word,sort,status') - ->order('sort DESC,id ASC')->select(); + $search = request()->get('search') ?? false; +// dd($where); + $build = Db::name('item') + ->where('status',1); + if ($search){ + $build->where(function ($query) use ($search){ + $query->where('title','like','%'.$search.'%') + ->whereOr('key_word','like','%'.$search.'%'); + }); + } + + $ruleList = $build->field('id,pid,level,title,key_word,sort,status') +// ->order('sort','desc') +// ->fetchSql(true) + ->select(); + if ($search){ + $pids = array_column($ruleList,'pid') ; + $pidData = Db::name('item') + ->where('status',1)->whereIn('id',$pids) + ->field('id,pid,level,title,key_word,sort,status')->select(); + $ruleList = array_values(array_reduce(array_merge($ruleList,$pidData), function ($carry, $item) { + $carry[$item['id']] = $item; + return $carry; + }, [])); + } Tree::instance()->init($ruleList)->icon = ['    ', '    ', '    ']; -// dd($ruleList); +// dd($ruleList); $this->itemdata = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title'); foreach ($this->itemdata as &$v) { - $v['status'] = $v['status'] ?'normal' : ''; + $v['status'] = $v['status'] ?'normal' : 'hidden'; } unset($v); diff --git a/application/admin/controller/Order.php b/application/admin/controller/Order.php index 9e374fb..acb7658 100644 --- a/application/admin/controller/Order.php +++ b/application/admin/controller/Order.php @@ -3,6 +3,7 @@ namespace app\admin\controller; use app\common\controller\Backend; +use fast\Tree; use think\Db; use think\exception\PDOException; use think\exception\ValidateException; @@ -20,12 +21,77 @@ class Order extends Backend * @var \app\admin\model\Order */ protected $model = null; - + protected $sources = null; + protected $items = null; public function _initialize() { parent::_initialize(); $this->model = new \app\admin\model\Order; $this->view->assign("statusList", $this->model->getStatusList()); + + $sources = Db::name('source') + ->where('status',1) + ->field(['id','title','key_word','pid']) + ->order('pid','asc') + ->order('sort','desc') + ->select(); + $this->sources = $sources; + $filtered = array_filter($sources, function($item) { + return $item['pid'] == 0; + }); + + $pid_map = array_column($filtered,null,'id'); + $res = []; + foreach ($sources as $item){ + if ($item['pid'] != 0 && isset($pid_map[$item['pid']])){ + $res [] = [ + ...$item,'ptitle' => $pid_map[$item['pid']]['title'] + ]; + } + } +// dd($res); + +// Tree::instance()->init($sources); +// $data = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title'); +// dd($data); + + $items = Db::name('item') + ->where('status',1) + ->field(['id','title','key_word','pid']) + ->order('pid','asc') + ->order('sort','desc') + ->select(); + + $phones = Db::name('phones') + ->where('assigned_user',$this->auth->id) + ->field(['id','model','phone_number']) + ->select(); + + $this->items = $items; + $filtered = array_filter($items, function($item) { + return $item['pid'] == 0; + }); + + $pid_map = array_column($filtered,null,'id'); + $res_items = []; + foreach ($items as $item){ + if ($item['pid'] != 0 && isset($pid_map[$item['pid']])){ + $res_items [] = [ + ...$item,'ptitle' => $pid_map[$item['pid']]['title'] + ]; + } + } + + $coupons = Db::name('coupons') + ->where('status','active') + ->field(['id','code','description']) + ->select(); + + $this->view->assign("statusList", $this->model->getStatusList()); + $this->view->assign("sources", $res); + $this->view->assign("coupons", $coupons); + $this->view->assign("items", $res_items); + $this->view->assign("phones", $phones); //$this->view->assign("collectList", $this->model->getCollectList()); //$this->view->assign("dispatchTypeList", $this->model->getDispatchTypeList()); } @@ -52,10 +118,17 @@ class Order extends Backend } [$where, $sort, $order, $offset, $limit] = $this->buildparams(); $list = $this->model - ->field(['id','order_no','customer','tel','status','area_id','address', - 'source','source_uid','source','item_title','item_id', + ->field(['id','order_no','user_id','customer','tel','status','area_id','address', + 'source','source_shop','source_uid','source','item_title','item_id','work_tel_id', 'detail','remark','images','create_time','update_time']) ->where($where) + ->with(['user' => function($q){ + $q->field('id,nickname'); + },'area' => function($q){ + $q->field('id,area_code,merge_name'); + },'phone' => function($q){ + $q->field('id,model'); + }]) ->order($sort, $order) ->paginate($limit); $result = ['total' => $list->total(), 'rows' => $list->items()]; @@ -86,7 +159,13 @@ class Order extends Backend $this->model->validateFailException()->validate($validate); } - $params['enter_admin_id'] = $this->auth->id; + $sources = $this->sources; + $items = $this->items; + $sources = array_column($sources,'title','id'); + $items = array_column($items,'title','id'); + $params['source_shop'] = $sources[$params['source']] ?? null; + $params['item_title'] = $items[$params['item_id']] ?? null; + $params['user_id'] = $this->auth->id; $params['status'] = 10; $params['order_no'] = $this->generateOrderNumber(); $params['create_time'] = date('Y-m-d H:i:s'); @@ -127,10 +206,27 @@ class Order extends Backend // 判断是否为POST请求,进行更新操作 if (request()->isPost()) { // 获取表单提交的数据 - $data = input('post.row/a'); - $data['update_time'] = date('Y-m-d H:i:s'); + $params = input('post.row/a'); + $params['update_time'] = date('Y-m-d H:i:s'); + $sources = $this->sources; + $sources = array_column($sources,'title','id'); +// $data['user_id'] = $this->auth->id; + $params['source_shop'] = $sources[$params['source']] ?? null; + + $sources = $this->sources; + $items = $this->items; + + $sources = array_column($sources,'title','id'); + $items = array_column($items,'title','id'); + + $params['source_shop'] = $sources[$params['source']] ?? null; + $params['item_title'] = $items[$params['item_id']] ?? null; + + $params['create_time'] = date('Y-m-d H:i:s'); + $params['update_time'] = date('Y-m-d H:i:s'); + // 更新订单信息 - $order->save($data); + $order->save($params); // 返回成功信息 $this->success('更新成功', 'index'); @@ -138,7 +234,7 @@ class Order extends Backend $area = new \app\admin\model\Area(); $area_name = $area->getNameByCode($order->area_id); $order->area_name = $area_name; - +// dd($area_name); // 将订单数据传递到视图 $this->assign('row', $order); diff --git a/application/admin/controller/Phones.php b/application/admin/controller/Phones.php new file mode 100644 index 0000000..c5c7f44 --- /dev/null +++ b/application/admin/controller/Phones.php @@ -0,0 +1,160 @@ +model = new \app\admin\model\Phones; + + $users = Db::name('admin') +// ->where('status',1) + ->field(['id','nickname']) + ->select(); + $this->view->assign("statusList", $this->model->getStatusList()); + $this->view->assign("users", $users); + + + } + + + + /** + * 默认生成的控制器所继承的父类中有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) + ->with(['user' => function($q){ + $q->field('id,nickname'); + }]) + ->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; + } + $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); + } + if ($params['assigned_user'] != 0){ + $params['status'] = 'assigned'; + $params['assigned_date'] = date('Y-m-d H:i:s'); + }else{ + $params['status'] = 'available'; + $params['assigned_date'] = null; + } + + + $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(); + } + + public function edit($ids = null) + { + if (!$ids) { + if (request()->isPost()){ + $ids = input('id'); + if (!$ids){ + $this->error('缺少订单ID'); + } + }else{ + $this->error('缺少订单ID'); + } + } + + // 获取当前ID对应的订单信息 + $order = $this->model->get($ids); + if (!$order) { + $this->error('订单不存在'); + } + + // 判断是否为POST请求,进行更新操作 + if (request()->isPost()) { + // 获取表单提交的数据 + $data = input('post.row/a'); + + if ($data['assigned_user'] != 0){ + $data['status'] = 'assigned'; + $data['assigned_date'] = date('Y-m-d H:i:s'); + }else{ + $data['status'] = 'available'; + $data['assigned_date'] = null; + } + // 更新订单信息 + $order->save($data); + + // 返回成功信息 + $this->success('更新成功', 'index'); + } + // 将订单数据传递到视图 + $this->assign('row', $order); + + // 渲染编辑页面 + return $this->fetch(); + } + +} diff --git a/application/admin/controller/Source.php b/application/admin/controller/Source.php new file mode 100644 index 0000000..09e41be --- /dev/null +++ b/application/admin/controller/Source.php @@ -0,0 +1,237 @@ +model = new \app\admin\model\Source; + $this->view->assign("statusList", $this->model->getStatusList()); + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + public function index() + { + if ($this->request->isAjax()) { + // 必须将结果集转换为数组 + $search = request()->get('search') ?? false; +// dd($where); + $build = Db::name('source') + ->where('status',1); + if ($search){ + $build->where(function ($query) use ($search){ + $query->where('title','like','%'.$search.'%') + ->whereOr('key_word','like','%'.$search.'%'); + }); + } + + $ruleList = $build->field('id,pid,level,title,key_word,sort,status') +// ->order('sort','desc') +// ->fetchSql(true) + ->select(); + if ($search){ + $pids = array_column($ruleList,'pid') ; + $pidData = Db::name('source') + ->where('status',1)->whereIn('id',$pids) + ->field('id,pid,level,title,key_word,sort,status')->select(); + $ruleList = array_values(array_reduce(array_merge($ruleList,$pidData), function ($carry, $source) { + $carry[$source['id']] = $source; + return $carry; + }, [])); + } + + Tree::instance()->init($ruleList)->icon = ['    ', '    ', '    ']; +// dd($ruleList); + $this->sourcedata = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title'); + foreach ($this->sourcedata as &$v) { + $v['status'] = $v['status'] ?'normal' : 'aqua'; + } + unset($v); + + $list = $this->sourcedata; + $total = count($this->sourcedata); + $result = array("total" => $total, "rows" => $list); + + return json($result); + } + return $this->view->fetch(); + } + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + public function add() + { + if (false === $this->request->isPost()) { + // 必须将结果集转换为数组 + $ruleList = \think\Db::name("source") + ->where('pid',0) + ->field('id,pid,level,title,key_word') + ->order('sort DESC,id ASC')->select(); + + Tree::instance()->init($ruleList)->icon = ['    ', '    ', '    ']; +// dd($ruleList); + $this->sourcedata = Tree::instance()->getTreeList(Tree::instance() + ->getTreeArray(0), 'title'); + $sourcedata = [0 => __('None')]; + foreach ($this->sourcedata as $k => $v) { + $sourcedata[$v['id']] = $v['title']; + unset($v['spacer']); + } + unset($v); + + $this->view->assign('sourcedata', $sourcedata); + 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; + } + $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); + } + + $pid = $params['pid']; + if ($pid > 0){ + $parent = $this->model->where('id',$pid)->find(); + if ($parent){ + $params['level'] = $parent->value('level') + 1; + } + }else{ + $params['level'] = 0; + } + + + $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(); + } + + public function search(){ + + $keyword = request()->get('keyword'); + if (!$keyword){ + $this->success(data:[]); + }else{ + $data = model('source') + ->where('level','=',2) + ->where(function ($query)use ($keyword){ + $query->where('title','like','%'.$keyword.'%') + ->whereOr('key_word', 'like', "%{$keyword}%"); + }) + ->order('level','desc') + ->field('title,id,key_word') + ->limit(0,10) + ->select(); + $this->success(data:$data); + } + + } + + public function edit($ids = null) + { + $row = $this->model->get($ids); + if (!$row) { + $this->error(__('No Results were found')); + } + $adminIds = $this->getDataLimitAdminIds(); + if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) { + $this->error(__('You have no permission')); + } + if (false === $this->request->isPost()) { + // 必须将结果集转换为数组 + $ruleList = \think\Db::name("source") + ->where('pid',0) + ->field('id,pid,level,title,key_word') + ->order('sort DESC,id ASC')->select(); + + Tree::instance()->init($ruleList)->icon = ['    ', '    ', '    ']; +// dd($ruleList); + $this->sourcedata = Tree::instance()->getTreeList(Tree::instance() + ->getTreeArray(0), 'title'); + $sourcedata = [0 => __('None')]; + foreach ($this->sourcedata as $k => $v) { + $sourcedata[$v['id']] = $v['title']; + unset($v['spacer']); + } + unset($v); + + $this->view->assign('sourcedata', $sourcedata); + $this->view->assign('row', $row); + 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); + $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 . '.edit' : $name) : $this->modelValidate; + $row->validateFailException()->validate($validate); + } + $result = $row->allowField(true)->save($params); + Db::commit(); + } catch (ValidateException|PDOException|Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if (false === $result) { + $this->error(__('No rows were updated')); + } + $this->success(); + } + +} diff --git a/application/admin/lang/zh-cn/coupons.php b/application/admin/lang/zh-cn/coupons.php new file mode 100644 index 0000000..de9a13b --- /dev/null +++ b/application/admin/lang/zh-cn/coupons.php @@ -0,0 +1,20 @@ + '优惠码唯一标识', + 'Code' => '优惠码名称', + 'Description' => '优惠码描述', + 'Discount_type' => '折扣类型', + 'Min_order' => '最低消费金额', + 'Max_discount' => '最大优惠金额', + 'Status' => '状态', + 'Threshold' => '优惠门槛', + 'Discount_value' => '优惠金额', + 'Created_at' => '创建时间', + 'Updated_at' => '更新时间', + 'Percentage' => '百分比优惠', + + 'Fixed' => '固定优惠', + 'Active' => '可用', + 'Inactive' => '禁用', +]; diff --git a/application/admin/lang/zh-cn/order.php b/application/admin/lang/zh-cn/order.php index 23ce16d..2fc90ac 100644 --- a/application/admin/lang/zh-cn/order.php +++ b/application/admin/lang/zh-cn/order.php @@ -57,5 +57,6 @@ return [ 'Payment_time' => '付款时间', 'Finishe_time' => '完成时间', 'Dispatch_time' => '派单时间', - 'Delete_time' => '删除时间' + 'Delete_time' => '删除时间', + 'Coupons' => '优惠', ]; diff --git a/application/admin/lang/zh-cn/phones.php b/application/admin/lang/zh-cn/phones.php new file mode 100644 index 0000000..59af4f3 --- /dev/null +++ b/application/admin/lang/zh-cn/phones.php @@ -0,0 +1,10 @@ + '手机号码', + 'Model' => '型号', + 'Assigned_user' => '使用者', + 'Assigned_date' => '使用时期', + 'Available' => '空闲', + 'Assigned' => '已分配', +]; diff --git a/application/admin/lang/zh-cn/source.php b/application/admin/lang/zh-cn/source.php new file mode 100644 index 0000000..fd5908f --- /dev/null +++ b/application/admin/lang/zh-cn/source.php @@ -0,0 +1,16 @@ + 'ID', + 'Pid' => 'PID', + 'Level' => '层级', + 'Title' => '服务名称', + 'Key_word' => '关键字', + 'Image' => '图标', + 'Sort' => '排序', + 'Status' => '状态', + 'Status 1' => '启用', + 'Set status to 1'=> '设为启用', + 'Status 0' => '关闭', + 'Set status to 0'=> '设为关闭' +]; diff --git a/application/admin/model/Area.php b/application/admin/model/Area.php index 94919f6..89743f0 100644 --- a/application/admin/model/Area.php +++ b/application/admin/model/Area.php @@ -13,7 +13,8 @@ class Area extends Model public function getNameByCode($code){ - return $this->where('area_code',$code)->find()->value('merge_name'); + return $this->where('area_code','=',$code) + ->value('merge_name'); } diff --git a/application/admin/model/Coupons.php b/application/admin/model/Coupons.php new file mode 100644 index 0000000..f3996dc --- /dev/null +++ b/application/admin/model/Coupons.php @@ -0,0 +1,63 @@ + __('Fixed'), 'percentage' => __('Percentage')]; + } + + public function getStatusList() + { + return ['active' => __('Active'), 'inactive' => __('Inactive')]; + } + + + public function getDiscountTypeTextAttr($value, $data) + { + $value = $value ?: ($data['discount_type'] ?? ''); + $list = $this->getDiscountTypeList(); + return $list[$value] ?? ''; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ?: ($data['status'] ?? ''); + $list = $this->getStatusList(); + return $list[$value] ?? ''; + } + + + + +} diff --git a/application/admin/model/Order.php b/application/admin/model/Order.php index e626744..35be7c1 100644 --- a/application/admin/model/Order.php +++ b/application/admin/model/Order.php @@ -99,7 +99,14 @@ class Order extends Model } - public function admin(){ - return $this->belongsTo(Admin::class,'audit_admin_id',); + public function user(){ + return $this->belongsTo(Admin::class,'user_id',); + } + + public function area(){ + return $this->belongsTo(Area::class,'area_id','area_code'); + } + public function phone(){ + return $this->belongsTo(Phones::class,'work_tel_id',); } } diff --git a/application/admin/model/Phones.php b/application/admin/model/Phones.php new file mode 100644 index 0000000..6cbc532 --- /dev/null +++ b/application/admin/model/Phones.php @@ -0,0 +1,47 @@ + __('Available'), 'assigned' => __('Assigned')]; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ?: ($data['status'] ?? ''); + $list = $this->getStatusList(); + return $list[$value] ?? ''; + } + + + + public function user(){ + return $this->belongsTo(Admin::class,'assigned_user'); + } +} diff --git a/application/admin/model/Source.php b/application/admin/model/Source.php new file mode 100644 index 0000000..8c5d186 --- /dev/null +++ b/application/admin/model/Source.php @@ -0,0 +1,49 @@ + __('Status 1'), '0' => __('Status 0')]; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ?: ($data['status'] ?? ''); + $list = $this->getStatusList(); + return $list[$value] ?? ''; + } + + + + +} diff --git a/application/admin/validate/Coupons.php b/application/admin/validate/Coupons.php new file mode 100644 index 0000000..2a1b72b --- /dev/null +++ b/application/admin/validate/Coupons.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/admin/validate/Phones.php b/application/admin/validate/Phones.php new file mode 100644 index 0000000..61a94e5 --- /dev/null +++ b/application/admin/validate/Phones.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/admin/validate/Source.php b/application/admin/validate/Source.php new file mode 100644 index 0000000..bf63a14 --- /dev/null +++ b/application/admin/validate/Source.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/admin/view/coupons/add.html b/application/admin/view/coupons/add.html new file mode 100644 index 0000000..cc2ac12 --- /dev/null +++ b/application/admin/view/coupons/add.html @@ -0,0 +1,81 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/application/admin/view/coupons/edit.html b/application/admin/view/coupons/edit.html new file mode 100644 index 0000000..f500d2f --- /dev/null +++ b/application/admin/view/coupons/edit.html @@ -0,0 +1,81 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ +
diff --git a/application/admin/view/coupons/index.html b/application/admin/view/coupons/index.html new file mode 100644 index 0000000..8e5b965 --- /dev/null +++ b/application/admin/view/coupons/index.html @@ -0,0 +1,46 @@ +
+ +
+ {:build_heading(null,FALSE)} + +
+ + +
+
+
+
+
+ + {:__('Add')} + {:__('Edit')} + {:__('Delete')} + + + + + +
+ +
+
+
+ +
+
+
diff --git a/application/admin/view/item/add.html b/application/admin/view/item/add.html index d9d89b0..3146a68 100644 --- a/application/admin/view/item/add.html +++ b/application/admin/view/item/add.html @@ -19,24 +19,18 @@ -
- -
-
- -
- - -
- -
- -
-
- + - + + + + + + + + +
@@ -54,7 +48,7 @@ diff --git a/application/admin/view/item/edit.html b/application/admin/view/item/edit.html index 641d890..f6ef34c 100644 --- a/application/admin/view/item/edit.html +++ b/application/admin/view/item/edit.html @@ -18,20 +18,20 @@
-
- -
-
- -
- - -
- -
- -
-
+ + + + + + + + + + + + + + diff --git a/application/admin/view/item/index.html b/application/admin/view/item/index.html index a597675..c1aa4e2 100644 --- a/application/admin/view/item/index.html +++ b/application/admin/view/item/index.html @@ -1,11 +1,13 @@
- +
{:build_heading(null,FALSE)}
@@ -16,22 +18,28 @@
- +
+ + +
+ +
+ +
+
+
- - - - - - - +
+ +
+ +
+ +
+
+ +
diff --git a/application/admin/view/order/copy.html b/application/admin/view/order/copy.html index e5a0a5b..3e9626d 100644 --- a/application/admin/view/order/copy.html +++ b/application/admin/view/order/copy.html @@ -5,27 +5,24 @@
-
复制订单
+
编辑订单
- - -
- +
- +
- +
- +
- +
- + @@ -34,43 +31,69 @@
- +
- +
- +
- +
-
- -
- - - +
+ +
+ +
+
- - +
+ +
+ +
+
+ +
+ +
+
- +
- +
- +
@@ -84,9 +107,9 @@
diff --git a/application/admin/view/order/edit.html b/application/admin/view/order/edit.html index fcaf38a..08f3d15 100644 --- a/application/admin/view/order/edit.html +++ b/application/admin/view/order/edit.html @@ -11,21 +11,21 @@
- +
- +
- +
- +
- +
- + @@ -34,43 +34,69 @@
- +
- +
- +
- +
-
- -
- - - +
+ +
+ +
+
- - +
+ +
+ +
+
+ +
+ +
+
- +
- +
- +
@@ -84,7 +110,7 @@
+
+
+
+ +
+ + diff --git a/application/admin/view/source/add.html b/application/admin/view/source/add.html new file mode 100644 index 0000000..a0f3d8f --- /dev/null +++ b/application/admin/view/source/add.html @@ -0,0 +1,54 @@ +
+ +
+ +
+ {:build_select('row[pid]', $sourcedata, null, ['class'=>'form-control', 'required'=>''])} +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + +
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+ +
diff --git a/application/admin/view/source/edit.html b/application/admin/view/source/edit.html new file mode 100644 index 0000000..1d9dc26 --- /dev/null +++ b/application/admin/view/source/edit.html @@ -0,0 +1,59 @@ +
+ +
+ +
+ {:build_select('row[pid]', $sourcedata, $row.pid, ['class'=>'form-control', 'required'=>''])} +
+
+
+ +
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+ +
diff --git a/application/admin/view/source/index.html b/application/admin/view/source/index.html new file mode 100644 index 0000000..c1aa4e2 --- /dev/null +++ b/application/admin/view/source/index.html @@ -0,0 +1,54 @@ +
+ +
+ {:build_heading(null,FALSE)} + +
+ + +
+
+
+
+
+ + {:__('Add')} + {:__('Edit')} + {:__('Delete')} + + + +
+ +
+
+
+ +
+
+
diff --git a/application/config.php b/application/config.php index d79325d..bf39d53 100755 --- a/application/config.php +++ b/application/config.php @@ -48,7 +48,7 @@ return [ // 默认语言 'default_lang' => 'zh-cn', // 允许的语言列表 - 'allow_lang_list' => ['zh-cn', 'en'], + 'allow_lang_list' => ['zh-cn'], // 应用类库后缀 'class_suffix' => false, // 控制器类后缀 @@ -280,11 +280,11 @@ return [ //FastAdmin配置 'fastadmin' => [ //是否开启前台会员中心 - 'usercenter' => true, + 'usercenter' => false, //会员注册验证码类型email/mobile/wechat/text/false 'user_register_captcha' => 'text', //登录验证码 - 'login_captcha' => true, + 'login_captcha' => false, //登录失败超过10次则1天后重试 'login_failure_retry' => true, //是否同一账号同一时间只能在一个地方登录 diff --git a/public/assets/js/backend/coupons.js b/public/assets/js/backend/coupons.js new file mode 100644 index 0000000..608d10e --- /dev/null +++ b/public/assets/js/backend/coupons.js @@ -0,0 +1,62 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'coupons/index' + location.search, + add_url: 'coupons/add', + edit_url: 'coupons/edit', + del_url: 'coupons/del', + multi_url: 'coupons/multi', + import_url: 'coupons/import', + table: 'coupons', + } + }); + + 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: 'code', title: __('Code'), operate: 'LIKE'}, + {field: 'description', title: __('Description'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'discount_type', title: __('Discount_type'), searchList: {"fixed":__('Fixed'),"percentage":__('Percentage')}, formatter: Table.api.formatter.normal}, + {field: 'min_order', title: __('Min_order'), operate:'BETWEEN'}, + {field: 'max_discount', title: __('Max_discount'), operate:'BETWEEN'}, + {field: 'status', title: __('Status'), searchList: {"active":__('Active'),"inactive":__('Inactive')}, formatter: Table.api.formatter.status}, + {field: 'threshold', title: __('Threshold'), operate:'BETWEEN'}, + {field: 'discount_value', title: __('Discount_value'), operate:'BETWEEN'}, + {field: 'created_at', title: __('Created_at')}, + {field: 'updated_at', title: __('Updated_at')}, + {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; +}); diff --git a/public/assets/js/backend/item.js b/public/assets/js/backend/item.js index 6dd6ffb..8a81c94 100644 --- a/public/assets/js/backend/item.js +++ b/public/assets/js/backend/item.js @@ -5,7 +5,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function // 初始化表格参数配置 Table.api.init({ extend: { - "index_url": "item/index", + "index_url": "item/index" + location.search, "add_url": "item/add", "edit_url": "item/edit", "del_url": "item/del", @@ -19,8 +19,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function // 初始化表格 table.bootstrapTable({ url: $.fn.bootstrapTable.defaults.extend.index_url, - sortName: '', - escape: true, + // sortName: 'id', + // escape: true, + fixedColumns: true, + fixedRightNumber: 1, columns: [ [ {field: 'state', checkbox: true,}, @@ -39,7 +41,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ] ], pagination: false, - search: false, + search: true, commonSearch: false, rowAttributes: function (row, index) { return row.pid === 0 ? {} : {style: "display:none"}; @@ -154,13 +156,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function }, }, bindevent: function () { - $(document).on('click', "input[name='row[ismenu]']", function () { - var name = $("input[name='row[name]']"); - var ismenu = $(this).val() === 1; - name.prop("placeholder", ismenu ? name.data("placeholder-menu") : name.data("placeholder-node")); - $('div[data-type="menu"]').toggleClass("hidden", !ismenu); - }); - $("input[name='row[ismenu]']:checked").trigger("click"); + Form.api.bindevent($("form[role=form]")); } } }; diff --git a/public/assets/js/backend/order.js b/public/assets/js/backend/order.js index df71d7e..4b8ad56 100644 --- a/public/assets/js/backend/order.js +++ b/public/assets/js/backend/order.js @@ -28,6 +28,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin [ {checkbox: true}, {field: 'id', title: __('Id')}, + {field: 'user.nickname', title: '录单员'}, {field: 'order_no', title: __('Order_no'), operate: 'LIKE'}, {field: 'customer', title: __('Customer'), operate: 'LIKE'}, {field: 'tel', title: __('Tel'), operate: 'LIKE'}, @@ -46,7 +47,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin }, formatter: Table.api.formatter.status }, - {field: 'area_id', title: __('Area_id')}, + {field: 'area.merge_name', title: __('Area_id')}, { field: 'address', title: __('Address'), @@ -55,9 +56,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin class: 'autocontent', formatter: Table.api.formatter.content }, - {field: 'work_tel_id', title: __('Work_tel_id')}, + {field: 'phone.model', title: __('Work_tel_id')}, // {field: 'worker_id', title: __('Worker_id')}, - {field: 'source', title: __('Source')}, + {field: 'source_shop', title: __('Source')}, // {field: 'source_uid', title: __('Source_uid'), operate: 'LIKE'}, {field: 'item_title', title: __('Item_title'), operate: 'LIKE'}, { @@ -136,7 +137,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin classname:"btn-view btn-dialog", icon:'fa fa-money', url: function(row){ - return 'orders/income/add?order_id='+row.id + return 'orders/income/add?order_id='+row.id; }, dropdown:"更多", visible:function(row){ @@ -154,6 +155,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin Table.api.bindevent(table); }, add: function () { + console.log(1); Controller.api.bindevent(); }, edit: function () { @@ -164,7 +166,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin }, api: { bindevent: function () { - Form.api.bindevent($("form[role=form]")); + Form.api.bindevent($("form[role=form]"),function (success,ret) { + console.log(success); + }); } } }; @@ -232,64 +236,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin } - let $inputService = $("#c-service_title"); - let $dropdownService = $("#service-list"); - let $hiddenFieldService = $("#selected-service_id"); - let timerService = null; // 定义定时器 - - $inputService.on("input", function () { - clearTimeout(timerService); // 清除上次的定时器 - let keyword = $(this).val().trim(); - - if (keyword.length === 0) { - $dropdown.hide(); - return; - } - - // 延迟 500 毫秒后执行 AJAX 查询(防止过快触发) - timerService = setTimeout(() => { - $.ajax({ - url: "/admin/item/search", // 你的 API 地址 - type: "GET", - data: {keyword: keyword}, - dataType: "json", - success: function (data) { - renderDropdownService(data.data); - }, - error: function () { - console.error("请求失败"); - } - }); - }, 200); // 500 毫秒防抖 - }); - - // 渲染资源城市下拉选项 - function renderDropdownService(data) { - $dropdownService.empty(); // 清空列表 - if (data.length === 0) { - let $option = $("") - .text('未搜索到结果') - .attr("data-value", 0); - $dropdownService.append($option); - } else { - data.forEach(item => { - let $option = $("") - .html(item.title + `${item.key_word}`) - .attr("data-value", item.id) // 绑定 area_code - .on("click", function () { - $inputService.val(item.title); // 选中后填充输入框 - $hiddenFieldService.val($(this).attr("data-value")); // 存储 area_code - $dropdownService.hide(); - }); - $dropdownService.append($option); - }); - } - - - $dropdownService.show(); // 显示下拉框 - } - - // 点击外部隐藏下拉框 $(document).on("click", function (e) { if (!$(e.target).closest("#c-address, #address-list").length) { diff --git a/public/assets/js/backend/phones.js b/public/assets/js/backend/phones.js new file mode 100644 index 0000000..099c90a --- /dev/null +++ b/public/assets/js/backend/phones.js @@ -0,0 +1,55 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'phones/index' + location.search, + add_url: 'phones/add', + edit_url: 'phones/edit', + del_url: 'phones/del', + multi_url: 'phones/multi', + import_url: 'phones/import', + table: 'phones', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'phone_number', title: __('Phone_number'), operate: 'LIKE'}, + {field: 'model', title: __('Model'), operate: 'LIKE'}, + {field: 'user.nickname', title: __('Assigned_user')}, + {field: 'assigned_date', title: __('Assigned_date'), operate:'RANGE', addclass:'datetimerange', autocomplete:false}, + {field: 'status', title: __('Status'), searchList: {"available":__('Available'),"assigned":__('Assigned')}, formatter: Table.api.formatter.status}, + {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; +}); diff --git a/public/assets/js/backend/source.js b/public/assets/js/backend/source.js new file mode 100644 index 0000000..e540815 --- /dev/null +++ b/public/assets/js/backend/source.js @@ -0,0 +1,164 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + "index_url": "source/index" + location.search, + "add_url": "source/add", + "edit_url": "source/edit", + "del_url": "source/del", + "multi_url": "source/multi", + "table": "source" + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + // sortName: 'id', + // escape: true, + fixedColumns: true, + fixedRightNumber: 1, + columns: [ + [ + {field: 'state', checkbox: true,}, + // {field: 'id', title: 'ID'}, + {field: 'title', title: __('Title'), align: 'left', formatter: Controller.api.formatter.title, clickToSelect: !false}, + {field: 'key_word', title: __('Key_word'), align: 'left', formatter: Controller.api.formatter.content}, + // {field: 'sort', title: __('Sort')}, + {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, + { + field: 'operate', + title: __('Operate'), + table: table, + events: Table.api.events.operate, + formatter: Table.api.formatter.operate + } + ] + ], + pagination: false, + search: true, + commonSearch: false, + rowAttributes: function (row, index) { + return row.pid === 0 ? {} : {style: "display:none"}; + } + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + + var btnSuccessEvent = function (data, ret) { + if ($(this).hasClass("btn-change")) { + var index = $(this).data("index"); + var row = Table.api.getrowbyindex(table, index); + row.ismenu = $("i.fa.text-gray", this).length > 0 ? 1 : 0; + table.bootstrapTable("updateRow", {index: index, row: row}); + } else if ($(this).hasClass("btn-delone")) { + if ($(this).closest("tr[data-index]").find("a.btn-node-sub.disabled").length > 0) { + $(this).closest("tr[data-index]").remove(); + } else { + table.bootstrapTable('refresh'); + } + } else if ($(this).hasClass("btn-dragsort")) { + table.bootstrapTable('refresh'); + } + Fast.api.refreshmenu(); + return false; + }; + + //表格内容渲染前 + table.on('pre-body.bs.table', function (e, data) { + var options = table.bootstrapTable("getOptions"); + options.escape = true; + }); + + //当内容渲染完成后 + table.on('post-body.bs.table', function (e, data) { + var options = table.bootstrapTable("getOptions"); + options.escape = false; + + //点击切换/排序/删除操作后刷新左侧菜单 + $(".btn-change[data-id],.btn-delone,.btn-dragsort").data("success", btnSuccessEvent); + + }); + + table.on('post-body.bs.table', function (e, settings, json, xhr) { + //显示隐藏子节点 + $(">tbody>tr[data-index] > td", this).on('click', "a.btn-node-sub", function () { + var status = $(this).data("shown") ? true : false; + $("a[data-pid='" + $(this).data("id") + "']").each(function () { + $(this).closest("tr").toggle(!status); + }); + if (status) { + $("a[data-pid='" + $(this).data("id") + "']").trigger("collapse"); + } + $(this).data("shown", !status); + $("i", this).toggleClass("fa-caret-down").toggleClass("fa-caret-right"); + return false; + }); + }); + + //隐藏子节点 + $(document).on("collapse", ".btn-node-sub", function () { + if ($("i", this).length > 0) { + $("a[data-pid='" + $(this).data("id") + "']").trigger("collapse"); + } + $("i", this).removeClass("fa-caret-down").addClass("fa-caret-right"); + $(this).data("shown", false); + $(this).closest("tr").toggle(false); + }); + + //批量删除后的回调 + $(".toolbar > .btn-del,.toolbar .btn-more~ul>li>a").data("success", function (e) { + Fast.api.refreshmenu(); + }); + + //展开隐藏一级 + $(document.body).on("click", ".btn-toggle", function (e) { + $("a[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide(); + var that = this; + var show = $("i", that).hasClass("fa-chevron-down"); + $("i", that).toggleClass("fa-chevron-down", !show).toggleClass("fa-chevron-up", show); + $("a[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show); + $(".btn-node-sub[data-pid=0]").data("shown", show); + }); + + //展开隐藏全部 + $(document.body).on("click", ".btn-toggle-all", function (e) { + var that = this; + var show = $("i", that).hasClass("fa-plus"); + $("i", that).toggleClass("fa-plus", !show).toggleClass("fa-minus", show); + $(".btn-node-sub:not([data-pid=0])").closest("tr").toggle(show); + $(".btn-node-sub").data("shown", show); + $(".btn-node-sub > i").toggleClass("fa-caret-down", show).toggleClass("fa-caret-right", !show); + }); + }, + add: function () { + Controller.api.bindevent(); + }, + edit: function () { + Controller.api.bindevent(); + }, + api: { + formatter: { + title: function (value, row, index) { + value = value.toString().replace(/(&|&)nbsp;/g, ' '); + var caret = row.pid === 0 ? '' : ''; + value = value.indexOf(" ") > -1 ? value.replace(/(.*) /, "$1" + caret) : caret + value; + + value = row.status === 0 ? "" + value + "" : value; + return '' + value + ''; + }, + }, + bindevent: function () { + Form.api.bindevent($("form[role=form]")); + } + } + }; + return Controller; +});