From e2b7a9c570cf879366337e1a34fdbb1e7197acc6 Mon Sep 17 00:00:00 2001 From: 15090180611 <215509543@qq.com> Date: Thu, 26 Dec 2024 18:13:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=8F=91=E9=80=80=E6=AC=BE=EF=BC=88?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E4=B8=AD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../school/classes/activity/Activity.php | 29 +- .../classes/activity/order/OrderItem.php | 77 + .../school/classes/activity/activity.php | 3 +- .../classes/activity/order/order_item.php | 40 + .../admin/model/school/classes/ClassesLib.php | 3 +- .../school/classes/activity/Activity.php | 23 +- .../school/classes/activity/ActivityAuth.php | 3 +- .../classes/activity/order/OrderItem.php | 119 ++ .../classes/activity/order/OrderItem.php | 27 + .../admin/view/manystore/index/add.html | 8 +- .../admin/view/manystore/index/edit.html | 8 +- .../school/classes/activity/activity/add.html | 4 +- .../classes/activity/activity/edit.html | 4 +- .../classes/activity/activity_auth/add.html | 4 +- .../classes/activity/activity_auth/edit.html | 4 +- .../activity/order/order_item/add.html | 117 ++ .../activity/order/order_item/edit.html | 117 ++ .../activity/order/order_item/index.html | 46 + .../activity/order/order_item/recyclebin.html | 25 + .../school/classes/classes_lib/addnew.html | 4 +- .../view/school/classes/classes_lib/edit.html | 4 +- .../service_order/admin_confirmation.html | 4 +- .../service_order/shop_confirmation.html | 4 +- .../service_order/user_confirmation.html | 4 +- .../view/school/classes/teacher/add.html | 4 +- .../view/school/classes/teacher/edit.html | 4 +- application/api/controller/User.php | 4 + .../api/controller/school/Activity.php | 217 ++- .../api/controller/school/activity/Order.php | 224 +++ .../api/controller/school/activity/Pay.php | 325 ++++ .../api/controller/school/worker/Base.php | 5 +- .../school/worker/activity/Order.php | 152 ++ application/common.php | 11 +- application/common/hooks.php | 49 +- .../listener/activityorder/OrderHook.php | 78 + .../common/listener/classes/ActivityHook.php | 15 +- .../model/school/classes/ClassesLib.php | 48 +- .../school/classes/activity/Activity.php | 730 +++++++- .../school/classes/activity/ActivityAuth.php | 3 +- .../school/classes/activity/order/Order.php | 1547 ++++++++++++++++- .../classes/activity/order/OrderDetail.php | 3 +- .../classes/activity/order/OrderItem.php | 119 ++ .../classes/activity/order/OrderLog.php | 51 +- .../model/school/classes/order/Order.php | 40 +- application/extra/site.php | 56 +- application/extra/upload.php | 2 +- .../school/classes/activity/Activity.php | 28 +- .../classes/activity/order/OrderItem.php | 80 + .../school/classes/activity/activity.php | 3 +- .../classes/activity/order/order_item.php | 38 + application/manystore/library/Auth.php | 3 + .../manystore/library/ManystoreAuth.php | 2 +- .../model/school/classes/ClassesLib.php | 3 +- .../school/classes/activity/Activity.php | 20 +- .../school/classes/activity/ActivityAuth.php | 3 +- .../classes/activity/order/OrderItem.php | 117 ++ .../classes/activity/order/OrderItem.php | 27 + .../manystore/view/general/profile/index.html | 10 +- .../school/classes/activity/activity/add.html | 64 +- .../classes/activity/activity/edit.html | 64 +- .../classes/activity/activity_auth/add.html | 4 +- .../classes/activity/activity_auth/edit.html | 4 +- .../activity/order/order_item/add.html | 112 ++ .../activity/order/order_item/edit.html | 112 ++ .../activity/order/order_item/index.html | 44 + .../activity/order/order_item/recyclebin.html | 25 + .../school/classes/classes_lib/addnew.html | 4 +- .../view/school/classes/classes_lib/edit.html | 4 +- .../service_order/admin_confirmation.html | 4 +- .../service_order/shop_confirmation.html | 4 +- .../service_order/user_confirmation.html | 4 +- .../view/school/classes/teacher/add.html | 4 +- .../view/school/classes/teacher/edit.html | 4 +- .../school/classes/activity/activity.js | 6 +- .../school/classes/activity/activity_auth.js | 2 +- .../classes/activity/order/order_detail.js | 2 +- .../classes/activity/order/order_item.js | 139 ++ .../school/classes/activity/activity.js | 3 +- .../school/classes/activity/activity_auth.js | 2 +- .../classes/activity/order/order_detail.js | 2 +- .../classes/activity/order/order_item.js | 136 ++ 81 files changed, 5261 insertions(+), 190 deletions(-) create mode 100644 application/admin/controller/school/classes/activity/order/OrderItem.php create mode 100644 application/admin/lang/zh-cn/school/classes/activity/order/order_item.php create mode 100644 application/admin/model/school/classes/activity/order/OrderItem.php create mode 100644 application/admin/validate/school/classes/activity/order/OrderItem.php create mode 100644 application/admin/view/school/classes/activity/order/order_item/add.html create mode 100644 application/admin/view/school/classes/activity/order/order_item/edit.html create mode 100644 application/admin/view/school/classes/activity/order/order_item/index.html create mode 100644 application/admin/view/school/classes/activity/order/order_item/recyclebin.html create mode 100644 application/api/controller/school/activity/Order.php create mode 100644 application/api/controller/school/activity/Pay.php create mode 100644 application/api/controller/school/worker/activity/Order.php create mode 100644 application/common/listener/activityorder/OrderHook.php create mode 100644 application/common/model/school/classes/activity/order/OrderItem.php create mode 100644 application/manystore/controller/school/classes/activity/order/OrderItem.php create mode 100644 application/manystore/lang/zh-cn/school/classes/activity/order/order_item.php create mode 100644 application/manystore/model/school/classes/activity/order/OrderItem.php create mode 100644 application/manystore/validate/school/classes/activity/order/OrderItem.php create mode 100644 application/manystore/view/school/classes/activity/order/order_item/add.html create mode 100644 application/manystore/view/school/classes/activity/order/order_item/edit.html create mode 100644 application/manystore/view/school/classes/activity/order/order_item/index.html create mode 100644 application/manystore/view/school/classes/activity/order/order_item/recyclebin.html create mode 100644 public/assets/js/backend/school/classes/activity/order/order_item.js create mode 100644 public/assets/js/manystore/school/classes/activity/order/order_item.js diff --git a/application/admin/controller/school/classes/activity/Activity.php b/application/admin/controller/school/classes/activity/Activity.php index ef291d2..cd23d1a 100644 --- a/application/admin/controller/school/classes/activity/Activity.php +++ b/application/admin/controller/school/classes/activity/Activity.php @@ -77,7 +77,7 @@ class Activity extends Backend if ($this->request->request('keyField')) { return $this->selectpage(); } - list($where, $sort, $order, $offset, $limit, $page, $alias, $bind, $excludearray) = $this->buildparams(null, null, ["has_expire"]); + list($where, $sort, $order, $offset, $limit, $page, $alias, $bind, $excludearray) = $this->buildparams(null, null, ["has_expire","has_sign_expire"]); if (isset($excludearray['has_expire']['value']) && $excludearray['has_expire']['value']) { $has_expire = $excludearray['has_expire']['value']; @@ -100,10 +100,35 @@ class Activity extends Backend $expireWhere = [[]]; } + + if (isset($excludearray['has_sign_expire']['value']) && $excludearray['has_sign_expire']['value']) { + $has_expire = $excludearray['has_sign_expire']['value']; + $as = (new \app\common\model\school\classes\activity\Activity)->getWithAlisaName(); + switch ($has_expire) { + case '1': //查过期 + $expireSignWhere = [ + $as . '.sign_end_time', '<=', time(), + ]; + break; + case '2': //查未过期 + $expireSignWhere = [ + $as . '.sign_end_time', '>', time(), + ]; + break; + default: + } + + } else { + $expireSignWhere = [[]]; + } + + + $list = $this->model ->with(['manystore','shop']) ->where($where) ->where(...$expireWhere) + ->where(...$expireSignWhere) ->order($sort, $order) ->paginate($limit); @@ -122,7 +147,7 @@ class Activity extends Backend protected function update_classes($classes_activity_id){ - + if($classes_activity_id) \app\common\model\school\classes\activity\Activity::update_classes($classes_activity_id); } diff --git a/application/admin/controller/school/classes/activity/order/OrderItem.php b/application/admin/controller/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..b75afef --- /dev/null +++ b/application/admin/controller/school/classes/activity/order/OrderItem.php @@ -0,0 +1,77 @@ +model = new \app\admin\model\school\classes\activity\order\OrderItem; + $this->view->assign("statusList", $this->model->getStatusList()); + $this->view->assign("sexList", $this->model->getSexList()); + $this->view->assign("feelList", $this->model->getFeelList()); + } + + + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + + /** + * 查看 + */ + public function index() + { + //当前是否为关联查询 + $this->relationSearch = true; + //设置过滤方法 + $this->request->filter(['strip_tags', 'trim']); + if ($this->request->isAjax()) { + //如果发送的来源是Selectpage,则转发到Selectpage + if ($this->request->request('keyField')) { + return $this->selectpage(); + } + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); + + $list = $this->model + ->with(['activityorder','manystore','shop','activity','item']) + ->where($where) + ->order($sort, $order) + ->paginate($limit); + + foreach ($list as $row) { + + $row->getRelation('activityorder')->visible(['order_no','pay_no']); + $row->getRelation('manystore')->visible(['nickname']); + $row->getRelation('shop')->visible(['name','logo']); + $row->getRelation('activity')->visible(['title','headimage']); + $row->getRelation('item')->visible(['name','price']); + } + + $result = array("total" => $list->total(), "rows" => $list->items()); + + return json($result); + } + return $this->view->fetch(); + } + +} diff --git a/application/admin/lang/zh-cn/school/classes/activity/activity.php b/application/admin/lang/zh-cn/school/classes/activity/activity.php index 59f3abe..4e59fa9 100644 --- a/application/admin/lang/zh-cn/school/classes/activity/activity.php +++ b/application/admin/lang/zh-cn/school/classes/activity/activity.php @@ -68,7 +68,8 @@ return [ 'Limit_num' => '本项目限定人数', 'Age' => '年龄限制描述', 'Item_json' => '活动项目', - 'Has_expire' => '是否过期', + 'Has_expire' => '活动是否过期', 'Has_expire 1' => '往期活动', 'Has_expire 2' => '进行中活动', + 'Has_sign_expire' => '报名是否过期', ]; diff --git a/application/admin/lang/zh-cn/school/classes/activity/order/order_item.php b/application/admin/lang/zh-cn/school/classes/activity/order/order_item.php new file mode 100644 index 0000000..ed494c0 --- /dev/null +++ b/application/admin/lang/zh-cn/school/classes/activity/order/order_item.php @@ -0,0 +1,40 @@ + '课程活动订单id', + 'Manystore_id' => '机构账号id', + 'Shop_id' => '机构店铺id', + 'Classes_activity_id' => '课程活动id', + 'Classes_activity_item_id' => '课程活动项id', + 'Name' => '活动项名称', + 'Price' => '项目价格(0为免费)', + 'Limit_num' => '本项目限定人数', + 'Age' => '年龄限制描述', + 'Status' => '状态', + 'Status 1' => '上架', + 'Set status to 1' => '设为上架', + 'Status 2' => '下架', + 'Set status to 2' => '设为下架', + 'Sex' => '性别限制', + 'Sex 1' => '男', + 'Sex 2' => '女', + 'Sex 3' => '男女不限', + 'Weigh' => '权重', + 'Sign_num' => '已报名人数', + 'Verification_num' => '已核销人数', + 'Createtime' => '创建时间', + 'Updatetime' => '修改时间', + 'Deletetime' => '删除时间', + 'Feel' => '是否免费', + 'Feel 0' => '否', + 'Feel 1' => '是', + 'Order.order_no' => '订单号', + 'Order.pay_no' => '微信支付单号', + 'Manystore.nickname' => '昵称', + 'Shop.name' => '店铺名称', + 'Shop.logo' => '品牌LOGO', + 'Activity.title' => '标题', + 'Activity.headimage' => '头图', + 'Item.name' => '活动项名称', + 'Item.price' => '项目价格(0为免费)' +]; diff --git a/application/admin/model/school/classes/ClassesLib.php b/application/admin/model/school/classes/ClassesLib.php index 1076c87..4ca17b4 100644 --- a/application/admin/model/school/classes/ClassesLib.php +++ b/application/admin/model/school/classes/ClassesLib.php @@ -88,7 +88,8 @@ class ClassesLib extends Model self::afterInsert(function ($row) { if (!$row['weigh']) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); } }); } diff --git a/application/admin/model/school/classes/activity/Activity.php b/application/admin/model/school/classes/activity/Activity.php index 2690f1c..50ca95e 100644 --- a/application/admin/model/school/classes/activity/Activity.php +++ b/application/admin/model/school/classes/activity/Activity.php @@ -40,8 +40,28 @@ class Activity extends Model 'expirestatus_text', 'add_type_text', 'has_expire', + 'has_sign_expire', ]; + + public function getHasSignExpireAttr($value, $data) + { + $sign_start_time = (isset($data['sign_start_time']) ? $data['sign_start_time'] : ''); + $sign_end_time = (isset($data['sign_end_time']) ? $data['sign_end_time'] : ''); + + if(!$sign_end_time) return '2'; + + if( $sign_end_time < time()) { + return '1'; + }else{ + return '2'; + } + + } + + + + public function getHasExpireList() { return ['1' => __('Has_expire 1'), '2' => __('Has_expire 2')]; @@ -66,7 +86,8 @@ class Activity extends Model self::afterInsert(function ($row) { if (!$row['weigh']) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); } }); } diff --git a/application/admin/model/school/classes/activity/ActivityAuth.php b/application/admin/model/school/classes/activity/ActivityAuth.php index f6df995..6c8debb 100644 --- a/application/admin/model/school/classes/activity/ActivityAuth.php +++ b/application/admin/model/school/classes/activity/ActivityAuth.php @@ -69,7 +69,8 @@ class ActivityAuth extends Model self::afterInsert(function ($row) { if (!$row['weigh']) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); } }); } diff --git a/application/admin/model/school/classes/activity/order/OrderItem.php b/application/admin/model/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..b593394 --- /dev/null +++ b/application/admin/model/school/classes/activity/order/OrderItem.php @@ -0,0 +1,119 @@ +getPk(); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + } + }); + } + + + public function getStatusList() + { + return ['1' => __('Status 1'), '2' => __('Status 2')]; + } + + public function getSexList() + { + return ['1' => __('Sex 1'), '2' => __('Sex 2'), '3' => __('Sex 3')]; + } + + public function getFeelList() + { + return ['0' => __('Feel 0'), '1' => __('Feel 1')]; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['status']) ? $data['status'] : ''); + $list = $this->getStatusList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + public function getSexTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['sex']) ? $data['sex'] : ''); + $list = $this->getSexList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + public function getFeelTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['feel']) ? $data['feel'] : ''); + $list = $this->getFeelList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + + + public function activityorder() + { + return $this->belongsTo(Order::class, 'classes_activity_order_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function manystore() + { + return $this->belongsTo(Manystore::class, 'manystore_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function shop() + { + return $this->belongsTo(Shop::class, 'shop_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function activity() + { + return $this->belongsTo(Activity::class, 'classes_activity_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function item() + { + return $this->belongsTo(ActivityItem::class, 'classes_activity_item_id', 'id', [], 'LEFT')->setEagerlyType(0); + } +} diff --git a/application/admin/validate/school/classes/activity/order/OrderItem.php b/application/admin/validate/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..a90306e --- /dev/null +++ b/application/admin/validate/school/classes/activity/order/OrderItem.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/admin/view/manystore/index/add.html b/application/admin/view/manystore/index/add.html index e60261d..5253ba9 100644 --- a/application/admin/view/manystore/index/add.html +++ b/application/admin/view/manystore/index/add.html @@ -130,8 +130,8 @@
- - + +
@@ -233,8 +233,8 @@
- - + +
diff --git a/application/admin/view/manystore/index/edit.html b/application/admin/view/manystore/index/edit.html index 21d0724..143a841 100644 --- a/application/admin/view/manystore/index/edit.html +++ b/application/admin/view/manystore/index/edit.html @@ -145,8 +145,8 @@
- - + +
@@ -250,8 +250,8 @@
- - + +
diff --git a/application/admin/view/school/classes/activity/activity/add.html b/application/admin/view/school/classes/activity/activity/add.html index dfd92ee..be4f46a 100644 --- a/application/admin/view/school/classes/activity/activity/add.html +++ b/application/admin/view/school/classes/activity/activity/add.html @@ -41,8 +41,8 @@
- - + +
diff --git a/application/admin/view/school/classes/activity/activity/edit.html b/application/admin/view/school/classes/activity/activity/edit.html index 3f7157d..6e031e0 100644 --- a/application/admin/view/school/classes/activity/activity/edit.html +++ b/application/admin/view/school/classes/activity/activity/edit.html @@ -43,8 +43,8 @@
- - + +
diff --git a/application/admin/view/school/classes/activity/activity_auth/add.html b/application/admin/view/school/classes/activity/activity_auth/add.html index ad29ee1..c7dcc61 100644 --- a/application/admin/view/school/classes/activity/activity_auth/add.html +++ b/application/admin/view/school/classes/activity/activity_auth/add.html @@ -41,8 +41,8 @@
- - + +
diff --git a/application/admin/view/school/classes/activity/activity_auth/edit.html b/application/admin/view/school/classes/activity/activity_auth/edit.html index feb6941..f4d17a5 100644 --- a/application/admin/view/school/classes/activity/activity_auth/edit.html +++ b/application/admin/view/school/classes/activity/activity_auth/edit.html @@ -65,8 +65,8 @@
- - + +
diff --git a/application/admin/view/school/classes/activity/order/order_item/add.html b/application/admin/view/school/classes/activity/order/order_item/add.html new file mode 100644 index 0000000..9b5dbae --- /dev/null +++ b/application/admin/view/school/classes/activity/order/order_item/add.html @@ -0,0 +1,117 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +
+
+ +
diff --git a/application/admin/view/school/classes/activity/order/order_item/edit.html b/application/admin/view/school/classes/activity/order/order_item/edit.html new file mode 100644 index 0000000..dd830b6 --- /dev/null +++ b/application/admin/view/school/classes/activity/order/order_item/edit.html @@ -0,0 +1,117 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +
+
+ +
diff --git a/application/admin/view/school/classes/activity/order/order_item/index.html b/application/admin/view/school/classes/activity/order/order_item/index.html new file mode 100644 index 0000000..53a6f57 --- /dev/null +++ b/application/admin/view/school/classes/activity/order/order_item/index.html @@ -0,0 +1,46 @@ +
+ +
+ {:build_heading(null,FALSE)} + +
+ + +
+
+
+
+
+ + {:__('Add')} + {:__('Edit')} + {:__('Delete')} + + + + + {:__('Recycle bin')} +
+ +
+
+
+ +
+
+
diff --git a/application/admin/view/school/classes/activity/order/order_item/recyclebin.html b/application/admin/view/school/classes/activity/order/order_item/recyclebin.html new file mode 100644 index 0000000..e985ac3 --- /dev/null +++ b/application/admin/view/school/classes/activity/order/order_item/recyclebin.html @@ -0,0 +1,25 @@ +
+ {:build_heading()} + +
+
+
+ +
+ +
+
+
diff --git a/application/admin/view/school/classes/classes_lib/addnew.html b/application/admin/view/school/classes/classes_lib/addnew.html index 30b5261..d29ce3b 100644 --- a/application/admin/view/school/classes/classes_lib/addnew.html +++ b/application/admin/view/school/classes/classes_lib/addnew.html @@ -139,8 +139,8 @@
- - + +
diff --git a/application/admin/view/school/classes/classes_lib/edit.html b/application/admin/view/school/classes/classes_lib/edit.html index 0954d1b..5b85c6c 100644 --- a/application/admin/view/school/classes/classes_lib/edit.html +++ b/application/admin/view/school/classes/classes_lib/edit.html @@ -177,8 +177,8 @@
- - + +
diff --git a/application/admin/view/school/classes/order/service_order/admin_confirmation.html b/application/admin/view/school/classes/order/service_order/admin_confirmation.html index 86e594e..b5aa8f6 100644 --- a/application/admin/view/school/classes/order/service_order/admin_confirmation.html +++ b/application/admin/view/school/classes/order/service_order/admin_confirmation.html @@ -40,8 +40,8 @@
- - + +
diff --git a/application/admin/view/school/classes/order/service_order/shop_confirmation.html b/application/admin/view/school/classes/order/service_order/shop_confirmation.html index 3b1972b..02158c8 100644 --- a/application/admin/view/school/classes/order/service_order/shop_confirmation.html +++ b/application/admin/view/school/classes/order/service_order/shop_confirmation.html @@ -40,8 +40,8 @@
- - + +
diff --git a/application/admin/view/school/classes/order/service_order/user_confirmation.html b/application/admin/view/school/classes/order/service_order/user_confirmation.html index e3a7b10..54f465b 100644 --- a/application/admin/view/school/classes/order/service_order/user_confirmation.html +++ b/application/admin/view/school/classes/order/service_order/user_confirmation.html @@ -40,8 +40,8 @@
- - + +
diff --git a/application/admin/view/school/classes/teacher/add.html b/application/admin/view/school/classes/teacher/add.html index ee81caa..c8dfa2c 100644 --- a/application/admin/view/school/classes/teacher/add.html +++ b/application/admin/view/school/classes/teacher/add.html @@ -28,14 +28,14 @@
- +
- +
diff --git a/application/admin/view/school/classes/teacher/edit.html b/application/admin/view/school/classes/teacher/edit.html index 74577b6..996836e 100644 --- a/application/admin/view/school/classes/teacher/edit.html +++ b/application/admin/view/school/classes/teacher/edit.html @@ -28,14 +28,14 @@
- +
- +
diff --git a/application/api/controller/User.php b/application/api/controller/User.php index 9ee2b72..3511448 100644 --- a/application/api/controller/User.php +++ b/application/api/controller/User.php @@ -66,6 +66,10 @@ class User extends Api } catch (\Exception $e){ $this->error($e->getMessage()); } + if(empty($result['openid'])){ + $this->error(__('获取openid失败'),$result); + } + Cache::set('wechat_miniapp_code'.$code.$result['openid'],"1",60); $this->success('',$result); } diff --git a/application/api/controller/school/Activity.php b/application/api/controller/school/Activity.php index 7d1d5ca..d3ba849 100644 --- a/application/api/controller/school/Activity.php +++ b/application/api/controller/school/Activity.php @@ -3,6 +3,7 @@ namespace app\api\controller\school; use app\common\model\school\classes\ActivityDemo; +use app\common\model\school\classes\ClassesLib; use app\common\model\school\classes\Teacher as Teachermodel; /** * 活动接口 @@ -21,7 +22,7 @@ class Activity extends Base protected function _initialize() { - $this->model = new ActivityDemo(); + $this->model = new \app\common\model\school\classes\activity\Activity(); parent::_initialize(); //判断登录用户是否是员工 @@ -45,7 +46,7 @@ class Activity extends Base } try { - $res = $this->model->detail($id); + $res = (new ActivityDemo)->detail($id); } catch (\Exception $e){ // Log::log($e->getMessage()); $this->error($e->getMessage(),['errcode'=>$e->getCode()]); @@ -88,7 +89,7 @@ class Activity extends Base try{ //当前申请状态 - $res = $this->model::allList($page, $limit,$params); + $res = ActivityDemo::allList($page, $limit,$params); // if($user_id =='670153'){ // file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql()); // } @@ -100,5 +101,215 @@ class Activity extends Base } + + + + + + + /** + * @ApiTitle( 通用活动大索索列表) + * @ApiSummary(通用活动大索索列表) + * @ApiRoute(/api/school/activity/activity_list) + * @ApiMethod(GET) + * @ApiParams(name = "keywords", type = "string",required=false,description = "搜索关键字") + * @ApiParams(name = "page", type = "string",required=true,description = "页数") + * @ApiParams(name = "limit", type = "string",required=true,description = "条数") + * @ApiParams(name = "start_time", type = "int",required=false,description = "开始时间10位秒级时间戳") + * @ApiParams(name = "end_time", type = "int",required=false,description = "结束时间10位秒级时间戳") + * @ApiParams(name = "sign_start_time", type = "int",required=false,description = "报名开始时间10位秒级时间戳") + * @ApiParams(name = "sign_end_time", type = "int",required=false,description = "报名结束时间10位秒级时间戳") + * @ApiParams(name = "has_shop", type = "int",required=false,description = "是否查机构") + * @ApiParams(name = "is_expire", type = "int",required=false,description = "是否查过期:1只查过期,2只查不过期,0全查") + * @ApiParams(name = "is_sign_expire", type = "int",required=false,description = "是否查报名过期:1只查过期,2只查不过期,0全查") + * @ApiParams(name = "shop_id", type = "int",required=false,description = "机构店铺id") + * @ApiParams(name = "keyword", type = "string",required=false,description = "关键字搜索") + * @ApiParams(name = "address_type", type = "string",required=false,description = "地址类型:1=按机构,2=独立位置") + * @ApiParams(name = "province", type = "string",required=false,description = "省编号") + * @ApiParams(name = "city", type = "string",required=false,description = "市编号") + * @ApiParams(name = "district", type = "string",required=false,description = "县区编号") + * @ApiParams(name = "status", type = "string",required=false,description = "不传则默认查上架的 状态: 1=上架,2=下架,3=平台下架") + * @ApiParams(name = "recommend", type = "string",required=false,description = "平台推荐:0=否,1=是") + * @ApiParams(name = "hot", type = "string",required=false,description = "平台热门:0=否,1=是") + * @ApiParams(name = "new", type = "string",required=false,description = "平台最新:0=否,1=是") + * @ApiParams(name = "selfhot", type = "string",required=false,description = "机构热门:0=否,1=是") + * @ApiParams(name = "feel", type = "string",required=false,description = "是否免费:0=否,1=是") + * @ApiParams(name = "collect", type = "int",required=false,description = "是否专查我的收藏(需登录):1=是") + * @ApiParams(name = "order", type = "string",required=false,description = " normal=综合排序推薦優先,distance=距离优先,hot=熱門优先,new=平台最新优先,selfhot=机构热门优先,sale=銷量优先,views=浏览量优先,collect=收藏量优先") + * @ApiParams(name = "nearby", type = "string",required=false,description = "限制最大搜索距离(米)") + * @ApiParams(name = "latitude", type = "string",required=false,description = "latitude") + * @ApiParams(name = "longitude", type = "string",required=false,description = "longitude") + * @ApiReturn({ + * + *}) + */ + public function activity_list() + { + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $params =[]; + $params["my_user_id"] = $user_id; + $params["collect"] = $this->request->get('collect/d', 0); //页数 + $params["page"] = $this->request->get('page/d', 1); //页数 + $params["limit"] = $this->request->get('limit/d', 10); //条数 + $params["keywords"] = $this->request->get('keywords/s', ''); //搜索关键字 + $params["shop_id"] = $this->request->get('shop_id/d', ''); //机构店铺id + + $params["keyword"] = $this->request->get('keyword/s', ''); //机构店铺id + + $params["address_type"] = $this->request->get('address_type/s', ''); //机构店铺id + $params["province"] = $this->request->get('province/s', ''); //机构店铺id + + $params["classes_type"] = $this->request->get('classes_type/s', ''); //机构店铺id + + $params["city"] = $this->request->get('city/s', ''); //机构店铺id + $params["district"] = $this->request->get('district/s', ''); //机构店铺id + $params["status"] = $this->request->get('status/s', '-2'); //机构店铺id + $params["recommend"] = $this->request->get('recommend/s', ''); //机构店铺id + $params["hot"] = $this->request->get('hot/s', ''); //机构店铺id + $params["new"] = $this->request->get('new/s', ''); //机构店铺id + $params["selfhot"] = $this->request->get('selfhot/s', ''); //机构店铺id + $params["feel"] = $this->request->get('feel/s', ''); //机构店铺id + + $params["is_expire"] = $this->request->get('is_expire/d', 0); //机构店铺id + $params["is_sign_expire"] = $this->request->get('is_sign_expire/d', 0); //机构店铺id + + + $params["order"] = $this->request->get('order/s', ''); //机构店铺id + $params["nearby"] = $this->request->get('nearby/s', ''); //机构店铺id + $params["has_shop"] = $this->request->get('has_shop/d', ''); //主讲师用户id + + $params["latitude"] = $this->request->get('latitude/s', ''); //机构店铺id + $params["longitude"] = $this->request->get('longitude/s', ''); //机构店铺id + + + $params["sign_start_time"] = $this->request->get('sign_start_time/d', ''); //主讲师用户id + $params["sign_end_time"] = $this->request->get('sign_end_time/d', ''); //机构店铺id + + $params["start_time"] = $this->request->get('start_time/d', ''); //主讲师用户id + $params["end_time"] = $this->request->get('end_time/d', ''); //机构店铺id + +// $params["auth_status"] = $this->request->get('auth_status/d', '-2'); //机构店铺id + + + +// $type = $this->request->get('type/s', ''); //筛选学员和教练单 + + try{ + //当前申请状态 + $res = $this->model::getVaildList($params); +// if($user_id =='670153'){ +// file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql()); +// } + }catch (\Exception $e){ + + $this->error($e->getMessage()); + } + $this->success('查询成功', ["list"=>$res]); + } + + + /** + * @ApiTitle(课程活动规格) + * @ApiSummary(课程活动规格) + * @ApiRoute(/api/school/activity/spec) + * @ApiMethod(GET) + * @ApiParams(name = "id", type = "int",required=true,description = "活动id") + * @ApiParams(name = "user_id", type = "int",required=true,description = "需要查询是否下单的用户id") + * @ApiReturn({ spec 活动规格 }) + */ + public function spec(){ + $user_id = $this->request->get('user_id/d',0); + $id = $this->request->get('id/d',''); + $user = $this->auth->getUser();//登录用户 + + if(empty($id)){ + $this->error(__('缺少必要参数')); + } + + try { + //如果是员工端操作 + if($user_id && $id && $user){ +// //判断是否有操作权限 + $classes_lib_ids = (new \app\common\model\school\classes\activity\Activity)->getActivityAuthIds($user['id']); + //判断当前订单课程是否在此课程授权范围内 + if(!in_array($id,$classes_lib_ids)) throw new \Exception("该课程不在您的授权范围内,无法查看!"); + + } + + + if($user && !$user_id)$user_id = $user['id']; + + + $res = $this->model->spec($id,$user_id); + } catch (\Exception $e){ +// Log::log($e->getMessage()); + $this->error($e->getMessage(),['errcode'=>$e->getCode()]); + } + $this->success('获取成功', ['spec'=>$res]); + } + + + /** + * @ApiTitle(活动详情接口) + * @ApiSummary(活动详情接口) + * @ApiRoute(/api/school/activity/detail) + * @ApiMethod(GET) + * @ApiParams(name = "id", type = "int",required=true,description = "活动id") + * @ApiReturn({ + + * + *}) + */ + public function detail(){ + $id = $this->request->get('id/d',''); + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + if(empty($id)){ + $this->error(__('缺少必要参数')); + } + + try { + $res = $this->model->detail($id,$user_id); + } catch (\Exception $e){ +// Log::log($e->getMessage()); + $this->error($e->getMessage(),['errcode'=>$e->getCode()]); + } + $this->success('获取成功', ['detail' => $res]); + } + + + + + /** + * @ApiTitle( 设置活动收藏和取消收藏) + * @ApiSummary(设置活动收藏和取消收藏) + * @ApiRoute(/api/school/activity/collect) + * @ApiMethod(POST) + * @ApiParams(name = "id", type = "int",required=true,description = "活动id") + * @ApiParams(name = "is_collect", type = "int",required=true,description = "收藏操作:0取消收藏,1收藏") + * @ApiReturn({ + * + *}) + */ + public function collect(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + + $id = $this->request->post('id/d', 0); //搜索关键字 + $collect = $this->request->post('is_collect/d', 0); //搜索关键字 + + try{ + $res = $this->model->collect($id,$user_id,$collect,'user',$user_id,true); + }catch (\Throwable $e){ + $this->error($e->getMessage()); + } + $this->success('查询成功', $res); + } + + } diff --git a/application/api/controller/school/activity/Order.php b/application/api/controller/school/activity/Order.php new file mode 100644 index 0000000..93baec6 --- /dev/null +++ b/application/api/controller/school/activity/Order.php @@ -0,0 +1,224 @@ +model = new OrderModel; + parent::_initialize(); + + //判断登录用户是否是员工 + } + + + /** + * @ApiTitle( 订单详情) + * @ApiSummary(订单详情) + * @ApiMethod(GET) + * @ApiParams(name = "id", type = "int",required=true,description = "订单id或订单号") + * @ApiReturn({ + * + *}) + */ + public function detail(){ + $id = $this->request->get('id/d',''); + + if(empty($id)){ + $this->error(__('缺少必要参数')); + } + + try { + $res = OrderModel::getDetail($id); + } catch (\Exception $e){ +// Log::log($e->getMessage()); + $this->error($e->getMessage(),['errcode'=>$e->getCode()]); + } + $this->success('获取成功', ['detail' => $res]); + } + + + + + + + + + /** + * @ApiTitle( 我的订单列表接口) + * @ApiSummary(我的订单列表接口) + * @ApiMethod(GET) + * @ApiParams(name = "keywords", type = "string",required=false,description = "搜索关键字") + * @ApiParams(name = "page", type = "string",required=true,description = "页数") + * @ApiParams(name = "limit", type = "string",required=true,description = "条数") + * @ApiParams(name = "status", type = "string",required=false,description = "订单状态:-3=已取消,0=待支付,2=已报名待审核,3=已预约,4=售后中,6=已退款,9=已完成") + * @ApiParams(name = "classes_activity_id", type = "int",required=false,description = "课程活动id") + * @ApiReturn({ + * + *}) + */ + public function order_list() + { + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $page = $this->request->get('page/d', 0); //页数 + $limit = $this->request->get('limit/d', 0); //条数 + $keywords = $this->request->get('keywords/s', ''); //搜索关键字 + $status = $this->request->get('status/s', ''); //搜索关键字 + $classes_activity_id = $this->request->get('classes_activity_id/s', ''); //搜索关键字 + + $has_evaluate = $this->request->get('has_evaluate/d', 0); //搜索关键字 +// $type = $this->request->get('type/s', ''); //筛选学员和教练单 + + try{ + //当前申请状态 + $res = $this->model::allList($user_id,$page, $limit,$keywords,$status,$classes_activity_id,$has_evaluate); +// if($user_id =='670153'){ +// file_put_contents("ceshi66.txt",(new AppointmentOrder())->getLastSql()); +// } + }catch (\Exception $e){ + + $this->error($e->getMessage()); + } + $this->success('查询成功', $res); + } + + + /** + * @ApiTitle( 我的订单数量接口) + * @ApiSummary(返回订单各个数量) + * @ApiMethod(GET) + * @ApiParams(name = "classes_activity_id", type = "int",required=false,description = "课程活动id(非必填)") + * @ApiReturn({ + * + *}) + */ + public function order_count(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + + $classes_activity_id = $this->request->get('classes_activity_id/s', ''); //搜索关键字 + try{ + $res = $this->model::orderCount($user_id,$classes_activity_id); + }catch (\Throwable $e){ + $this->error($e->getMessage()); + } + $this->success('查询成功', $res); + } + + + + + + /** + * @ApiTitle( 订单确认/订单计算接口) + * @ApiSummary(订单确认/订单计算接口【有过期时间】) + * @ApiMethod(POST) + * @ApiParams(name = "classes_activity_id", type = "int",required=true,description = "活动id") + * @ApiParams(name = "order_no", type = "string",required=false,description = "缓存key") + * @ApiParams(name = "classes_activity_item_id", type = "int",required=true,description = "活动规定id") + * @ApiParams(name = "is_compute", type = "int",required=false,description = "是否重新计算并更新缓存 默认传1") + * @ApiReturn({ + * + *}) + */ + public function confirm(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $classes_activity_id = $this->request->post('classes_activity_id/d', 0); //课程id + $classes_activity_item_id = $this->request->post('classes_activity_item_id/d', 0); //想同时约的课时id +// $param = urldecode($this->request->post('param/s', "{}")); //参数 + $param = []; + + //参数 + $order_no = $this->request->post('order_no/s', ''); //订单号 + $is_compute = $this->request->post('is_compute/d', 1); //是否重新计算并更新缓存 + try{ + //当前申请状态 + $res = $this->model->confirm($user_id, $classes_activity_id,$classes_activity_item_id,$order_no,$param, $is_compute); + }catch (\Exception $e){ +// Log::log($e->getMessage()); + $this->error($e->getMessage(),['errcode'=>$e->getCode()]); + } + $this->success('执行成功,可用缓存key下单', $res); + } + + + /** + * @ApiTitle( 订单下单接口) + * @ApiSummary(订单下单接口) + * @ApiMethod(POST) + * @ApiParams(name = "order_no", type = "string",required=true,description = "缓存key") + * @ApiReturn({ + * + *}) + */ + public function create(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $order_no = $this->request->post('order_no/s', ''); //订单号 + $remark = $this->request->post('remark/s', ''); //下单备注 +// repeat_filter("appointment\order\create".$user_id, 2); + try{ + //当前申请状态 + $res = $this->model->cacheCreateOrder($order_no,$user_id,$remark,true); + }catch (\Throwable $e){ +// file_put_contents("test.txt",$e->getMessage().$e->getFile().$e->getLine());//写入文件,一般做正式环境测试 +// Log::log($e->getMessage()); + $this->error($e->getMessage(),['errcode'=>$e->getCode()]);; + } + $this->success('订单创建成功,缓存key被消耗', $res); + } + + + + + + /** + * @ApiTitle(活动单取消接口) + * @ApiSummary(活动单取消接口(已完成的单无法取消)) + * @ApiMethod(POST) + * @ApiParams(name = "order_no", type = "string",required=true,description = "订单号") + * @ApiReturn({ + * + *}) + */ + public function cancel(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $order_no = $this->request->post('order_no/s', ''); //订单号 + try{ + //当前申请状态 + $res = $this->model->cancel($order_no,$user_id,true,'user',0,true); + }catch (\Throwable $e){ + $this->error($e->getMessage()); + } + $this->success('活动取消成功', $res); + } + + +} + diff --git a/application/api/controller/school/activity/Pay.php b/application/api/controller/school/activity/Pay.php new file mode 100644 index 0000000..6123537 --- /dev/null +++ b/application/api/controller/school/activity/Pay.php @@ -0,0 +1,325 @@ +model = new OrderModel; + parent::_initialize(); + + //判断登录用户是否是员工 + } + + + /** + * @ApiTitle( 活动第三方支付) + * @ApiSummary(活动第三方支付(微信等支付)) + * @ApiMethod(POST) + * @ApiParams(name = "order_no", type = "string",required=true,description = "订单id或订单号") + * @ApiParams(name = "type", type = "string",required=true,description = "服务商:alipay=支付宝,wechat=微信") + * @ApiParams(name = "platform", type = "string",required=true,description = "平台:web=PC网页支付,wap=H5手机网页支付,app=APP支付,scan=扫码支付,mp=微信公众号支付,miniapp=微信小程序支付") + * @ApiParams(name = "openid", type = "string",required=false,description = "用户openid(非必填)") + * @ApiReturn({ + * + *}) + */ + public function payment() + { + $order_no = $this->request->post('order_no/s'); + $type = $this->request->post('type/s'); + $method = $this->request->post('platform/s'); + $openid = $this->request->post('openid/s', ""); + $platform = $method; + try { + //订单支付前校验 + $this->model->checkPay($order_no,$type); + $order = OrderModel::where('order_no', $order_no)->find(); + $amount = $order["totalprice"]; + } catch (\Exception $e) { + $this->error($e->getMessage()); + } + + + + + + if (!$amount || $amount < 0) { + $this->error("支付金额必须大于0"); + } + + if (!$type || !in_array($type, ['alipay', 'wechat'])) { + $this->error("支付类型不能为空"); + } + + if (in_array($method, ['miniapp', 'mp']) && !$openid) { + + // 微信公众号,小程序支付,必须有 openid + if (isset($openid) && $openid) { + // 如果传的有 openid + } else { + // 没有 openid 默认拿下单人的 openid + $oauth = Third::where([ + 'user_id' => $order->user_id, + 'platform' => $type, + 'apptype' => $platform + ])->find(); + + $openid = $oauth ? $oauth->openid : ''; + } + + if (!$openid) { + // 缺少 openid + $this->error("授权过期,请您重新授权登录"); + } + } + + //订单号 + $out_trade_no = $order_no; + + //订单标题 + $title = '活动订单['.$out_trade_no."]支付"; + + //回调链接 + $notifyurl = $this->request->root(true) . '/api/school.activity.pay/notifyx/paytype/' . $type. '/platform/' . $method; + $returnurl = $this->request->root(true) . '/api/school.activity.pay/returnx/paytype/' . $type . '/out_trade_no/' . $out_trade_no; + + $response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method, $openid); + + $this->success('查询成功', ["paydata"=>$response]); + +// return $response; + } + + /** + * @ApiTitle( 第三方支付支付成功回调) + * @ApiSummary(第三方支付成功回调) + * @ApiMethod(GET) + * @ApiReturn({ + * + *}) + */ + public function notifyx() + { + $paytype = $this->request->param('paytype'); + $platform = $this->request->param('platform'); + $pay = Service::checkNotify($paytype); + if (!$pay) { + return json(['code' => 'FAIL', 'message' => '失败'], 500, ['Content-Type' => 'application/json']); + } + $payment = $paytype; + // 获取回调数据,V3和V2的回调接收不同 + $data = Service::isVersionV3() ? $pay->callback() : $pay->verify(); + + + + Log::write('notifyx-result:'. json_encode($data)); + + $out_trade_no = $data['out_trade_no']; + $out_refund_no = $data['out_biz_no'] ?? ''; + + + + // 判断是否是支付宝退款(支付宝退款成功会通知该接口) + if ($paytype == 'alipay' // 支付宝支付 + && $data['notify_type'] == 'trade_status_sync' // 同步交易状态 + && $data['trade_status'] == 'TRADE_CLOSED' // 交易关闭 + && $out_refund_no // 退款单号 + ) { + // 退款回调 + +// $this->refundFinish($out_trade_no, $out_refund_no,$platform); + + return $pay->success()->send(); + } + + + + + + + // 判断支付宝微信是否是支付成功状态,如果不是,直接返回响应 + if ($payment == 'alipay' && $data['trade_status'] != 'TRADE_SUCCESS') { + // 不是交易成功的通知,直接返回成功 + return $pay->success()->send(); + } + if ($payment == 'wechat' && ($data['result_code'] != 'SUCCESS' || $data['return_code'] != 'SUCCESS')) { + // 微信交易未成功,返回 false,让微信再次通知 + return false; + } + + + try { + //微信支付V3返回和V2不同 + if (Service::isVersionV3() && $paytype === 'wechat') { + $data = $data['resource']['ciphertext']; + $data['total_fee'] = $data['amount']['total']; + } + + \think\Log::record($data); + + $payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100; + $out_trade_no = $data['out_trade_no']; + + \think\Log::record("回调成功,订单号:{$out_trade_no},金额:{$payamount}"); + + //你可以在此编写订单逻辑 + + // 支付成功流程 + //获取支付金额、订单号 + $pay_fee = $payment == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100; + + //你可以在此编写订单逻辑 + $order = OrderModel::getNopayOrder($out_trade_no); + + if (!$order || $order["status"] != '0') { + // 订单不存在,或者订单已支付 + return $pay->success()->send(); + } + $notify = [ + 'order_no' => $data['out_trade_no'], + 'transaction_id' => $payment == 'alipay' ? $data['trade_no'] : $data['transaction_id'], + 'notify_time' => date('Y-m-d H:i:s', strtotime($data['time_end'])), + 'buyer_email' => $payment == 'alipay' ? $data['buyer_logon_id'] : $data['openid'], + 'payment_json' => json_encode($data->all()), + 'pay_fee' => $pay_fee, + 'pay_type' => $payment, // 支付方式 + 'platform' => $platform, + ]; + + $this->model->paySuccess($order['order_no'],$notify,$pay_fee,true,true); + + + + } catch (Exception $e) { + \think\Log::record("回调逻辑处理错误:" . $e->getMessage(), "error"); + } + + //下面这句必须要执行,且在此之前不能有任何输出 + if (Service::isVersionV3()) { + return $pay->success()->getBody()->getContents(); + } else { + return $pay->success()->send(); + } + } + + /** + * 支付返回,网页支付版本(小程序忽略) + */ + public function returnx() + { + $paytype = $this->request->param('paytype'); + $out_trade_no = $this->request->param('out_trade_no'); + $pay = Service::checkReturn($paytype); + if (!$pay) { + $this->error('签名错误', ''); + } + + //你可以在这里定义你的提示信息,但切记不可在此编写逻辑 + $this->success("请返回网站查看支付结果", addon_url("epay/index/index")); + } + + + /** + * 支付返回 + */ + public function notifyRefund($callback) + { + $pay = $this->getPay(); + + try { + $data = $pay->verify(null, true); // 是的,验签就这么简单! + + $result = $callback($data, $pay); + + // Log::debug('Wechat notify', $data->all()); + } catch (\Exception $e) { + // $e->getMessage(); + } + + return $result; + } + + + /** + * 退款成功回调 + */ + public function notifyr() + { + Log::write('notifyreturn-comein:'); + + $payment = $this->request->param('payment'); + $platform = $this->request->param('platform'); + + $config = Service::getConfig('wechat'); + + $notify_url = request()->domain() . '/api/school.activity.pay/notifyr/payment/' . $payment . '/platform/' . $platform; + + $config['notify_url'] = $notify_url; + $pay = \Yansongda\Pay\Pay::wechat($config); + + try { + $data = $pay->verify(null, true); // 是的,验签就这么简单! + + Log::write('notifyr-result:' . json_encode($data)); + + $out_refund_no = $data['out_refund_no']; + $out_trade_no = $data['out_trade_no']; + + // 退款 + $this->refundFinish($out_trade_no, $out_refund_no,$platform); + + + return $pay->success()->send(); + // Log::debug('Wechat notify', $data->all()); + } catch (\Exception $e) { + Log::write('notifyreturn-error:' . json_encode($e->getMessage())); + } + return $pay->success()->send(); + } + + + private function refundFinish($out_trade_no, $out_refund_no,$platform) { + +// $order = Order::where('order_sn', $out_trade_no)->find(); +// $refundLog = \app\admin\model\shopro\order\RefundLog::where('refund_sn', $out_refund_no)->find(); +// +// if (!$order || !$refundLog || $refundLog->status != 0) { +// // 订单不存在,或者订单已退款 +// return true; +// } +// +// $item = \app\admin\model\shopro\order\OrderItem::where('id', $refundLog->order_item_id)->find(); +// +// Db::transaction(function () use ($order, $item, $refundLog) { +// \app\admin\model\shopro\order\Order::refundFinish($order, $item, $refundLog); +// }); + $this->model::refundSuccess($out_refund_no,true); + return true; + } + + + +} \ No newline at end of file diff --git a/application/api/controller/school/worker/Base.php b/application/api/controller/school/worker/Base.php index 5f20faa..0247449 100644 --- a/application/api/controller/school/worker/Base.php +++ b/application/api/controller/school/worker/Base.php @@ -3,6 +3,7 @@ namespace app\api\controller\school\worker; use app\common\controller\Api; +use app\common\model\school\classes\activity\Activity; use app\common\model\school\classes\ClassesLib; use app\common\model\school\classes\Teacher; use app\common\model\school\classes\Verification; @@ -11,6 +12,7 @@ class Base extends Api { protected $classes_lib_ids = []; + protected $classes_activity_ids = []; protected $shop_id = 0; /** @@ -37,9 +39,10 @@ class Base extends Api $this->error($e->getMessage(),['errcode'=>30003]); } $this->classes_lib_ids = (new ClassesLib)->getClassesAuthIds($user_id); + $this->classes_activity_ids = (new Activity())->getActivityAuthIds($user_id); //如果没有任何可管理的classes_lib_id 则返回错误 - if(!$this->classes_lib_ids && !$this->shop_id)$this->error("您没有员工权限访问该接口!",['errcode'=>30003]); + if(!$this->classes_lib_ids && !$this->shop_id && !$this->classes_activity_ids)$this->error("您没有员工权限访问该接口!",['errcode'=>30003]); } diff --git a/application/api/controller/school/worker/activity/Order.php b/application/api/controller/school/worker/activity/Order.php new file mode 100644 index 0000000..d3ead0a --- /dev/null +++ b/application/api/controller/school/worker/activity/Order.php @@ -0,0 +1,152 @@ +model = new OrderModel; + parent::_initialize(); + + //判断登录用户是否是员工 + } + + + /** + * @ApiTitle( 订单详情) + * @ApiSummary(订单详情) + * @ApiMethod(GET) + * @ApiParams(name = "id", type = "int",required=true,description = "订单id或订单号") + * @ApiReturn({ + * + *}) + */ + public function detail(){ + $id = $this->request->get('id/s',''); + + if(empty($id)){ + $this->error(__('缺少必要参数')); + } + + try { + $res = OrderModel::getDetail($id,$this->classes_activity_ids); + if(!$res)throw new \Exception('您无操作权限!',40003); + } catch (\Exception $e){ +// Log::log($e->getMessage()); + $this->error($e->getMessage(),['errcode'=>$e->getCode()]); + } + $this->success('获取成功', ['detail' => $res]); + } + + + + + /** + * @ApiTitle( 我的订单列表接口) + * @ApiSummary(我的订单列表接口) + * @ApiMethod(GET) + * @ApiParams(name = "keywords", type = "string",required=false,description = "搜索关键字") + * @ApiParams(name = "page", type = "string",required=true,description = "页数") + * @ApiParams(name = "limit", type = "string",required=true,description = "条数") + * @ApiParams(name = "status", type = "string",required=false,description = "状态搜索条件:-3=已取消,0=待支付,2=已报名待审核,3=已预约,4=售后中,6=已退款,9=已完成") + * @ApiParams(name = "classes_activity_id", type = "int",required=false,description = "课程活动id") + * @ApiReturn({ + * + *}) + */ + public function order_list() + { + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $page = $this->request->get('page/d', 0); //页数 + $limit = $this->request->get('limit/d', 0); //条数 + $keywords = $this->request->get('keywords/s', ''); //搜索关键字 + $status = $this->request->get('status/s', ''); //搜索关键字 + $classes_activity_id = $this->request->get('classes_activity_id/s', ''); //搜索关键字 +// $type = $this->request->get('type/s', ''); //筛选学员和教练单 + + + try{ + //当前申请状态 + $res = $this->model::workList($user_id,$page, $limit,$keywords,$status,$classes_activity_id,$this->classes_activity_ids); +// var_dump($this->model->getLastSql()); + }catch (\Exception $e){ + + $this->error($e->getMessage()); + } + $this->success('查询成功', $res); + } + + + /** + * @ApiTitle( 我的订单数量接口) + * @ApiSummary(返回订单各个数量) + * @ApiMethod(GET) + * @ApiParams(name = "classes_activity_id", type = "int",required=false,description = "课程活动id") + * @ApiReturn({ + * + *}) + */ + public function order_count(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + + $classes_activity_id = $this->request->get('classes_activity_id/s', ''); //搜索关键字 + try{ + $res = $this->model::workCount($classes_activity_id,$this->classes_activity_ids); + }catch (\Throwable $e){ + $this->error($e->getMessage()); + } + $this->success('查询成功', $res); + } + + + + + + /** + * @ApiTitle( 员工代操作:活动订单取消接口) + * @ApiSummary(活动订单取消接口(已支付单无法取消,要走售后)) + * @ApiMethod(POST) + * @ApiParams(name = "order_no", type = "string",required=true,description = "订单号") + * @ApiReturn({ + * + *}) + */ + public function cancel(){ + $user_id = 0; + $user = $this->auth->getUser();//登录用户 + if($user)$user_id = $user['id']; + $order_no = $this->request->post('order_no/s', ''); //订单号 + try{ + //当前申请状态 + $res = $this->model->cancel($order_no,0,true,'user',$user_id,true); + }catch (\Throwable $e){ + $this->error($e->getMessage()); + } + $this->success('预约课时取消成功', $res); + } + +} + diff --git a/application/common.php b/application/common.php index 9570b64..e8adc68 100644 --- a/application/common.php +++ b/application/common.php @@ -571,11 +571,16 @@ if (!function_exists('de_code')) { } } - +if (!function_exists('matchLatLng')) { + function matchLatLng($latlng) { + $match = "/^\d{1,3}\.\d{1,30}$/"; + return preg_match($match, $latlng) ? $latlng : 0; + } +} if (!function_exists('getDistanceBuilder')) { - function getDistanceBuilder($lat, $lng) { - return "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN((". matchLatLng($lat) . " * PI() / 180 - latitude * PI() / 180) / 2), 2) + COS(". matchLatLng($lat). " * PI() / 180) * COS(latitude * PI() / 180) * POW(SIN((". matchLatLng($lng). " * PI() / 180 - longitude * PI() / 180) / 2), 2))) * 1000) AS distance"; + function getDistanceBuilder($lat, $lng,$a="") { + return "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN((". matchLatLng($lat) . " * PI() / 180 - {$a}latitude * PI() / 180) / 2), 2) + COS(". matchLatLng($lat). " * PI() / 180) * COS({$a}latitude * PI() / 180) * POW(SIN((". matchLatLng($lng). " * PI() / 180 - {$a}longitude * PI() / 180) / 2), 2))) * 1000) AS distance"; } } diff --git a/application/common/hooks.php b/application/common/hooks.php index d52493f..f156aa1 100644 --- a/application/common/hooks.php +++ b/application/common/hooks.php @@ -27,16 +27,6 @@ $defaultHooks = [ 'app\\common\\listener\\classesorder\\OrderHook' ], -// - // app\common\listener\classesorder - - // 订单取消 -// 'order_cancel_before' => [ // 订单取消前 -// ], -// 'order_cancel_after' => [ // 订单取消后 -// 'addons\\shopro\\listener\\order\\Invalid' -// ], - ]; @@ -185,6 +175,43 @@ $activityHooks = [ 'activity_view_after' => [ // 活动触发浏览后 'app\\common\\listener\\classes\\ActivityHook' ], + 'activity_collect_success_after' => [ // 课程收藏后 + 'app\\common\\listener\\classes\\ActivityHook' + ], + 'activity_collect_cancel_after' => [ // 课程取消收藏后 + 'app\\common\\listener\\classes\\ActivityHook' + ], + +]; + + + +$activityOrderHooks = [ + // 订单创建 + 'classes_activity_order_create_before' => [ // 订单创建前 + 'app\\common\\listener\\activityorder\\OrderHook' + ], + 'classes_activity_order_create_after' => [ // 订单创建后 + 'app\\common\\listener\\activityorder\\OrderHook' + ], + 'classes_activity_order_payed_after' => [ // 订单支付成功 + 'app\\common\\listener\\activityorder\\OrderHook' + ], + 'classes_activity_order_cancel_after' => [ // 订单取消后 + 'app\\common\\listener\\activityorder\\OrderHook' + ], +// +// 'classes_order_finish_after' => [ // 订单完成后 +// 'app\\common\\listener\\classesorder\\OrderHook' +// ], +// +// 'classes_order_evaluate_after'=> [ // 订单评价后 +// 'app\\common\\listener\\classesorder\\OrderHook' +// ], +// +// 'classes_order_evaluate_update_after'=> [ // 订单评价修改后 +// 'app\\common\\listener\\classesorder\\OrderHook' +// ], ]; @@ -202,6 +229,8 @@ $defaultHooks = array_merge_recursive($defaultHooks, $userHooks); $defaultHooks = array_merge_recursive($defaultHooks, $serviceHooks); $defaultHooks = array_merge_recursive($defaultHooks, $activityHooks); +$defaultHooks = array_merge_recursive($defaultHooks, $activityOrderHooks); + return $defaultHooks; diff --git a/application/common/listener/activityorder/OrderHook.php b/application/common/listener/activityorder/OrderHook.php new file mode 100644 index 0000000..97029e6 --- /dev/null +++ b/application/common/listener/activityorder/OrderHook.php @@ -0,0 +1,78 @@ +$user_id, 'classes_activity_id'=>$classes_activity_id,'classes_activity_item_id'=>$classes_activity_item_id,'param'=>$param, 'order_no'=>$order_no, 'price_info'=>$price_info] = $params; + } + + + // 订单创建成功后 + public function classesActivityOrderCreateAfter(&$params) + { + ["order"=>$order] = $params; + + + } + + + + // 订单支付成功后 + public function classesActivityOrderPayedAfter(&$params) + { + ["order"=>$order] = $params; + + + + } + + // 订单取消成功后 + public function classesActivityOrderCancelAfter(&$params) + { + ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; + + + + + } + + // 订单完成后 + public function classesActivityOrderFinishAfter(&$params) + { + + } + + + + // 订单评价成功后 + public function classesActivityOrderEvaluateAfter(&$params) + { + ['order' => $order,"classes_evaluate"=>$classes_evaluate,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; + + + } + + + + + // 订单评价更新后 + public function classesOrderEvaluateUpdateAfter(&$params) + { + ['order' => $order,"classes_evaluate"=>$classes_evaluate,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; + + + } + + + + + + +} \ No newline at end of file diff --git a/application/common/listener/classes/ActivityHook.php b/application/common/listener/classes/ActivityHook.php index 02176f0..9e33699 100644 --- a/application/common/listener/classes/ActivityHook.php +++ b/application/common/listener/classes/ActivityHook.php @@ -105,11 +105,24 @@ class ActivityHook public function activityViewAfter(&$params) { - ['classes' => $classes,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; + ['activity' => $activity,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; } + public function activityCollectSuccessAfter(&$params) + { + ['activity' => $activity,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; + + } + + public function activityCollectCancelAfter(&$params) + { + ['activity' => $activity,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id] = $params; + + } + + } \ No newline at end of file diff --git a/application/common/model/school/classes/ClassesLib.php b/application/common/model/school/classes/ClassesLib.php index de92900..df623ab 100644 --- a/application/common/model/school/classes/ClassesLib.php +++ b/application/common/model/school/classes/ClassesLib.php @@ -9,6 +9,7 @@ use app\common\model\dyqc\ManystoreShop; use app\common\model\manystore\Shop; use app\common\model\manystore\UserAuth; use app\common\model\school\Area; +use app\common\model\school\classes\activity\Activity; use app\common\model\school\classes\lib\Spec; use app\common\model\school\classes\order\OrderDetail; use app\common\model\school\classes\order\ServiceOrder; @@ -127,7 +128,8 @@ class ClassesLib extends BaseModel self::afterInsert(function ($row) { if (!empty($row['weigh'])) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); } }); } @@ -682,7 +684,7 @@ $user_unpaid_order = $user_paid_order =null; //得到距离 if (isset($latitude) && isset($longitude) && $latitude && $longitude) { - $field .= ', '.getDistanceBuilder($latitude, $longitude); + $field .= ', '.getDistanceBuilder($latitude, $longitude,$a); }else{ $field .= ', 0 as distance'; } @@ -836,6 +838,15 @@ $user_unpaid_order = $user_paid_order =null; } + if(isset($order) && $order == "distance"){ + $selfetch = $selfetch->where("{$a}longitude","not null") + ->where("{$a}latitude","not null") + ->where("{$a}longitude","<>","") + ->where("{$a}latitude","<>","") + ->where("{$a}longitude","<>","null") + ->where("{$a}latitude","<>","null"); + } + @@ -878,6 +889,7 @@ $user_unpaid_order = $user_paid_order =null; } if(isset($nearby) && $nearby) { + throw new \Exception("现版本不支持"); $selfetch = $selfetch->having("distance <= {$nearby}"); } @@ -887,12 +899,12 @@ $user_unpaid_order = $user_paid_order =null; $selfetch = $selfetch->paginate($per_page); //额外附加数据 - foreach ($selfetch as $row) { //迭代器魔术方法遍历,填值自动引用传值 + foreach ($selfetch as &$row) { //迭代器魔术方法遍历,填值自动引用传值 //设置是否已收藏 $row->is_collect = in_array($row->id,$collect_classes_lib_ids) ? 1 : 0; if($row->is_collect){ - $row["collect"] = Collect::where("user_id",$my_user_id)->find(); + $row["collect"] = Collect::where("user_id",$my_user_id)->where("classes_lib_id",$row->id)->find(); } $classes_label_ids = $row['classes_label_ids']; $classes_cate_ids = $row['classes_cate_ids']; @@ -915,6 +927,7 @@ $user_unpaid_order = $user_paid_order =null; $row['classes_type_name'] = $classes_type; } +// var_dump(self::getLastSql());die; return $selfetch; } @@ -924,6 +937,28 @@ $user_unpaid_order = $user_paid_order =null; //更新课程规格库存 $classes_lib = self::get($classes_lib_id); if($classes_lib){ + + $classes_lib->sale = Order::where("classes_lib_id",$classes_lib["id"])->where("status","<>","-3")->count(); + + //遍历课程课时规格,更新课时统计数据 + $specs = $classes_lib->specs; + if($specs){ + foreach ($specs as $spec){ + // '已核销人数', + $spec->verification_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_spec_id",$spec["id"])->where("status","=","3")->count(); + //已报名人数 + $spec->sign_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_spec_id",$spec["id"])->where("status","in",["-1","0","3"])->count(); + $spec->save(); + } + + } + //统计课程总报名和总核销 + $classes_lib->sign_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_id",$classes_lib["id"])->where("status","in",["-1","0","3"])->count(); + $classes_lib->verification_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_id",$classes_lib["id"])->where("status","=","3")->count(); + + + + //所有课时加起来 $classes_lib->limit_num = ClassesSpec::where("classes_lib_id",$classes_lib_id)->sum( "limit_num"); //更新虚拟用户数据 @@ -1478,8 +1513,13 @@ $user_unpaid_order = $user_paid_order =null; $help_user_info = User::where('id',$oper_id)->find(); if(!$help_user_info) throw new \Exception("代下单员工不存在!"); $classes_lib_ids = (new ClassesLib)->getClassesAuthIds($oper_id); + $activity_lib_ids = (new Activity())->getActivityAuthIds($oper_id); + if(!$shop_id && $classes_lib_ids)$shop_id = self::where("id" ,"in", $classes_lib_ids)->value("shop_id"); + if(!$shop_id && $activity_lib_ids)$shop_id = Activity::where("id" ,"in", $activity_lib_ids)->value("shop_id"); + + //判断当前订单课程是否在此课程授权范围内 if($classes && !in_array($classes_id,$classes_lib_ids)) throw new \Exception("该课程不在您的授权范围内,无法代操作!"); diff --git a/application/common/model/school/classes/activity/Activity.php b/application/common/model/school/classes/activity/Activity.php index 5e76ce2..ddc1ba1 100644 --- a/application/common/model/school/classes/activity/Activity.php +++ b/application/common/model/school/classes/activity/Activity.php @@ -3,11 +3,19 @@ namespace app\common\model\school\classes\activity; use app\admin\model\manystore\Shop; +use app\common\model\manystore\UserAuth; use app\common\model\school\classes\activity\order\Order; use app\common\model\BaseModel; use app\common\model\dyqc\ManystoreShop; use app\common\model\school\Area; +use app\common\model\school\classes\Cate; +use app\common\model\school\classes\ClassesLib; use app\common\model\school\classes\ClassesSpec; +use app\common\model\school\classes\Collect; +use app\common\model\school\classes\Label; +use app\common\model\school\classes\Type; +use app\common\model\school\classes\Verification; +use app\common\model\school\classes\VirtualUser; use app\manystore\model\Manystore; use think\Model; use traits\model\SoftDelete; @@ -45,14 +53,27 @@ class Activity extends BaseModel 'expirestatus_text', 'add_type_text', 'has_expire', + 'has_sign_expire', ]; - public function getHasExpireList() + + public function getHasSignExpireAttr($value, $data) { - return ['1' => __('Has_expire 1'), '2' => __('Has_expire 2')]; + $sign_start_time = (isset($data['sign_start_time']) ? $data['sign_start_time'] : ''); + $sign_end_time = (isset($data['sign_end_time']) ? $data['sign_end_time'] : ''); + + if(!$sign_end_time) return '2'; + + if( $sign_end_time < time()) { + return '1'; + }else{ + return '2'; + } + } + public function getHasExpireAttr($value, $data) { $end_time = (isset($data['end_time']) ? $data['end_time'] : ''); @@ -65,6 +86,38 @@ class Activity extends BaseModel } } + + + + + + public function getDistanceTextAttr($value, $data) { + $distance_text = ''; + $distance = $data['distance'] ?? 0; + + switch (true) { + case $distance >= 1000; + $distance_text = round(($distance / 1000), 2) . 'km'; + break; + default : + $distance_text = $distance . 'm'; + break; + + } + + return $distance_text; + } + + + public function getHasExpireList() + { + return ['1' => __('Has_expire 1'), '2' => __('Has_expire 2')]; + } + + + + + protected static function init() @@ -72,7 +125,8 @@ class Activity extends BaseModel self::afterInsert(function ($row) { if (!$row['weigh']) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); } }); } @@ -231,6 +285,43 @@ class Activity extends BaseModel } + + + public function getHeadimageAttr($value, $data) + { + if (!empty($value)) return cdnurl($value, true); + } + + + public function getImagesAttr($value, $data) + { + $imagesArray = []; + if (!empty($value)) { + $imagesArray = explode(',', $value); + foreach ($imagesArray as &$v) { + $v = cdnurl($v, true); + } + return $imagesArray; + } + return $imagesArray; + } + + + + + public function setImagesAttr($value, $data) + { + $imagesArray = $value; + if (!empty($value) && is_array($value)) { + //转成逗号拼接字符串 + $imagesArray = implode(',', $value); + } + return $imagesArray; + } + + + + public function manystore() { return $this->belongsTo(Manystore::class, 'manystore_id', 'id', [], 'LEFT')->setEagerlyType(0); @@ -690,7 +781,7 @@ class Activity extends BaseModel $activity->save(); - + self::update_classes($activity["id"]); if($trans){ self::commitTrans(); } @@ -848,4 +939,635 @@ class Activity extends BaseModel + + /**得到基础条件 + * @param $status + * @param null $model + * @param string $alisa + */ + public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false) + { + + if (!$model) { + $model = new static; + if ($alisa&&!$with) $model = $model->alias($alisa); + } + if ($alisa) $alisa = $alisa . '.'; + $tableFields = (new static)->getTableFields(); + foreach ($tableFields as $fields) + { + if(in_array($fields, ['status','title','address_city','address','address_detail','start_time','end_time','sign_start_time','sign_end_time']))continue; +// if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]); + + if (isset($whereData[$fields]) && $whereData[$fields]){ + if(is_array($whereData[$fields])){ + $model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]); + }else{ + $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]); + } + + } + + + } + if (isset($whereData['status']) && $whereData['status']) $model = $model->where("{$alisa}status", 'in', $whereData['status']); + if (isset($whereData['not_status']) && $whereData['not_status']) $model = $model->where("{$alisa}status", 'not in', $whereData['not_status']); + + + if (isset($whereData['keywords'])&&$whereData['keywords']) $model = $model->where("{$alisa}title|{$alisa}id|{$alisa}address|{$alisa}address_detail", '=', $whereData['keywords']); + if (isset($whereData['time'])&&$whereData['time']){ + $model = $model->time(["{$alisa}createtime",$whereData['time']]); + } + + return $model; + } + + + + + + /** 课程详情 + * @param $id + * @throws \think\exception\DbException + */ + public function detail($id,$user_id=0,$oper_type='user',$trans=false){ + $self = $this->get($id,['shop','items']); + + //是否收藏 + $self['is_collect'] = 0; + //是否购买 + $self['have_buy'] = 0; + if($user_id){ + //判断是否收藏 + $self['is_collect'] = Collect::where("user_id",$user_id)->where("classes_activity_id",$id)->count() ? 1:0 ; + + //判断用户是否已报名 + $self['have_buy'] = Order::where("classes_activity_id",$id) + ->where("user_id",$user_id) + ->where("status","not in",["-3","6","9"]) + ->count() ? 1 : 0 ; + } + + // + $this->setViews($id,$user_id,$oper_type,$user_id,$trans); +// $self->getRelation('user')->visible(['nickname','realname','mobile','avatar']); + //参与人数 = 虚拟人数 + 平台人数 + return $self; + } + + /**设置浏览量 + * @param $id + * @param int $user_id + * @param bool $check + * @param bool $trans + * @throws \Exception + */ + public function setViews($id,$user_id,$oper_type='user',$oper_id=0,$trans=false){ + $classes_lib = self::where("id",$id)->find(); + if(!$classes_lib)throw new \Exception("找不到活动!"); + //判断逻辑 + if($trans){ + self::beginTrans(); + } + + try{ + //事务逻辑 + $classes_lib->views = $classes_lib->views + 1; + //查询是否已收藏 + $classes_lib->save(); + + + //调用事件 + $data = ['activity' => $classes_lib,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; + \think\Hook::listen('activity_view_after', $data); + + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + return $classes_lib; + } + + + /**课程规格 + * @param $id + * + */ + public function spec($id,$user_id=0){ + //课程规格 + $spec_data = ActivityItem::where("classes_activity_id",$id)->where("status",'1')->order("weigh desc,id desc")->select(); + foreach ($spec_data as &$spec){ + //默认未下单预约 + $spec["user_reservation"] = null; + if($user_id){ + $spec["user_reservation"] = Order::where("classes_activity_id",$id)->where("classes_activity_item_id",$spec['id'])->where("user_id",$user_id)->where("status","not in",["-3","6","9"])->find(); + } + + } + return $spec_data; + } + + + + + /** + * 获取所有活动列表 + */ + public static function getVaildList($params) { + extract($params); + $a = (new self)->getWithAlisaName().'.'; + $with = ['items']; +// if (isset($has_shop) && $has_shop) { + $with[] = 'shop'; +// } + + + +// $cate_list = Cate::where("status",'1')->column("name","id"); +// $label_list = Label::where("status",'1')->column("name","id"); +// $type_list = Type::where("status",'1')->column("name","id"); + $selfetch = self::with($with); + // 查询自提点 + if($status == "-2"){ + $selfetch = $selfetch->where($a.'status', '1'); + } + +// if($auth_status == "-2"){ +// $selfetch = $selfetch->where("{$a}auth_status",1); +// } + + + + $order = $order?? 'normal'; + $per_page = $limit ?? 10; + + + $field = "{$a}start_time,{$a}end_time,{$a}sign_start_time,{$a}sign_end_time,{$a}id,{$a}shop_id,{$a}title,{$a}headimage,{$a}images,{$a}address_type,{$a}province,{$a}city,{$a}district,{$a}address,{$a}address_detail,{$a}longitude,{$a}latitude,{$a}sale,{$a}price,{$a}status,{$a}weigh,{$a}recommend,{$a}hot,{$a}new,{$a}selfhot,{$a}createtime,{$a}feel,{$a}sign_num,{$a}verification_num"; + + //得到距离 + if (isset($latitude) && isset($longitude) && $latitude && $longitude) { + $field .= ', '.getDistanceBuilder($latitude, $longitude,$a); + }else{ + $field .= ', 0 as distance'; + } + + //得到每个 + + + $selfetch = $selfetch->field($field); + if (isset($keywords) && $keywords) { + $selfetch = $selfetch->where("{$a}title|{$a}address|{$a}address_detail|{$a}address_city", 'like', '%' . $keywords . '%'); + } + + + if(isset($start_time) && isset($end_time) && ($end_time || $start_time)) { + if($start_time){ + $selfetch = $selfetch->where("{$a}start_time", '>=', $start_time); + } + if($end_time){ + $selfetch = $selfetch->where("{$a}end_time", '<=', $end_time); + } + } + + + if(isset($sign_start_time) && isset($sign_end_time) && ($sign_end_time || $sign_start_time)) { + if($sign_start_time){ + $selfetch = $selfetch->where("{$a}sign_start_time", '>=', $sign_start_time); + } + if($sign_end_time){ + $selfetch = $selfetch->where("{$a}sign_end_time", '<=', $sign_end_time); + } + } + + + + // is_expire 是否查过期:1只查过期,2只查不过期,0全查 + if(isset($is_expire) && $is_expire) { + if($is_expire == 1){ + $selfetch = $selfetch->where("{$a}end_time", '<', time()); + }else{ + $selfetch = $selfetch->where("{$a}end_time", '>=', time()); + } + + } + + // is_expire 是否查过期:1只查过期,2只查不过期,0全查 + if(isset($is_sign_expire) && $is_sign_expire) { + if($is_sign_expire == 1){ + $selfetch = $selfetch->where("{$a}sign_end_time", '<', time()); + }else{ + $selfetch = $selfetch->where("{$a}sign_end_time", '>=', time()); + } + + } + + + + + if (isset($manystore_id) && $manystore_id) { + $selfetch = $selfetch->where("{$a}manystore_id", 'in', ''.$manystore_id); + } + + if (isset($shop_id) && $shop_id) { + $selfetch = $selfetch->where("{$a}shop_id", 'in', ''.$shop_id); + } + + if (isset($user_id) && $user_id) { + $selfetch = $selfetch->where("{$a}user_id", 'in', ''.$user_id); + } + + if (isset($my) && $my && isset($my_user_id) && $my_user_id) { + $selfetch = $selfetch->where("{$a}user_id", 'in', ''.$my_user_id); + } + + + +// if (isset($teacher_id) && $teacher_id) { +// $selfetch = $selfetch->where("{$a}teacher_id", 'in', ''.$teacher_id); +// } + +// if (isset($type) && $type) { +// $selfetch = $selfetch->where("{$a}type", 'in', ''.$type); +// } + + if (isset($address_type) && $address_type) { + $selfetch = $selfetch->where("{$a}address_type", 'in', ''.$address_type); + } + + + if (isset($recommend) && $recommend) { + $selfetch = $selfetch->where("{$a}recommend", 'in', ''.$recommend); + } + + + if (isset($hot) && $hot) { + $selfetch = $selfetch->where("{$a}hot", 'in', ''.$hot); + } + + + if (isset($new) && $new) { + $selfetch = $selfetch->where("{$a}new", 'in', ''.$new); + } + + if (isset($feel) && $feel) { + $selfetch = $selfetch->where("{$a}feel", 'in', ''.$feel); + } + +// //设置订单信息 +// if(isset($auth_status) && $auth_status != -1 && $auth_status != -2){ +// $selfetch = $selfetch->where("{$a}auth_status", 'in', ''.$auth_status); +// } + + //设置订单信息 + if(isset($status) && $status != -1 && $status != -2){ + $selfetch = $selfetch->where("{$a}status", 'in', ''.$status); + } + + + + //区域搜索 + if (isset($province) && $province) { + $selfetch = $selfetch->where("{$a}province", 'in', ''.$province); + } + + + if (isset($city) && $city) { + $selfetch = $selfetch->where("{$a}city", 'in', ''.$city); + } + + if (isset($district) && $district) { + $selfetch = $selfetch->where("{$a}district", 'in', ''.$district); + } + + + + + + + + + + +// if (isset($self_label_tag) && $self_label_tag) { +// $self_label_tag = implode("|",explode(',',$self_label_tag)); +// $selfetch = $selfetch->whereRaw(" {$a}self_label_tag REGEXP '({$self_label_tag})'"); +// } +// +// if (isset($classes_type) && $classes_type) { +// $classes_type = implode("|",explode(',',$classes_type)); +// $selfetch = $selfetch->whereRaw(" {$a}classes_type REGEXP '({$classes_type})'"); +// } + + + + +// if (isset($classes_cate_ids) && $classes_cate_ids) { +// $classes_cate_ids = implode("|",explode(',',$classes_cate_ids)); +// $selfetch = $selfetch->whereRaw(" {$a}classes_cate_ids REGEXP '({$classes_cate_ids})'"); +// } +// +// if (isset($classes_label_ids) && $classes_label_ids) { +// $classes_label_ids = implode("|",explode(',',$classes_label_ids)); +// $selfetch = $selfetch->whereRaw(" {$a}classes_label_ids REGEXP '({$classes_label_ids})'"); +// } + $collect_classes_lib_ids = [-1]; + //需登录查询条件: + if(isset($my_user_id) && $my_user_id){ + //得到我收藏的课程ids + $collect_classes_lib_ids = Collect::where("user_id",$my_user_id)->column("classes_activity_id"); + //专查我的收藏 + if(isset($collect) && $collect){ + $selfetch = $selfetch->where("{$a}id","in",$collect_classes_lib_ids); + } + + } + + if(isset($order) && $order == "distance"){ + $selfetch = $selfetch->where("{$a}longitude","not null") + ->where("{$a}latitude","not null") + ->where("{$a}longitude","<>","") + ->where("{$a}latitude","<>","") + ->where("{$a}longitude","<>","null") + ->where("{$a}latitude","<>","null"); + } + + + + + + //排序 + switch ($order) { + case "normal": //综合排序(推薦優先) + $selfetch = $selfetch->order("{$a}recommend desc,{$a}hot desc,{$a}new desc,{$a}weigh desc,{$a}start_time desc,{$a}id desc"); + break; + case "distance": //距离优先 权重 + $selfetch = $selfetch->order("distance asc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc"); + break; + case "hot": //熱門优先 + $selfetch = $selfetch->order("{$a}hot desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc"); + break; + + case "new": //平台最新优先 + $selfetch = $selfetch->order("{$a}new desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc"); + break; + case "selfhot": //机构热门优先 + $selfetch = $selfetch->order("{$a}selfhot desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc"); + break; + + case "recommend": //推薦优先 + $selfetch = $selfetch->order("{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc,{$a}sign_num desc"); + break; + + case "sale": //銷量优先 + $selfetch = $selfetch->order("{$a}sale desc,{$a}verification_num desc,{$a}sign_num desc,{$a}recommend desc,{$a}weigh desc"); + break; + + case "views": //浏览量优先 + $selfetch = $selfetch->order("{$a}views desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc"); + break; + case "collect": //收藏量优先 + $selfetch = $selfetch->order("{$a}collect desc,{$a}recommend desc,{$a}weigh desc,{$a}verification_num desc,{$a}sale desc"); + break; + default: + throw new \Exception("不支持的排序类型"); + } + + if(isset($nearby) && $nearby) { +// throw new \Exception("现版本不支持"); + $selfetch = $selfetch->having("distance <= {$nearby}"); + } + + + + + $selfetch = $selfetch->page($page,$limit)->select(); + + + foreach ($selfetch as $row) { + +// $row->getRelation('manystore')->visible(['nickname']); + $row->getRelation('shop')->visible(['name','logo']); + } + $rows = $selfetch; +// $total = $selfetch->total(); + + + + //额外附加数据 + foreach ($rows as &$row) { //迭代器魔术方法遍历,填值自动引用传值 + //设置是否已收藏 + $row->is_collect = in_array($row->id,$collect_classes_lib_ids) ? 1 : 0; + + if($row->is_collect){ + $row["collect"] = Collect::where("user_id",$my_user_id)->where("classes_activity_id",$row->id)->find(); + } +// $classes_label_ids = $row['classes_label_ids']; +// $classes_cate_ids = $row['classes_cate_ids']; +// $classes_type_ids = $row['classes_type']; +// $classes_label = $classes_cate = $classes_type = []; +// foreach (explode(",", $classes_label_ids) as $classes_label_id){ +// if(isset($label_list[$classes_label_id]))$classes_label[] = $label_list[$classes_label_id]; +// } +// foreach (explode(",", $classes_cate_ids) as $classes_cate_id){ +// if(isset($cate_list[$classes_cate_id]))$classes_cate[] = $cate_list[$classes_cate_id]; +// } +// +// foreach (explode(",", $classes_type_ids) as $classes_type_id){ +// if(isset($type_list[$classes_type_id]))$classes_type[] = $type_list[$classes_type_id]; +// } +// +// +// $row['classes_label'] = $classes_label; +// $row['classes_cate'] = $classes_cate; +// $row['classes_type_name'] = $classes_type; + + } + $result = array("data" => $rows); + return $result; + } + + + + protected $classes_activity_ids = []; + /** 管理的活动ids + * @param $user_id + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function getActivityAuthIds($user_id){ + //必须是授权过的用户 + if(config("site.shop_auth_user_check")){ + $auth_shop_ids = UserAuth::where("status" ,1)->where("user_id",$user_id)->column("shop_id"); + $shop_where = ["shop_id" ,"in" ,$auth_shop_ids]; + }else{ + $shop_where = [[]]; + } + + //核销员有核销全部课程权力 + $classes_lib_ids = []; + $shop_id = Verification::where("user_id",$user_id)->where(...$shop_where)->where("status",'1')->value("shop_id"); + if($shop_id){ + $classes_libids = self::where("shop_id",$shop_id)->column("id"); + if($classes_libids)$classes_lib_ids[] = implode(",", $classes_libids); + } + if($classes_lib_ids){ + //遍历课程ids + foreach ($classes_lib_ids as $classes_lib_id){ + $classes_lib_id_arr = explode(",",$classes_lib_id)?:[]; + foreach ($classes_lib_id_arr as $v){ + $this->classes_activity_ids[] = $v; + } + } + } + + $this->classes_activity_ids = array_unique($this->classes_activity_ids); + + return $this->classes_activity_ids; + } + + + + + /**设置收藏 + * @param $id + * @param int $user_id + * @param int $collect 0取消收藏 1收藏 + * @param bool $check + * @param bool $trans + * @throws \Exception + */ + public function collect($id,$user_id,$collect,$oper_type='user',$oper_id=0,$trans=false){ + $classes_lib = self::where("id",$id)->find(); + if(!$classes_lib)throw new \Exception("找不到活动!"); + //判断逻辑 + if($trans){ + self::beginTrans(); + } + + try{ + //事务逻辑 + $where = [ + "user_id"=>$user_id, + "classes_activity_id"=>$id, +// "weigh"=>$classes_lib["weigh"], + ]; + //查询是否已收藏 + $res1 = Collect::where($where)->find(); + if($collect){ + if(!$res1){ + $where["weigh"] = $classes_lib["weigh"]; + + //未收藏,添加收藏 + $res1 = new Collect(); + $res1->allowField(true)->save($where); + } + + self::update_classes($classes_lib["id"]); + //调用事件 + $data = ['activity' => $classes_lib,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; + \think\Hook::listen('activity_collect_success_after', $data); + + }else{ + + unset($where["weigh"]); + //取消收藏 + $res1 = Collect::where($where)->delete(); + self::update_classes($classes_lib["id"]); + //调用事件 + $data = ['activity' => $classes_lib,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; + \think\Hook::listen('activity_collect_cancel_after', $data); + + + } + + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + $where["is_collect"] = $collect; + return $where; + } + + + + + public static function update_classes($classes_lib_id){ + //更新课程规格库存 + $classes_lib = self::get($classes_lib_id); + if($classes_lib){ + $classes_lib->sale = Order::where("classes_activity_id",$classes_lib["id"])->where("status","not in",["-3","6"])->count(); + //遍历课程课时规格,更新课时统计数据 + $specs = $classes_lib->items; + if($specs){ + foreach ($specs as $item){ + // '已核销人数', + $item->verification_num = Order::where("classes_activity_item_id",$item["id"])->where("status","=","9")->count(); + //已报名人数 + $item->sign_num = Order::where("classes_activity_item_id",$item["id"])->where("status","not in",["-3","6"])->count(); + $item->save(); + } + } + //统计课程总报名和总核销 + $classes_lib->sign_num = Order::where("classes_activity_id",$classes_lib["id"])->where("status","not in",["-3","6"])->count(); + $classes_lib->verification_num = Order::where("classes_activity_id",$classes_lib["id"])->where("status","=","9")->count(); + + //所有课时加起来 + $classes_lib->stock = ActivityItem::where("classes_activity_id",$classes_lib_id)->sum( "limit_num"); + + //更新课程信息开始和结束时间信息 + //课程开始和结束时间等于所有课时的最早开始和最晚结束时间 +// $classes_lib->start_time = ClassesSpec::where("classes_lib_id",$classes_lib_id)->min("start_time"); +// $classes_lib->end_time = ClassesSpec::where("classes_lib_id",$classes_lib_id)->max("end_time"); + + //设置课程收藏 + $classes_lib->collect = Collect::where("classes_activity_id",$classes_lib_id)->count(); + + $classes_lib->save(); + //将课程信息和课时信息同步到所有已下单的订单信息中 + self::orderInfoSync($classes_lib_id); + } + return $classes_lib; + } + + + public static function orderInfoSync($classes_lib_id){ + $classes_lib = self::get($classes_lib_id); + if($classes_lib){ + //查询所有课程订单更新课程单信息 + $order = \app\common\model\school\classes\activity\order\OrderDetail::where("classes_activity_id",$classes_lib_id)->select(); + foreach ($order as $row){ + $update = $classes_lib->toArray(); + $update_data = $row->checkAssemblyParameters($update,["id","status","createtime","updatetime"]); + $row->save($update_data); + } + //同步更新订单课时信息 + $specs = $classes_lib->items; + foreach ($specs as $item){ + $hourorders = \app\common\model\school\classes\activity\order\OrderItem::where("classes_activity_item_id",$item->id)->select(); + foreach ($hourorders as $hourorder){ + $update = $item->toArray(); + $update_data = $hourorder->checkAssemblyParameters($update,["id","status","createtime","updatetime"]); + $hourorder->save($update_data); + } + } + + } + + } + + + } diff --git a/application/common/model/school/classes/activity/ActivityAuth.php b/application/common/model/school/classes/activity/ActivityAuth.php index e847b82..6e40bde 100644 --- a/application/common/model/school/classes/activity/ActivityAuth.php +++ b/application/common/model/school/classes/activity/ActivityAuth.php @@ -74,7 +74,8 @@ class ActivityAuth extends BaseModel self::afterInsert(function ($row) { if (!$row['weigh']) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); } }); } diff --git a/application/common/model/school/classes/activity/order/Order.php b/application/common/model/school/classes/activity/order/Order.php index 2ace225..50be643 100644 --- a/application/common/model/school/classes/activity/order/Order.php +++ b/application/common/model/school/classes/activity/order/Order.php @@ -2,14 +2,26 @@ namespace app\common\model\school\classes\activity\order; +use addons\epay\library\Service; +use app\admin\model\Admin; use app\admin\model\manystore\Shop; +use app\common\model\BaseModel; use app\common\model\dyqc\ManystoreShop; use app\common\model\school\classes\activity\Activity; +use app\common\model\school\classes\activity\ActivityItem; +use app\common\model\school\classes\ClassesLib; +use app\common\model\school\classes\ClassesSpec; +use app\common\model\school\classes\order\ServiceOrder; +use app\common\model\User; use app\manystore\model\Manystore; +use bw\Common; +use fast\Random; +use think\Cache; use think\Model; use traits\model\SoftDelete; +use Yansongda\Pay\Pay; -class Order extends Model +class Order extends BaseModel { use SoftDelete; @@ -182,6 +194,17 @@ class Order extends Model } + public function getCodeimageAttr($value, $data) + { + if (!empty($value)) return cdnurl($value, true); + } + + public function getCodeoneimageAttr($value, $data) + { + if (!empty($value)) return cdnurl($value, true); + } + + public function user() { return $this->belongsTo('app\admin\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0); @@ -210,4 +233,1526 @@ class Order extends Model { return $this->belongsTo(OrderDetail::class, 'activity_order_detail_id', 'id', [], 'LEFT')->setEagerlyType(0); } + + public function orderitem() + { + return $this->belongsTo(OrderItem::class, 'activity_order_item_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + + + //统计并更新活动数等相关统计数据 + public static function statisticsAndUpdateClassesNumber($order){ + if(is_string($order)||is_numeric($order))$order = self::getOrder($order); + $detail = $order->detail; + if(!$detail)throw new \think\Exception("订单信息缺失!"); +// //得到当前订单的所有未取消课时订单 +// $hourorderOrderCount = \app\common\model\school\classes\activity\order\Order::where("status","<>",'-3') +// ->where("classes_order_id","=",$order["id"]) +// ->count(); +// //更新已用课程数和剩余课程数 +// $detail->use_num = $hourorderOrderCount; +// $detail->sub_num = $detail->classes_num - $detail->use_num; +// //更新已用课程金额和剩余课程金额 +//// $detail->used_price = bcmul($detail->unit_price , $detail->use_num,2); +// $detail->save(); + +// //得到所有售后单的已退金额 +// $order->real_refundprice = ServiceOrder::where("classes_order_id" , $order["id"])->where("status","in",['7'])->where("sales_type","in",['10'])->sum("real_refundprice"); +// //实际付款额 - 已退金额 = 剩余未退 +// //更新剩余未退 +// $order->sub_refundprice = bcsub($order->payprice,$order->real_refundprice,2); +// //更新订单应退金额 +// $order->total_refundprice = bcsub($order->totalprice,$detail->used_price,2); +// $order->save(); + + + //课程下单时已核销人数更新 + $lib = $order->activity; + if($lib){ + + } + + + //将课程信息和课时信息同步到所有已下单的订单信息中 + Activity::update_classes($order["classes_activity_id"]); + + //如果有评价执行评价更新 + return $order; + } + + + + + /**得到基础条件 + * @param $status + * @param null $model + * @param string $alisa + */ + public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false) + { + + if (!$model) { + $model = new static; + if ($alisa&&!$with) $model = $model->alias($alisa); + } + if ($alisa) $alisa = $alisa . '.'; + $tableFields = (new static)->getTableFields(); + foreach ($tableFields as $fields) + { + if(in_array($fields, ['status',"auth_status",'classes_activity_id']))continue; +// if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]); + + if (isset($whereData[$fields]) && $whereData[$fields]){ + if(is_array($whereData[$fields])){ + $model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]); + }else{ + $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]); + } + + } + + + } + if (isset($whereData['status'])) $model = $model->where("{$alisa}status", 'in', $whereData['status']); + if (isset($whereData['not_status'])) $model = $model->where("{$alisa}status", 'not in', $whereData['not_status']); + + if (isset($whereData['auth_status'])) $model = $model->where("{$alisa}auth_status", 'in', $whereData['auth_status']); + if (isset($whereData['not_auth_status'])) $model = $model->where("{$alisa}auth_status", 'not in', $whereData['not_auth_status']); + + + if (isset($whereData['keywords'])&&$whereData['keywords']) $model = $model->where("{$alisa}order_no|{$alisa}pay_no|{$alisa}code", '=', $whereData['keywords']); + if (isset($whereData['time'])&&$whereData['time']){ + + $model = $model->time(["{$alisa}createtime",$whereData['time']]); + } + if (isset($whereData['user_id']) && $whereData['user_id']) $model = $model->where("{$alisa}user_id", '=', $whereData['user_id']); + + if (isset($whereData['classes_activity_ids']) && $whereData['classes_activity_ids']) $model = $model->where("{$alisa}classes_activity_id", 'in', $whereData['classes_activity_ids']); + if (isset($whereData['classes_activity_id']) && $whereData['classes_activity_id']) $model = $model->where("{$alisa}classes_activity_id", 'in', $whereData['classes_activity_id']); + +// if (isset($whereData['has_evaluate'])&&$whereData['has_evaluate']){ +// //1查已评价 2查未评价 +// if($whereData['has_evaluate'] == 1){ +// //1查已评价 +// $model = $model->where("{$alisa}classes_evaluate_id", '<>', 0); +// }else{ +// //2查未评价 +// $model = $model->whereExists(function ($query) use ($alisa) { +// $order_table_name = (new \app\common\model\school\classes\hourorder\Order())->getQuery()->getTable(); +// $query->table($order_table_name)->where($order_table_name . '.classes_order_id=' . $alisa . 'id')->where('status', '=', '3'); +// })->where("{$alisa}classes_evaluate_id", '=', 0); +// +// } +// } + + return $model; + } + + + + + + + public static function allList($user_id,$page, $limit,$keywords,$status,$classes_activity_id=[],$has_evaluate=0){ + $with_field = [ + 'user'=>['nickname','mobile','avatar','realname'], + 'base'=>['*'], + 'shop'=>['name','logo','image'], + 'detail'=>['*'], + 'orderitem'=>['*'], + ]; + $CANCEL = '-3'; + $NOPAY = '0'; + $PAYED = '2'; + $RESERV = '3'; + $REFUND = '6'; + $FINISH = '9'; + $IN_SERVICE = '4'; + $alisa = (new self)->getWithAlisaName(); + $sort = "field({$alisa}.status,'{$NOPAY}','{$PAYED}','{$RESERV}','{$FINISH}','{$REFUND}','{$IN_SERVICE}','{$CANCEL}') asc,{$alisa}.id desc"; + $serch_where = ['status'=>$status,'user_id'=>$user_id,'keywords'=>$keywords,"classes_activity_id"=>$classes_activity_id,"has_evaluate"=>$has_evaluate]; +// if($type)$serch_where['type'] = $type; + return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field); + } + + + + + public static function baseCount($where = []){ + $CANCEL = '-3'; + $NOPAY = '0'; + $PAYED = '2'; + $RESERV = '3'; + $REFUND = '6'; + $FINISH = '9'; + $IN_SERVICE = '4'; + $cancel_number = self::getBaseWhere(array_merge(['status'=>$CANCEL],$where))->count(); + $nopay_number = self::getBaseWhere(array_merge(['status'=>$NOPAY],$where))->count(); + $payed_number = self::getBaseWhere(array_merge(['status'=>$PAYED],$where))->count(); + $reserv_number = self::getBaseWhere(array_merge(['status'=>$RESERV],$where))->count(); + + + $retund_number = self::getBaseWhere(array_merge(['status'=>$REFUND],$where))->count(); + $finish_number = self::getBaseWhere(array_merge(['status'=>$FINISH],$where))->count(); + $in_service_number = self::getBaseWhere(array_merge(['status'=>$IN_SERVICE],$where))->count(); + + return compact('cancel_number','nopay_number','payed_number','in_service_number','retund_number','finish_number','reserv_number'); + } + + + + /**订单数量统计 + * @param int $user_id + * @return array + */ + public static function orderCount($user_id = 0,$classes_activity_id=[]){ + return self::baseCount(['user_id'=>$user_id,"classes_activity_id"=>$classes_activity_id]); + } + + + + + + public static function workList($user_id,$page, $limit,$keywords,$status,$classes_activity_id=[],$classes_activity_ids=[],$has_evaluate=0){ + $with_field = [ + 'user'=>['nickname','mobile','avatar','realname'], + 'base'=>['*'], + 'shop'=>['name','logo','image'], + 'detail'=>['*'], + 'orderitem'=>['*'], + ]; + $CANCEL = '-3'; + $NOPAY = '0'; + $PAYED = '2'; + $RESERV = '3'; + $REFUND = '6'; + $FINISH = '9'; + $IN_SERVICE = '4'; + $alisa = (new self)->getWithAlisaName(); + $sort = "field({$alisa}.status,'{$NOPAY}','{$PAYED}','{$RESERV}','{$FINISH}','{$REFUND}','{$IN_SERVICE}','{$CANCEL}') asc,{$alisa}.id desc"; + $serch_where = ['status'=>$status,'keywords'=>$keywords,"classes_activity_id"=>$classes_activity_id,"classes_activity_ids"=>$classes_activity_ids]; +// if($type)$serch_where['type'] = $type; + return (new self)->getBaseList($serch_where, $page, $limit,$sort,$with_field); + } + + + + + + + /**订单数量统计 + * @param int $user_id + * @return array + */ + public static function workCount($classes_activity_id=[],$classes_activity_ids=[]){ + return self::baseCount(["classes_activity_id"=>$classes_activity_id,"classes_activity_ids"=>$classes_activity_ids]); + } + + + + + /**得到订单详情 + * @param $order_no + */ + public static function getDetail($order_no,$classes_activity_id = []){ + $model = self::where('order_no|id|pay_no|code',$order_no); + if($classes_activity_id)$model = $model->where("classes_activity_id","in",$classes_activity_id); + $data = $model->find(); + + if(!$data) return $data; + //加载订单详情 + $data->detail; + //订单用户 +// $data->user; + $data->user->visible(['id','nickname','mobile','avatar','realname']); + //订单机构 + $data->shop; + //规格信息 + $data->orderitem; + //售后单信息 +// $data->serviceorder; + +// //得到二维码 +// $data->code_url = Common::getQrcode([ +// 'text' => $data['code'], +// 'size' => 200, +// ]); +// $data->one_code_url = Common::getBarcode([ +// 'text' => $data['code'], +// 'size' => 200, +// ]); + //评价 +// $data->evaluate; + + return $data; + } + + + /**展示订单信息 + * @param $order_no + * @param $price_info + * @return array + */ + public static function showInfo($order_no, $price_info = []){ + $data = []; + $data['order_no'] =$order_no; + $data['order_info'] = self::getDetail($order_no); + return array_merge($data,$price_info); + } + + /**得到订单 + * @param $order_no + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function getOrder($order_no){ + $order = self::where('order_no|id|pay_no|code',$order_no)->find(); + if(!$order)throw new \Exception("订单不存在"); + return $order; + } + + + + /** + * 设置订单缓存 + * @param $uid + * @param $data + * @return bool + */ + public static function setOrderCache($uid, $data) + { + //缓存名 = uid + order_no + $cacheNmae = 'classes_activity_order_cache' . $uid . $data['order_no']; + // 缓存在3600秒之后过期 + return Cache::set($cacheNmae, $data, config("site.unpaid_order_expire_time")); + } + + /** + * 得到订单缓存 + * @param $uid + * @param $order_no + * @return mixed + */ + public static function getOrderCache($uid, $order_no) + { + //缓存名 = uid + order_no + $cacheNmae = 'classes_activity_order_cache' . $uid . $order_no; + // 缓存在3600秒之后过期 + return Cache::get($cacheNmae); + } + + + /** + * 删除订单缓存 + * @param $uid + * @param $order_no + * @return mixed + */ + public static function deleteOrderCache($uid, $order_no) + { + //缓存名 = uid + order_no + $cacheNmae = 'classes_activity_order_cache' . $uid . $order_no; + // 缓存在3600秒之后过期 + return Cache::rm($cacheNmae); + } + + + + + //计算订单所需返回数据接口 + public static function getCost($user_id,$classes_activity_id,$classes_activity_item_id,$param=[],$other_params=[],$check = false){ + //用户 + $user_info = User::get($user_id); + $user_data = [ + "nickname"=>$user_info["nickname"], + "realname"=>$user_info["realname"], + "avatar"=>$user_info["avatar"], + "mobile"=>$user_info["mobile"], + "money" =>$user_info["money"], + "score" =>$user_info["score"], + ]; + //课程 + $activity_info = Activity::get($classes_activity_id); + $activity_info = $activity_info->toArray(); + $activity_info["classes_activity_id"] = $classes_activity_id; + $activity_info["classes_activity_order_id"] = 0; +// $activity_info['use_num'] = 0;//已使用课时 +// $activity_info['sub_num'] = $activity_info['classes_num'];//剩余课时 +// //单价 = 课程价格/总课时 +// $activity_info["unit_price"] = bcdiv($activity_info['price'],$activity_info['classes_num'],2); +// $activity_info["used_price"] = 0; + + + //组装订单下单数据 + $order_data = []; + $order_data["user_id"] = $user_id; + $order_data["manystore_id"] = $activity_info["manystore_id"]; + $order_data["shop_id"] = $activity_info["shop_id"]; + $order_data["classes_activity_id"] = $classes_activity_id; + $order_data["activity_order_detail_id"] = 0; + $order_data["classes_activity_item_id"] = $classes_activity_item_id; + $order_data["beforeprice"] = $activity_info["price"]; + $order_data["totalprice"] = $activity_info["price"]; + $order_data["payprice"] = 0; + $order_data["status"] = '0'; + $order_type = "multiple"; + //如果课程只存在一个规格,则订单类型为单课 + $classes_spec_count = ActivityItem::where('classes_activity_id',$classes_activity_id)->count(); + if($classes_spec_count==1){ + $order_type = "single"; + } + $classes_activity_item = null; + + if($classes_activity_item_id){ + $classes_activity_item = ActivityItem::get($classes_activity_item_id); + + $order_data["beforeprice"] = $classes_activity_item["price"]; + $order_data["totalprice"] = $classes_activity_item["price"]; + } + + + return compact('order_data','activity_info','user_data','order_type',"classes_activity_item"); + } + + + + + /** 订单确认(订单计算) + * @param $user_id 下单用户 + * @param $order_no 订单号(缓存标识) + * @param $classes_activity_id 課程活动id + * @param $classes_activity_item_id 課程活动规格id + * @param $param 額外参数(扩展用) + * @param bool $is_compute 是否重新计算订单 + * @return array + */ + public function confirm($user_id, $classes_activity_id,$classes_activity_item_id,$order_no,$param=[], $is_compute = false) + { + if ($order_no && !$is_compute) { + //得到缓存 + $data = self::getOrderCache($user_id, $order_no); + if (!$data) throw new \Exception('请您完善参加信息!'); + $price_info = $data['price_info']; + } else { + //订单信息计算 +// if(!$param) throw new \Exception('缺少必要信息'); + $this->orderVaild($user_id,$classes_activity_id,$classes_activity_item_id,$order_no, $param); + //订单支付信息 + $price_info = $this->getCost($user_id,$classes_activity_id,$classes_activity_item_id,$param); + //生成订单号 + if (!$order_no) $order_no = get_order_sn(); + //生成缓存 + $data = compact('user_id', 'classes_activity_id','classes_activity_item_id','param', 'order_no', 'price_info'); + self::setOrderCache($user_id, $data); + } + + \think\Hook::listen('classes_activity_order_create_before', $data); + + //下单数据展示 + return $this->showInfo($order_no, $price_info); + } + + + + + /**订单校验 + * @param $user_id 用户id + * @param $classes_lib_id 课程id + * @param $order_no 订单号 + * @param $param 表单扩展参数 + * @return bool + */ + public function orderVaild($user_id,$classes_activity_id,$classes_activity_item_id, $order_no, $param,$check=false){ + if(!$user_id||!$classes_activity_id )throw new \Exception("缺少必要参数"); + + //校验订单参数 + //课程活动是否存在并上架 + $classes_lib_info = Activity::where('id',$classes_activity_id)->find(); + if(!$classes_lib_info || $classes_lib_info['status']!='1') throw new \Exception("该活动不存在或已下架!"); + + //往期课程活动无法下单 + $now_time = time(); + if($classes_lib_info['end_time'] <= $now_time) throw new \Exception("该活动已过期,是往期活动,无法购买!"); + + //当前时间不在改报名时间段sign_start_time 和 sign_end_time 内则无法购买 + if($classes_lib_info['sign_start_time'] > $now_time || $classes_lib_info['sign_end_time'] < $now_time) throw new \Exception("不在活动报名时间范围内,无法购买!"); + + + + + //默认校验订单是否已创建 + if($check){ + //判断订单是否已创建 + $order_info = self::where(['order_no'=>$order_no])->find(); + if($order_info) throw new \Exception("订单已生成,如需重新下单请退出页面重新进入!"); + //下单必须传规格id + if(!$classes_activity_item_id) throw new \Exception("请选择活动规格!"); + + //判断数量是否超出库存 + $classes_lib_info = Activity::update_classes($classes_activity_id); + $sale = Order::where("classes_activity_id",$classes_activity_id)->where("status","<>","-3")->count(); + if($sale >= $classes_lib_info['stock']) throw new \Exception("该活动已满人,无法参与!"); + } + + + + //执行免费课黑名单判断 + //免费课才进行判断 +// if($classes_lib_info && $classes_lib_info['feel']=='1'){ +// \app\common\model\school\classes\hourorder\Order::checkBlackList($user_id,true); +// } +// //免费课才进行判断(同個免費單只能买一次) +// if($classes_lib_info && $classes_lib_info['feel']=='1'){ +// \app\common\model\school\classes\hourorder\Order::checkOnlyone($user_id,$classes_lib_info,true); +// } + + + //用户存不存在 + $user_info = User::where('id',$user_id)->find(); + if(!$user_info) throw new \Exception("用户不存在!"); + + + + if($classes_activity_item_id){ + //没有订单id无法判断 +// //记录代下单人信息 +// $param = [ +// "type" =>'2', +// "help_user_id" =>$user_id, +// "help_type" =>'admin', +// "classes_lib_id" =>$classes_lib_id +// ]; +// +// +// //确认订单 +// $res = (new \app\common\model\school\classes\hourorder\Order)->confirm($user_id,0,null, $classes_lib_spec_id,$param, true); + //只简单判断课程和课时 记得判断库存 + self::checkLibSpec($user_id,$classes_activity_id ,$classes_activity_item_id,true,$order=null,$check); + } + + return true; + } + + + /** 课时信息选择合法检测 + * @param $user_id 下单用户 + * @param $classes_activity_id 活动id + * @param $classes_activity_item_id 活动规格id + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function checkLibSpec($user_id,$classes_activity_id ,$classes_activity_item_id,$add=false,$order=null,$check=false){ + if(!$classes_activity_id || !$classes_activity_item_id)throw new \Exception("缺少必要信息!"); + + $classes_lib_spec_info = ActivityItem::where('id',$classes_activity_item_id) + ->where('classes_activity_id',$classes_activity_id) + ->find(); + if(!$classes_lib_spec_info)throw new \Exception("规格信息不正确!"); + //课时已下架 + if($classes_lib_spec_info['status']!='1') throw new \Exception("该规格已下架,请选择其他规格!"); + + //存在同规格正在进行中的课时预约 + $order_info = self::where('classes_activity_item_id',$classes_activity_item_id) + ->where('status',"not in",["-3","6"]) + ->where('user_id',$user_id) + ->find(); + if($order_info) throw new \Exception("该活动规格已预约或已上过,请勿重复预约!"); + + //新增或更换课时时判断 + //是否达成限制人数 + //允许人数为0说明不限制 + if($classes_lib_spec_info['limit_num'] > 0 && $check){ + //得到当前课时已参与人数 + $sign_num = self::where('classes_activity_item_id',$classes_activity_item_id)->where("status","not in",["-3","6"])->count(); + + if($sign_num >= $classes_lib_spec_info['limit_num']){ + throw new \Exception("该活动已满,请选择其他活动!"); + } + + + if($add){ + + }else{ + + } + } + + + + //判断是否是免费课 + $lib = $classes_lib_spec_info->activity; + if(!$lib){ + throw new \Exception("该课程活动信息缺失!"); + } + + if($classes_lib_spec_info["feel"] == '1'){ + //免费课开始和结束时间有交叠无法下预约 + if(!config("site.free_time_activity_check")){ + //如果是免费课 + //判断时间是否有交叠 + $start_time = $lib['start_time']; + $end_time = $lib['end_time']; + + $as = (new self)->getWithAlisaName(); + //判断时间是否有交叠(只查所有的免费的预约记录) + $order_info = self::with("detail")->where("detail.price",0) + ->where("{$as}.status","not in",["-3","6","9"]) + ->where(function ($query) use ($as,$start_time,$end_time) { + //兩個時間區間重合 存在任意交集 都不行 + $query->where("detail.start_time BETWEEN {$start_time} AND {$end_time}"); + $query->whereOr("detail.end_time BETWEEN {$start_time} AND {$end_time}"); + $query->whereOr("detail.start_time <= {$start_time} AND detail.end_time >= {$end_time}"); + $query->whereOr("detail.start_time >= {$start_time} AND detail.end_time <= {$end_time}"); + }) + ->where("{$as}.user_id",$user_id)->find(); + if($order_info) throw new \Exception("当前时间区间内,您已预约免费活动{$order_info['detail']['title']},无法再预约其他免费活动"); + + + } + + } + + if(!config("site.all_time_activity_check")){ + //判断时间是否有交叠 + $start_time = $lib['start_time']; + $end_time = $lib['end_time']; + + $as = (new self)->getWithAlisaName(); + //判断时间是否有交叠(只查所有的免费的预约记录) + $order_info = self::with("detail") + ->where("{$as}.status","not in",["-3","6","9"]) + ->where(function ($query) use ($as,$start_time,$end_time) { + //兩個時間區間重合 存在任意交集 都不行 + $query->where("detail.start_time BETWEEN {$start_time} AND {$end_time}"); + $query->whereOr("detail.end_time BETWEEN {$start_time} AND {$end_time}"); + $query->whereOr("detail.start_time <= {$start_time} AND detail.end_time >= {$end_time}"); + $query->whereOr("detail.start_time >= {$start_time} AND detail.end_time <= {$end_time}"); + }) + ->where("{$as}.user_id",$user_id)->find(); + if($order_info) throw new \Exception("当前时间区间内,您已预约活动{$order_info['detail']['title']},无法再预约其他活动"); + } + + //执行免费课黑名单判断 +// //免费课才进行判断 +// if($lib && $lib['feel']=='1'){ +// self::checkBlackList($user_id,true); +// } + + //过期课时无法下单(结束时间小于等于当前时间) + if($lib["end_time"] <= time()){ + throw new \Exception("该活动已过期结束,无法预约!"); + } + + + + } + + + + + + /** + * 根据缓存创建订单 + */ + public function cacheCreateOrder($order_no, $user_id,$remark="", $trans = false) + { + //得到缓存 + $orderInfo = self::getOrderCache($user_id, $order_no); //得到下单信息 + if (!$orderInfo) throw new \Exception('請您完善預約信息!'); + + if ($trans) { + self::beginTrans(); + } + try { + //'classes_activity_id','classes_activity_item_id' + //1订单执行创建 + $order = $this->createOrder($user_id,$orderInfo['classes_activity_id'],$orderInfo['classes_activity_item_id'],$order_no,$orderInfo['param'],$remark); + + $orderitem = $order->orderitem; + //如果是免费订单,则直接调用支付完成 + if ($orderitem['feel'] == '1' || $order['totalprice'] == 0) { + //调用订单支付成功事件 + $this->paySuccess($order_no,['platform'=>"miniapp",'pay_type'=>'yue']); + } + + + + //5删除缓存 + self::deleteOrderCache($user_id, $order_no); + + + + if ($trans) { + self::commitTrans(); + } + } catch (\Exception $e) { + if ($trans) { + self::rollbackTrans(); + } + throw new \Exception($e->getMessage().$e->getFile() . $e->getLine()); + } + return self::showInfo($order_no); + } + + + + + public function createOrder($user_id,$classes_activity_id,$classes_activity_item_id,$order_no,$param,$remark='',$other_params=[]){ + + $this->orderVaild($user_id,$classes_activity_id,$classes_activity_item_id, $order_no, $param,true); + //订单支付信息 + $order_info = self::getCost($user_id,$classes_activity_id,$classes_activity_item_id,$param,$other_params,true); + + //组装订单数据 + $order_data = $order_info['order_data']; + $order_data["order_no"] = $order_no; + + $res1 = self::create($order_data); + if (!$res1) throw new \Exception('创建订单失败'); + $classes_activity_item = $order_info["classes_activity_item"]; + if(!$classes_activity_item)throw new \Exception('订单未选规格!'); + + //課程详情 + $activity_info = $order_info['activity_info']; + + $order_detail_data = []; + $order_detail_data = array_merge($order_detail_data,$activity_info); + $order_detail_data["classes_activity_id"] = $activity_info['id']; + $order_detail_data["classes_activity_order_id"] = $res1['id']; + + unset($order_detail_data['id']); + unset($order_detail_data['createtime']); + + $orderDetail = (new OrderDetail()); + $orderDetail->allowField(true)->save($order_detail_data); + + + $order_item_data = []; + $order_item_data = array_merge($order_item_data,$classes_activity_item->toArray()); + $order_item_data["classes_activity_item_id"] = $classes_activity_item['id']; + $order_item_data["classes_activity_order_id"] = $res1['id']; + + unset($order_item_data['id']); + unset($order_item_data['createtime']); + $orderItem = (new OrderItem()); + $orderItem->allowField(true)->save($order_item_data); + + //更新订单详情id + $res1->activity_order_detail_id = $orderDetail->id; + $res1->activity_order_item_id = $orderItem->id; + $res1->save(); + + + + //记录订单日志 + OrderLog::log($res1['id'],"活动订单创建成功,等待【学员】支付",'user',$user_id); + //7事件 + $data = ['order' => $res1]; + \think\Hook::listen('classes_activity_order_create_after', $data); + + + //更新订单数据 + self::statisticsAndUpdateClassesNumber($res1); + + + return $res1; + } + + + + + + + /**余额支付 + * @throws \Exception + */ + public function moneyPay($order_no,$method,$trans=false){ + $order = self::getNopayOrder($order_no); + //支付前判断 +// self::checkPay($order_no,'wallet'); + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + if($order['totalprice']){ + $memo = "活动订单[ID:{$order['id']}]下单,支付余额{$order['totalprice']}"; + try{ + //扣除用户余额 + User::money(-$order['totalprice'], $order['user_id'], $memo,'class_order_pay' ,[ + 'order_id' => $order->id, + 'order_sn' => $order->order_sn, + ]); + }catch (\Exception $e){ + throw new \Exception("余额不足!"); + } + } + //调用订单支付成功事件 + $this->paySuccess($order_no,['platform'=>$method,'pay_type'=>'yue']); + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + return $res; + + } + + + + + + /**调用订单支付成功事件 + * @param $order_no + * @param $pay_type + * @param $price + * @param $price_check + * @param bool $trans + * @return bool + * @throws \Exception + */ + public function paySuccess($order_no,$notify=[],$price=0,$price_check=false,$trans=false){ + $order = self::getNopayOrder($order_no); + //金额校验 :第三方支付时回调入口判断 + if($price_check){ + if(bccomp($price,$order['totalprice'])==-1)throw new \Exception("支付金额与订单需要支付金额对应不上,回调失败!"); + } + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + //不拆分订单,直接执行 + self::paySetData($order,$notify); + +// //如果需要快捷预约 +// $classes_lib_spec_id = $order['classes_lib_spec_id']; +// if($classes_lib_spec_id){ +// //记录代下单人信息 +// $param = [ +// "type" =>'2', +// "help_user_id" =>$order["user_id"] , +// "help_type" => 'admin', +// ]; +// +// //确认订单 +// $res = (new \app\common\model\school\classes\hourorder\Order)->confirm($order["user_id"],$order['id'],null, $classes_lib_spec_id,$param, true); +// $remark = "订单支付完成同时快捷预约一个课时"; +// //创建订单 +// $result = (new \app\common\model\school\classes\hourorder\Order)->cacheCreateOrder($res['order_no'], $order["user_id"],$remark); +// +// } + + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage().$e->getFile().$e->getLine()); + } + return $res; + } + + + public static function paySetData($order,$notify=[]){ + //订单支付更新 + $order = self::updatePay($order,$notify); + //生成订单一维码和二维码 + $order = self::buildCode($order); + //记录订单日志 + OrderLog::log($order['id'],"活动订单支付成功,核销码生成,等待审核结果",'user',$order['user_id']); + //调用支付成功事件 + $data = ['order' => $order]; + \think\Hook::listen('classes_activity_order_payed_after', $data); + //更新订单数据 + self::statisticsAndUpdateClassesNumber($order); + return true; + } + + + + + + public static function updatePay($order,$notify=[]){ + if(is_string($order)||is_numeric($order))$order = self::getNopayOrder($order); + $order->status ='2'; + $order->paytime = time(); + $order->pay_no = $notify['transaction_id'] ?? null; + $order->pay_json = $notify['payment_json'] ?? '{}'; + $order->pay_type = $notify['pay_type'] ?? 'yue'; + //如果订单创建时间大于预约时间,则等于预约时间 +// if($order['createtime']>$order['starttime'])$order['createtime'] = $order['starttime']; + switch ($order->pay_type) { + case "offline": //线下付款,线上不需要支付 + + break; + + default: + $order->payprice = $notify['pay_fee'] ?? $order->totalprice; + } + $order->platform = $notify['platform'] ?? 'miniapp'; + $order->sub_refundprice = $order->payprice; //剩余未退 = 支付金额 + + $order->save(); + return $order; + } + + /**得到待支付订单 + * @param $order_no + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function getNopayOrder($order_no){ + $order = self::where('order_no|id|pay_no|code',$order_no)->where("status",'0')->find(); + if(!$order)throw new \Exception("待支付订单不存在"); + return $order; + } + + + public static function buildCode($order){ + if(is_string($order)||is_numeric($order))$order = self::getNopayOrder($order); + //生成核销二维码和一维码 + //生成code + $vcode = en_code($order['id']). Random::alnum(); + $order['code'] = $vcode; + $params = [ + "type"=>"activity_verification", + "vcode" =>$vcode, + "order_id"=>$order['id'], + ]; + //$params生成get参数 + $params = http_build_query($params); + //生成二维码和一维码 + //二维码 + $order->codeimage = (Common::getQrcode([ + 'text' => $params, + 'size' => 200, + ]))['url']; + //一维码 + $order->codeoneimage = (Common::getBarcode([ + 'text' => $params, + 'size' => 200, + ]))['url']; + $order->save(); + return $order; + } + + + + /** + * 检测支付开关(待扩展) + */ + public static function checkPaySwitch($pay_type,$user_id){ + + + } + + + /**订单支付前判断 + * @param $order_no + * @param $pay_type + * @return array|false|\PDOStatement|string|Model + */ + public function checkPay($order_no,$pay_type,$password = null){ + $order = self::getNopayOrder($order_no); + + //支付前判断 + //TODO通用判 + + $this->orderVaild($order['user_id'],$order['classes_activity_id'],$order['classes_activity_item_id'],$order['order_no'], []); + + //... + $user = User::where('id',$order['user_id'])->find(); + if(!$user)throw new \Exception("支付用户异常"); + + //是否开通此支付方式 + self::checkPaySwitch($pay_type,$order['user_id']); + + //各自币种判断 + switch ($pay_type) { + case "wechat": //微信支付 + //.. + break; + case "alipay": //支付宝支付 + //... + break; + case "offline": //线下支付 + //.. + break; + case "yue": //余额支付 + //支付密码判断 +// $res = User::checkPayPassword($order['user_id'],$password,true); +// if(!$res['is_setting'])throw new \Exception("您还未设置支付密码,请您先去设置支付密码"); +// if(!$res['is_right'])throw new \Exception("支付密码错误"); + //判断余额是否充足 + //得到支付余额 + $total_amount = $order['totalprice'] ?:0; + //得到用户余额 + $money = $user['money']; + if(bccomp($money,$total_amount)==-1)throw new \Exception("当前余额不足以完成本次支付!"); + break; + default: + throw new \Exception("不支持的支付类型验证"); + } + + return true; + } + + + + + /** 课时订单操作权限检测 + * @param $order 订单 + * @param $oper_id 操作人id + * @param $oper_type 操作人类型:user-用户或员工,admin-管理员 + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function checkOptionAuth($classes_order_id,$oper_id,$oper_type,$only_user=false,$only_shop=false,$only_admin=false){ + + //课程是否存在并上架 + $classesOrder = Order::where("id",$classes_order_id)->find(); + if(!$classesOrder)throw new \Exception("订单不存在!"); + + switch ($oper_type) { + case 'user': + if($only_admin)throw new \Exception("您无权操作该订单!"); + + //自己或操作员 + if($oper_id != $classesOrder["user_id"]){ + if($only_user) throw new \Exception("您无权操作该订单!"); + + $Shop = \app\common\model\manystore\Shop::where("user_id",$oper_id)->find(); + if($Shop){ + if($Shop["id"] == $classesOrder["shop_id"]){ + break; + } + + } + + //说明是操作员 + $help_user_info = User::where('id',$oper_id)->find(); + if(!$help_user_info) throw new \Exception("代下单员工不存在!"); + $classes_activity_ids = (new Activity())->getActivityAuthIds($oper_id); + //判断当前订单课程是否在此课程授权范围内 + if(!in_array($classesOrder["classes_activity_id"],$classes_activity_ids)) throw new \Exception("该活动不在您的授权范围内,无法代操作!"); + }else{ + $classes_activity_ids = (new Activity())->getActivityAuthIds($oper_id); + //不是员工并且想操作只有机构能操作的单 + if(!in_array($classesOrder["classes_activity_id"],$classes_activity_ids) && $only_shop)throw new \Exception("您无权操作该订单!"); + } + break; + case 'admin': + $admin_info = Admin::where('id',$oper_id)->find(); + if(!$admin_info) throw new \Exception("代下单管理员不存在!"); + break; + case 'shop': + if($only_admin)throw new \Exception("您无权操作该订单!"); + + if($only_user) throw new \Exception("您无权操作该订单!"); + + $admin_info = Manystore::where('id',$oper_id)->find(); + if(!$admin_info) throw new \Exception("代下单管理员不存在!"); + $classes_activity_ids = Activity::where("manystore_id",$oper_id)->column("id"); + //判断当前订单课程是否在此课程授权范围内 + if(!in_array($classesOrder["classes_activity_id"],$classes_activity_ids)) throw new \Exception("该活动不在您的授权范围内,无法代操作!"); + + break; + default: + throw new \Exception("请选择正确的代下单类型!"); + } + + + } + + + + + /**得到可取消订单 + * @param $order_no + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function getHaveCancelOrder($order_no){ +// $where = [self::STATUS_NOPAY,self::STATUS_PAYED]; + $order = self::where('order_no|id|pay_no|code',$order_no)->find(); + $detail = $order->detail; + $orderitem = $order->orderitem; + if(!$detail) throw new \Exception("订单信息缺失!"); + if(!$orderitem) throw new \Exception("订单信息缺失!"); + if(!$order)throw new \Exception("只有待支付订单可取消,已支付请走售后申请,已取消请忽略!"); + //非免费单进行中无法取消 + if($orderitem["feel"] == "0" && $order['status'] != '0'){ + throw new \Exception("只有待支付订单可取消,已支付请走售后申请,已取消请忽略!"); + } + if(($orderitem["feel"] == "1" || $order['totalprice'] == 0)&& !in_array($order['status'],['0','2','3'])){ + throw new \Exception("只有进行中订单可取消,已取消请忽重复取消!"); + } + + return $order; + } + + + /**更新订单取消状态 + * @param $order + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function updateCancel($order){ + if(is_string($order))$order = self::getHaveCancelOrder($order); + $order->status = "-3";//refund_status + $order->canceltime = time(); + $order->save(); + return $order; + } + + /**订单取消 + * @param $order_no + * @param int $user_id + * @param bool $check + * @param bool $trans + * @return bool + * @throws \Exception + */ + public function cancel($order_no,$user_id=0,$check=false,$oper_type='user',$oper_id=0,$trans=false){ + //得到可取消订单 + $order = self::getHaveCancelOrder($order_no); + if($check){ + //用户操作权限检测 + self::checkOptionAuth($order['id'],$user_id ?: $oper_id,$oper_type); + + //进行中,用户自己无法操作取消 + if(($order['status'] == '2' || $order['status'] == '3' )&& $user_id == $order['user_id']){ + throw new \Exception("您无权操作取消!请您联系机构操作!"); + } + } + + + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + + //更新订单取消状态 + $order = self::updateCancel($order); + //插入订单取消日志 + if(!$user_id ||$order["user_id"] !=$user_id ){ + OrderLog::log($order['id'],"[系统操作]课程活动订单取消成功",$oper_type ?: 'user', $oper_id ?: $order['user_id']); + }else{ + OrderLog::log($order['id'],"课程活动订单取消成功",$oper_type ?: 'user', $oper_id ?: $order['user_id']); + } + + //调用订单取消事件 + $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; + \think\Hook::listen('classes_activity_order_cancel_after', $data); + //执行课时数更新 + $res1 = self::statisticsAndUpdateClassesNumber($order['id']); + + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage().$e->getFile().$e->getLine()); + } + return $res1; + } + + + + + + + /**得到可审核订单 + * @param $order_no + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function getHaveExamineOrder($order_no){ +// $where = [self::STATUS_NOPAY,self::STATUS_PAYED]; + $order = self::where('order_no|id|pay_no|code',$order_no)->where("status","in",['2'])->find(); + if(!$order)throw new \Exception("不是待审核的订单!"); + + return $order; + } + + + + + /**更新订单取消状态 + * @param $order + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function updateExamineSuccess($order,$oper_id = 0,$oper_type='user'){ + if(is_string($order))$order = self::getHaveExamineOrder($order); + $order->status = "3";//refund_status + $order->auth_status = "1";//refund_status + $order->auth_time = time(); + $order->auth_user_id = $oper_id; + $order->auth_type = $oper_type; + $order->save(); + return $order; + } + + + + + /**更新订单取消状态 + * @param $order + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function updateExamineFail($order,$reason,$oper_id = 0,$oper_type='user'){ + if(is_string($order))$order = self::getHaveExamineOrder($order); + $order->auth_status = "2"; + $order->auth_time = time(); + $order->reason = $reason; + $order->auth_user_id = $oper_id; + $order->auth_type = $oper_type; + $order->save(); + return $order; + } + + + + + + + /**活动订单审核 + * @param $order_no + * @param int $user_id + * @param bool $check + * @param bool $trans + * @return bool + * @throws \Exception + */ + public function examine($order_no,$auth_status,$reason="",$user_id=0,$check=false,$oper_type='user',$oper_id=0,$trans=false){ + + + //得到可取消订单 + $order = self::getHaveExamineOrder($order_no); + + if($check){ + //用户操作权限检测 + self::checkOptionAuth($order['id'],$user_id ?: $oper_id,$oper_type); + + + } + //审核状态字段检测 + $auth_status_arr = [1,2];//0=待审核,1=审核通过,2=审核失败 + if( !in_array($auth_status,$auth_status_arr)) throw new \Exception("审核状态不正确!"); + //审核失败需要传理由 + if($auth_status==2 && empty($reason)) throw new \Exception("审核失败需要填写理由!"); + + + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + + //插入订单取消日志 + if(!$user_id ||$order["user_id"] !=$user_id ){ + $pron = "[员工操作]"; + }else{ + $pron = ""; + } + //审核成功逻辑 + if($auth_status == 1){ + //更新订单状态 + $order = self::updateExamineSuccess($order,$user_id ?: $oper_id,$oper_type); + + OrderLog::log($order['id'],$pron."课程活动单审核成功,预约成功等待核销!",$oper_type ?: 'user', $oper_id ?: $order['user_id']); + //调用订单事件 + $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; + \think\Hook::listen('classes_activity_order_auth_success_after', $data); + + }else{ + $detail = $order->detail; + $orderitem = $order->orderitem; + + //如果是免费的订单,直接取消订单 + if($orderitem['feel'] == '1' || $order['payprice'] <= 0){ + //更新订单状态 + $order = self::updateExamineFail($order,$reason,$user_id ?: $oper_id,$oper_type); + + //审核失败逻辑 + OrderLog::log($order['id'],$pron."课程活动单审核不通过,原因;{$reason},该活动单将取消(若已支付将自动退款)以便重新下单",$oper_type ?: 'user', $oper_id ?: $order['user_id']); + //调用订单事件 + $data = ['order' => $order,"user_id"=>$user_id,"oper_type"=>$oper_type,"oper_id"=>$oper_id]; + \think\Hook::listen('classes_activity_order_auth_fail_after', $data); + //执行订单取消逻辑 + $this->cancel($order_no,$user_id,false,$oper_type,$oper_id); + }else{ + //调用退款发起 + self::orderRefund($order,$order['sub_refundprice'],$oper_type,$oper_id,$trans=false,$admin=false); + } + + } + + //执行课时数更新 +// $res1 = \app\common\model\school\classes\order\Order::statisticsAndUpdateClassesNumber($order['classes_order_id']); + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + return $order; + } + + + + /**预约订单退款(退全款) + * @param $order + * @param $refund_money + * @param $trans + */ + public static function orderRefund($order,$refund_money,$oper_type='user',$oper_id=0,$trans=false,$admin=false){ + if(is_numeric($order))$order = self::getBaseWhere(['id'=>$order])->find(); + if(!$order)throw new \Exception("找不到订单"); + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //生成退款单号 + $order['refund_no'] = get_order_sn(); + $order->save(); + + //事务逻辑 + switch ($order['pay_type']) { + case "wechat": //微信退款 + self::wechatRefund($order,$refund_money,$oper_type,$oper_id); + break; +// case "alipay": //支付宝退款 +// self::alipayRefund($order,$refund_money,$oper_type,$oper_id); +// break; +// case "wallet": //钱包支付退款 +// self::walletRefund($order,$refund_money,$oper_type,$oper_id); +// break; +// case "offline": //线下支付退款 +// +// break; + default: + throw new \Exception("订单币种异常!"); + } + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + return $res; + } + + + + /**微信退款 + * @param $order + * @param $refund_money + */ + public static function wechatRefund($order,$refund_money,$refund_desc="",$oper_type='user',$oper_id=0,$trans=false){ + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + //创建订单退款订单 + + + $classesorder = $order; + $detail = $order->detail; + + //执行微信退款sdk + $order_data = [ + 'out_trade_no' => $classesorder->order_no + ]; + $total_fee = $classesorder->payprice * 100; + $refund_fee = $refund_money * 100; + + $order_data = array_merge($order_data, [ + 'out_refund_no' => $order->refund_no, + 'total_fee' => $total_fee, + 'refund_fee' => $refund_fee, + 'refund_desc' => $refund_desc ?: "活动[{$detail["title"]}]订单[ID:{$classesorder['id']}]退款{$refund_money}已到账户", + ]); + + $config = Service::getConfig('wechat',[],$classesorder->platform); + + + + $notify_url = request()->domain() . '/api/school.activity.pay/notifyr/payment/' . $classesorder->pay_type . '/platform/' . $classesorder->platform; + + $config['notify_url'] = $notify_url; + $pay = Pay::wechat($config); + + + $result = $pay->refund($order_data); + + \think\Log::write('refund-result' . json_encode($result)); + + + if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') { + $res = true; + } else { + throw new \Exception($result['return_msg']); + } + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage().$e->getFile().$e->getLine()); + } + return $res; + } + + + /**得到可直接退款订单(正常取消退全款非售后) + * @param $order_no + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function getHaveRefundOrder($refund_sn){ +// $where = [self::STATUS_NOPAY,self::STATUS_PAYED]; + $order = self::where('refund_no',$refund_sn)->where("sub_refundprice",">",0)->find(); + if(!$order)throw new \Exception("不是可直接退款的订单!"); + + return $order; + } + + + + + + /**同意并发放退款金额 + * @param $order 退款单号 + * @return array|false|\PDOStatement|string|Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function updateRefundOrder($order,$pay_json=[]){ + if(is_string($order))$order = self::getHaveRefundOrder($order); + $order->before_status = $order->status;//refund_status + $order->status = "6"; + $order->service_stauts = "6"; + $order->real_refundprice = bcadd($order->real_refundprice ?:'0',$order->sub_refundprice ,2); + $order->sub_refundprice = 0; + $order->refundtime = time(); + $order->refund_json = json_encode($pay_json); + $order->save(); + return $order; + } + + + + + + + /**退款成功处理逻辑(需修改) + * @param $refund_sn + * @param bool $trans + * @return bool + * @throws \Exception + */ + public static function refundSuccess($refund_sn,$trans=false){ + //得到机构售后提交确认订单 + $order = self::getHaveRefundOrder($refund_sn); + + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + + //更新订单状态为同意 + $order = self::updateRefundOrder($refund_sn); + + //插入订单日志 + OrderLog::log($order['id'],"活动订单退全款已原路退回", 'admin', 0); + + //执行课时数更新 + $res1 = self::statisticsAndUpdateClassesNumber($order['id']); + + //调用订单取消事件 + $data = ['order' => $order,"user_id"=>$order['user_id'],"oper_type"=>'admin',"oper_id"=>0]; + \think\Hook::listen('classes_activity_order_auth_success_after', $data); + + + + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + return $res; + + } + + + } diff --git a/application/common/model/school/classes/activity/order/OrderDetail.php b/application/common/model/school/classes/activity/order/OrderDetail.php index ae545ba..ca9f86c 100644 --- a/application/common/model/school/classes/activity/order/OrderDetail.php +++ b/application/common/model/school/classes/activity/order/OrderDetail.php @@ -3,13 +3,14 @@ namespace app\common\model\school\classes\activity\order; use app\admin\model\manystore\Shop; +use app\common\model\BaseModel; use app\common\model\school\classes\activity\Activity; use app\common\model\dyqc\ManystoreShop; use app\manystore\model\Manystore; use think\Model; use traits\model\SoftDelete; -class OrderDetail extends Model +class OrderDetail extends BaseModel { use SoftDelete; diff --git a/application/common/model/school/classes/activity/order/OrderItem.php b/application/common/model/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..01cffe1 --- /dev/null +++ b/application/common/model/school/classes/activity/order/OrderItem.php @@ -0,0 +1,119 @@ +getPk(); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + } + }); + } + + + public function getStatusList() + { + return ['1' => __('Status 1'), '2' => __('Status 2')]; + } + + public function getSexList() + { + return ['1' => __('Sex 1'), '2' => __('Sex 2'), '3' => __('Sex 3')]; + } + + public function getFeelList() + { + return ['0' => __('Feel 0'), '1' => __('Feel 1')]; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['status']) ? $data['status'] : ''); + $list = $this->getStatusList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + public function getSexTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['sex']) ? $data['sex'] : ''); + $list = $this->getSexList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + public function getFeelTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['feel']) ? $data['feel'] : ''); + $list = $this->getFeelList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + + + public function activityorder() + { + return $this->belongsTo(Order::class, 'classes_activity_order_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function manystore() + { + return $this->belongsTo(Manystore::class, 'manystore_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function shop() + { + return $this->belongsTo(Shop::class, 'shop_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function activity() + { + return $this->belongsTo(\app\common\model\school\classes\activity\Activity::class, 'classes_activity_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function item() + { + return $this->belongsTo(\app\common\model\school\classes\activity\ActivityItem::class, 'classes_activity_item_id', 'id', [], 'LEFT')->setEagerlyType(0); + } +} diff --git a/application/common/model/school/classes/activity/order/OrderLog.php b/application/common/model/school/classes/activity/order/OrderLog.php index 956263f..421b1c5 100644 --- a/application/common/model/school/classes/activity/order/OrderLog.php +++ b/application/common/model/school/classes/activity/order/OrderLog.php @@ -2,10 +2,12 @@ namespace app\common\model\school\classes\activity\order; +use app\common\model\BaseModel; + use think\Model; use traits\model\SoftDelete; -class OrderLog extends Model +class OrderLog extends BaseModel { use SoftDelete; @@ -50,4 +52,51 @@ class OrderLog extends Model { return $this->belongsTo(Order::class, 'classes_activity_order_id', 'id', [], 'LEFT')->setEagerlyType(0); } + + + + /**记录订单日志 + * @param $params + * @param bool $trans + * @throws \Exception + */ + public static function log($order,$mark='更新订单状态',$oper_type='user',$oper_id = 0,$trans=false){ + if(is_numeric($order)||is_string($order))$order = Order::where('order_no|id|pay_no',$order)->find(); + if(!$order)throw new \Exception("找不到订单"); + //操作人信息(可扩展) + $data = [ + 'oper_type'=>$oper_type ?: 'user', + 'oper_id'=>$oper_id ?: $order['user_id'], + 'remark'=>$mark, + ]; + //判断逻辑 + if($trans){ + self::beginTrans(); + } + $res = true; + try{ + //事务逻辑 + $log_data = $order->toArray(); + $log_data["classes_activity_order_id"] = $order['id']; + unset($log_data['id']); + unset($log_data['createtime']); + if($mark)$log_data['log_text'] = $mark; + + $log_data = array_merge($log_data,$data); + + $log = (new self); + $log->allowField(true)->save($log_data); + if($trans){ + self::commitTrans(); + } + }catch (\Exception $e){ + if($trans){ + self::rollbackTrans(); + } + throw new \Exception($e->getMessage()); + } + return $log; + } + + } diff --git a/application/common/model/school/classes/order/Order.php b/application/common/model/school/classes/order/Order.php index 5139a28..7f75fb4 100644 --- a/application/common/model/school/classes/order/Order.php +++ b/application/common/model/school/classes/order/Order.php @@ -563,7 +563,7 @@ class Order extends BaseModel $order_data["classes_lib_id"] = $classes_lib_id; $order_data["beforeprice"] = $classes_lib_info["price"]; $order_data["totalprice"] = $classes_lib_info["price"]; - $order_data["payprice"] = $classes_lib_info["price"]; + $order_data["payprice"] = 0; $order_data["classes_lib_spec_id"] = $param['classes_lib_spec_id'] ?? 0; $order_data["status"] = '0'; $order_type = "multiple"; @@ -1038,24 +1038,24 @@ class Order extends BaseModel //课程下单时已核销人数更新 $lib = $order->lib; if($lib){ - $lib->sale = self::where("classes_lib_id",$lib["id"])->where("status","<>","-3")->count(); - - //遍历课程课时规格,更新课时统计数据 - $specs = $lib->specs; - if($specs){ - foreach ($specs as $spec){ - // '已核销人数', - $spec->verification_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_spec_id",$spec["id"])->where("status","=","3")->count(); - //已报名人数 - $spec->sign_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_spec_id",$spec["id"])->where("status","in",["-1","0","3"])->count(); - $spec->save(); - } - - } - //统计课程总报名和总核销 - $lib->sign_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_id",$lib["id"])->where("status","in",["-1","0","3"])->count(); - $lib->verification_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_id",$lib["id"])->where("status","=","3")->count(); - $lib->save(); +// $lib->sale = self::where("classes_lib_id",$lib["id"])->where("status","<>","-3")->count(); +// +// //遍历课程课时规格,更新课时统计数据 +// $specs = $lib->specs; +// if($specs){ +// foreach ($specs as $spec){ +// // '已核销人数', +// $spec->verification_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_spec_id",$spec["id"])->where("status","=","3")->count(); +// //已报名人数 +// $spec->sign_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_spec_id",$spec["id"])->where("status","in",["-1","0","3"])->count(); +// $spec->save(); +// } +// +// } +// //统计课程总报名和总核销 +// $lib->sign_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_id",$lib["id"])->where("status","in",["-1","0","3"])->count(); +// $lib->verification_num = \app\common\model\school\classes\hourorder\Order::where("classes_lib_id",$lib["id"])->where("status","=","3")->count(); +// $lib->save(); } @@ -1063,7 +1063,7 @@ class Order extends BaseModel //检测订单完成状态 self::statisticsAndUpdateOrderFinish($order->id); //将课程信息和课时信息同步到所有已下单的订单信息中 - ClassesLib::orderInfoSync($order["classes_lib_id"]); + ClassesLib::update_classes($order["classes_lib_id"]); //如果有评价执行评价更新 return $order; diff --git a/application/extra/site.php b/application/extra/site.php index 70c997d..9b01d89 100644 --- a/application/extra/site.php +++ b/application/extra/site.php @@ -3,7 +3,7 @@ return array ( 'name' => '多样青春夜校', 'beian' => '', - 'cdnurl' => '', + 'cdnurl' => 'https://testy1.hschool.com.cn/', 'version' => '1.0.3', 'timezone' => 'Asia/Shanghai', 'forbiddenip' => '', @@ -28,6 +28,14 @@ return array ( 'user' => '会员配置', 'example' => '示例分组', 'wx_miniapp' => '微信小程序配置', + 'classes_order' => '课程订单配置', + 'classes_hourorder' => '课时预约订单配置', + 'classes_query' => '课程查询配置', + 'home' => '首页参数配置', + 'agreement' => '协议配置', + 'shop' => '机构总配置', + 'classes' => '课程配置', + 'classes_activity' => '课程活动配置', ), 'mail_type' => '1', 'mail_smtp_host' => 'smtp.qq.com', @@ -38,10 +46,48 @@ return array ( 'mail_from' => '', 'attachmentcategory' => array ( - 'category1' => '分类一', - 'category2' => '分类二', + 'category1' => '非机密类1', + 'category2' => '非机密类2', 'custom' => '自定义', + 'cert' => '证件机密类', + 'code' => '二维码类', + 'user' => '用户端上传', ), - 'wx_miniapp_id' => 'wxd7e2deffbaa22254', - 'wx_miniapp_secret' => '573964aee57c334619396d4b6c05497d', + 'wx_miniapp_id' => 'wx867e324c44b9e016', + 'wx_miniapp_secret' => 'ea5f7cc16269798f0644dc7a4816bc1a', + 'default_nickname' => '青春-', + 'default_avatar' => '/old/static/common/images/tou4.png', + 'virtual_nickname' => '灭红神##天幽狼##血擎刀##逼摇妹er,##ar丶将军灬##月聊无痕##缕寒流##利铜锣烧##yond丨极限##寒夜々孤星##血战苍穹##丿星座灬天堂彡##淩亂玫瑰##|丶利刃メ出鞘丶##轩哥∥逆天改命##萧萧暮雨##烈火战神##橘萝卜蹲@##血虐修罗##歲月无痕##影猎杀戮##骑刀锋寒##宠物女孩##寒玉簪秋水##农场小镇##探险家##☆夏°指閒緑═→##叼着根香蕉闯遍天下##耀世红颜[由Www.QunZou.Com整理]##蓝铯の峢痕##现代战争##僵尸勿近##死怎样舒服##灭零##自嗨怪@##墨染迷舞##清歌留欢##天使★翅膀╮##幼稚女神蹦蹦恰!##南柯无痕##金鱼嘴@##战龙三国##ざ碎情漂移ド##清尊素影##梦幻舞步##三朝元老i##称雄三界##雨后の微笑##念荒寒##提莫队长正在送命##无心者##一阵寒风##〆﹎兲使雪↘##戎马↘生涯﹌##哈哈神###微微寒风秋凄凉##顽皮灬贝贝##风流雅痞妖姑娘っ##q水浒##萌面大盗##霸刀☆藐视天下##玩飞车滴孩子我陪你##不懂我心寒##夜店之王##顾北清歌寒##玉衡逍龙##萌尊!##红眼★夜袭彡##火花★之炫##煜逅彩泓##闹爷@##买梦人i##大侠传##从筠##坦克##南山不寒##蹦蹦蹦V@##omair圣珂##霸天修罗##愤怒的小鸟##冰残°零度伤~##滑雪大冒险##影丿战魂##野狼@##萨普莱斯##摩尔庄园##南梦破碎##赏你奔雷掌i##ゴ二逼主义°##龙剑##妥神!##逆战##草率怪~##枪心。@##っ惊恐嘟##北巷远人##清酒与你##鬼寐﹏孤寂##该用户身份不明 ##绿竹猗猗 ##潑墨為畫 ##秋叶满地伤 ##江山寒色远 ##紫醉琴缘 ##预感大师 ##楓葉晓寒 ##傲视判决 ##初夏少女 ##黄萝卜诅咒@ ##千囚迷森 ##笙歌初寒夜未央 ##洫聙↘刀锋 ##独步死神 ##◇ヽ少爷╰★╮ミ逍遙営 ##℃梦醒 ##深葬长白雪 ##叫兽光波i ##水果连连看 ##戎马↘追风 ##£极限★雨寒彡 ##凡人修真 ##部落战争 ##葫芦娃 ##贫僧灬不虐人 ##ヤpk淪為笑柄 ##南岸清风 ##心浪微勃 ##拖拉机小游戏 ##双月之夜_KRIS控 ##尛爺半生沉浮゛° ##格格巫i ##王者天下 ##新仙剑 ##北木在北 ##破恨南飞 ##战魔の不灭 ##打豆豆 ##咆哮战歌 ##皇后成长计划 ##亡梦爱人 ##皇族鬼圣 ##河南车神灬 ##俄罗斯方块 ##ヤGm﹎鬼魅℡ ##ぁ血刹风云城ぁ ##℡嵿级╔舞灵族╗ ##捕鱼达人 ##嗜魂龙吟 ##狂扁小朋友 ##╬最终メ狂暴╬ ##拿把雨伞装蘑菇 ##战神将军@ ##飞天女侠啵啵啵@ ##愤怒的小鸟太空版 ##神堂丨灬艹鸳鸯战 ##one丶piece丿r ##ㄗs風流』締國︶ㄣ ##逆水寒 ##独孤久贱 ##一滴水墨 ##mm小游戏 ##o戰☆無情★ ##┾恋戦℃ャ逍遥 ##oO冰暴★战神Oo ##掩卷别寒窗 ##贪婪虫 ##短发郁夏天 ##暴力摩托 ##帝王魂 ##扒一扒。 ##sky★血狼 ##哀而不伤 ##我请寒假吃炫迈 ##梦里花易寒 ##黑影子^ ##撕书狂魔i ##找你妹 ##久伴不弃 ##狼少° ##街头霸王 ##止步ツ梦江南 ##绝代风骚 ##£袅袅★烟云彡 ##寒春玉柳 ##萌哒女屌^ ##凯撒大帝! ##土鳖中的战斗鳖 ##妖美人@ ##所叹浅夏夜更寒。 ##新人不好混啊! ##果蔬连连看 ##[亡心者] ##哑巴汤姆猫@ ##星战 ##浴血み神鷹 ##荳蔻年華 ##修罗现世 ##对对碰 ##-大爆炸 ##一盏孤灯 ##『地狱★男爵』 ##极限丶雨寒 ##北海茫月 ##黄金矿工双人版 ##符咒Thedevil◢ ##彡炫灬月影萧梦灬 ##回首寒暄 ##直升机模拟飞行 ##丿star炫love绿茶 ##画轴初寒 ##舞蹈黑钟 ##苍空的蓝耀 ##≮神秘人≯ ##◇嗼尛寒◆ ##烽火ヤ角逐 ##青山灼灼 ##<诡使> ##Regin ##弑魂无情 ##旅人与风 ##萌面女神 ##栀寒老酒 ##づ暗暗的伤╄ ##神庙逃亡 ##Promise°魅眸 ##寒烟冷°浅暮流殇 ##←lěι濕枕寒→ ##猫溺怀歌者’ ##sun╮寒霜 ##风云之王 ##抿口老酒 ##似冷非寒冰i ##残月絮辰 ##慕雨遙长 ##雨落伊人 ##挽吟袖 ##天空不空 ##死亡公路 ##南风未恋 ##泪湿枕寒 ##大闹天宫ol ##圣诞节的节奏~ ##黑狱☆擎天 ##冒险小镇 ##血战メ傲神 ##SCメ戰無不勝 ##回忆づ我 ##龙刀杀戮 ##笙歌初寒夜未央 ##飒舛流寒i ##神将世界 ##硝烟冉冉 ##萌兽 ##颠峰霸天 ##灭世メ狂刀 ##q宠大乐斗 ##魁首阿^ ##ら魔粉の晓涛 ##疯狗三人组 ##领嗨掌门 ##血战メ孤狼 ##傲视天地 ##姐统领守护 ##泡沫女神i ##带我装逼带我飞# ##诗的颈窝 ##丿mx传说艹灬急速 ##不计寒暑 ##糖果味的初夏 ##乱世魔枭 ##丶绝望的战斗机i ##UnderTaker(送葬者) ##慕心倾寒 ##梦遗少年 ##别逃呀! ##战无不胜 ##浮动的记忆り ##在寒星中苏醒 ##女爆君@ ##坦克之怒 ##眼泪是魔鬼 ##〆霸气开爷° ##兔子大爆炸 ##无念倾颓 ##灭世狂舞 ##妖孽少年 ##づ`啵钣赯﹏ ##杀戮为生 ##枪魂 ##倾国妖魔ぃ ##哆啦A梦修理工场 ##^上↗璇月℡ ##烟雨寒~伊人醉 ##柚子半夏 ##醉心眠 ##神魔领域 ##横尸遍野 ##女战将i ##斗龙战士 ##北城凉筑 ##美食大战老鼠 ##羽翼之魔 ##噬血魅影@ ##·turbine°(涡轮) ##◆幻じ灭つ ##黄金矿工 ##百变五瞎i ##今夜酷寒不宜裸奔 ##乱世小熊 ##攻城略地 ##空白小姐 ##魔境仙踪 ##北①丿战魂 ##始终与你 ##幕_无情花舞 ##北有凉城 ##滚吧水果 ##Explosion°[爆炸] ##地铁跑酷 ##一发绝杀 ##稳中求胜,@ ##◢◢无名★悍将◣◣ ##神妖@ ##保卫萝卜 ##苍凉满目 ##寒岁饮醉 ##梅寒风独开 ##水却要煮鱼 ##细雨轻愁 ##少年纪@ ##坦克世界 ##大鱼吃小鱼 ##月狼の啸天 ##将军令 ##北栀怨寒 ##≮Azrael★柒岁≯ ##欢乐斗地主 ##清风清梦 ##长空夕醉 ##秦美人 ##霸气傲世 ##凉宸 ##弑神者 ##£冰泣↘美人鱼彡 ##丿莫兮丶风流寨丨 ##修真世界 ##高尔夫射击 ##心岛未晴 ##傲寒 ##厕所有枪声 ##紫色百合 ##乱斗堂 ##光治愈独角兽罒?罒 ##Top丶彪悍丿 ##江东过客 ##极品台球 ##阿sue做蛋糕 ##嗜血メ狂虐 ##月冷花残♂ ##如来神掌 ##°籽萝卜蹲@ ##主治撩妹 ##大周皇族 ##冷心寒心 ##繁華的世間 ##寒武紀的月光 ##天界 ##亮瞎你的眼 ##╰ゞ姐独占天下℡ ##▲°喧哗夜黎-Miss ##Govern(统治) ##宿妖瞳|CATOBLEPAS- ##一世霸主 ##-彻骨寒 ##衾枕寒 ##南影倾寒 ##飞无痕廴两院 ##泡泡堂 ##放假者们@ ##∑gray°鱼ル ##HeartAttack ##借风凉心 ##光影神力 ##圝◣帝潮◢圝 ##反恐精英 ##变形金刚 ##情若幽兰 ##||丶问鼎★青龙丶 ##死阿宅@ ##水果忍者 ##塞外う飛龍 ##邪恶% ##FlappyBird ##黑巷少年 ##吞食天地 ##皇帝成长计划 ##逆光夏花 ##僚机中的战斗机@ ##噬魂こfeel ##@女叫兽 ##北风承欢 ##寂念流年 ##识透人情寒透心 ##黄萝卜魔咒 ##傲视&狂朝 ##和风戏雨 ##五子棋 ##寒烟冷浅暮殇 ##那年夏天的歌 ##木屋茶花 ##生死悠关组合! ##会说话的汤姆猫 ##※豪〓城〓世〓家※ ##卡通农场 ##深巷古猫 ##脑溢血的驴 ##丨极速灬巅峰彡丨 ##£剑魂メ秒杀彡 ##污界小公举 ##自嗨宝@ ##亦情,凡恋@ ##大将军 ##青涩碧瞳 ##轰炸女王 ##陌上↘寒迁 ##夜ゞ月影 ##英雄脸萌 ##£忧殇☆寒影╮ ##拳皇 ##橙子军团! ##寒兮唸红颜° ##大富翁 ##泡泡龙 ##夕陽西下 ##音桀@ ##热血三国 ##我是VIP呀! ##BlackKnight- ##破军╃升龙 ##萌心初动 ##南瓜婆婆 ##孤影月下 ##梵音与笙 ##霸气无双 ##大家来找茬 ##一世倾城 ##魅影丨时尚灬 ##逐风★黑翼 ##山河风光 ##诛心人i ##翠烟寒 ##≮绿蕊★紫蓝≯ ##大队长 ##黑骑士@ ##超级玛丽 ##暴君与猫@ ##妄断弥空 ##姑你二大爷@ ##光辉终结 ##丠颩箛唥 ##蓝戈者 ##疯狂的玩具 ##南熙寒笙 ##无极剑圣i ##||丶王者★无双丶 ##爆菊神话 ##Dancer丿(舞者) ##冷月寒笙 ##锤伢破天 ##伴我几度 ##宠物连连看 ##轩辕譹冂oоο ##北海未暖 ##南烟在南 ##你画我猜 ##终极战犯 ##南巷近海 ##≮盘古★帝神≯ ##丿石门灬独圣 ##ご盗贼耍↘蛋刀﹌ ##短巷闻雨 ##七雄争霸 ##街舞少年i ##蒙面超女 ##甜味的风 ##南岸初晴 ##≮盖世★袅雄≯ ##九月的雪 ##vip紫炫灬风舞 ##骑猪兜风 ##南鱼在流浪 ##冬雾寒凉 ##子夜寒风 ##≮佳乐★宝贝≯ ##当初的我 ##复习者联盟@ ##花落↘冰层 ##肃杀’ ##长夜有星光 ##至尊D叉车 ##蝙蝠不会飞 ##鹿霸@ ##拖沓囍天王 ##火麒麟 ##死了心的心 ##寻觅海洋的鱼 ##潇潇暮雨 ##爆破女神SIBIAO ##凄寒半世留殇铭 ##斗破苍穹 ##死亡镰刀 ##伟大旳苍穹 ##怪咖软妹@ ##灰机灰过去了 ##楠木青城 ##将神 ##十年寒如雪丶 ##明星志愿之好莱坞 ##凝泪入侵者·@ ##惊悚怪 ##剪剪清风 ##devil★战神 ##三国战记 ##南栀倾寒° ##血葬③界 ##蔑王侯 ##暖风与她 ##植物大战僵尸 ##一笑震九天 ##完美风暴 ##魂斗罗 ##卿弦季鸢 ##凡尘清心 ##龙洁寒 ##||丶至尊★君绝﹌ ##突击风暴 ##我亦无泪纵横i ##ご噬魂★魅影﹌ ##扎小辫的帅锅 ##凉生初雨 ##幻夜冰羽 ##萝卜蹲i ##灭世炙天 ##魅色夫人 ##蜘蛛纸牌 ##彼岸髅灵 ##公子泺尘 ##寒梅↘傲立 ##≮飘飘★伊人≯ ##寒光竹影ぃ ##狂人领袖i ##傲剑 ##ご屌炸天的节奏ヾ ##大脸怪@ ##枪神 ##风云ㄋ战焰 ##ヤ未央мo寒メ ##眨眼的舒马赫 ##小黄人快跑 ##杀戮灭人性 ##狼门★血影 ##孤冥 ##聚会玩 ##覆旧人寒 ##£魔龙★祭天彡 ##Roar&咆哮 ##喂鱼抽猫- ##嫌淡超人i ##乱流年颜目 ##柔媚~妖瞳 ##微胖女神 ##旋风小陀螺 ##秋风追猎者 ##£浅笑↘嫣然彡 ##醉里秋波 ##持枪瞄准BOOM! ##死神★镰刀 ##@暖宝宝妖精 ##海浔深蓝 ##樱舞灬默寒 ##迷你大城市 ##虐杀原形 ##死亡MUSIC ##寒峰叶落 ##渚寒烟淡 ##念寒冬里的夜空 ##搞怪碰碰球在线玩 ##七月纪旅 ##芭比萌少女^! ##毒魂SHOOT, ##密室逃脱 ##报之以李 ##‰统帅→ ##丿安萧灬若痕丨轩 ##半裸时代fell ##☆刀霸※离伤☆ ##Provenceつ暗眸° ##寒冰★冠世 ##瞬灭天下 ##月下☆清影', + 'unpaid_order_expire_time' => '180', + 'the_city' => '河南省/洛阳市', + 'search_distance_list' => + array ( + 1000 => '1000米', + 3000 => '3000米', + ), + 'about_us' => '
', + 'entry_agreement' => '

青年夜校服务平台商户入驻服务合同    

编号:

 

根据中华人民共和国相关法律、法规的规定,在平等、自愿、公平、诚信原则的基础上,您与青年夜校服务平台双方经友好协商,签订本《商户入驻服务合同》(以下简称本合同”),以兹共同遵守。本合同是您(以下简称“甲方”)与青年夜校服务平台(以下简称“乙方”)就甲方使用乙方及乙方关联方平台服务相关事项所订立的有效合约。

在您接受本合同及同意签署本合同之前,您应仔细阅读本合同的全部内容和其他相关协议及规则(包括但不限于通过青年夜校服务平台平台或商家中心发布的《诚信公约及管理办法》、《商户信息发布管理规范》、《商户收录声明》、《青年夜校服务平台商户管理制度》、《商家端信息及隐私政策》等在线发布的所有基础规则、商户管理规则、运营规则、诚信规则),该等协议及规则是本合同的重要组成部分,与本合同正文具有同等法律效力。如果您对本合同的条款或规则有任何疑问的,请向平台进行询问,平台将向您解释条款内容。如果您不同意本合同或规则的任意内容,或者无法准确理解平台对条款的解释,请不要同意签署本合同或使用本合同项下的服务。您使用平台所提供的本合同项下的服务即表示您已接受了本合同所述的条款和条件,同意受本合同及规则约束。届时您不应以未阅读本合同或相关规则的内容或者未获得平台对您问询的解答等理由,主张本合同无效,或要求撤销本合同。

为充分维护您的合法权益,平台特别提醒您关注本合同条款中的加粗及/或加下划线部分,请您务必仔细阅读。

第一条 定义条款

甲乙双方确认并同意本条款中对于各名词的解释及定义,并同意按照该定义履行相关义务。

(一)平台:指由乙方签约主体或其他乙方关联方现在或将来拥有合法权限运营/管理的,提供买单、预订、推广等技术服务的网络服务平台,包括但不限于青年夜校服务平台、乙方关联方/乙方合作方运营或管理的网络服务平台,及未来可能新设或合作的网络平台及相应的网页版、桌面版或移动版软件客户端或小程序等,以下简称“平台”或“乙方平台”。

(二)产品信息:甲方通过平台发布的,在平台页面上展示的甲方商品/服务信息(如适用门店、商品/服务描述、兑换券有效期、团购使用规则、会员优惠、活动等)。除本合同或双方另有书面约定外,该信息为甲方就前述商品/服务向用户发出的要约,一旦用户通过平台确认同意购买/参与/接受甲方该商品/服务,即视为甲方与用户达成了相应合同。

(三)商家中心:为向甲方提供相关技术服务,乙方基于合同为甲方提供的管理系统

(四)买单:针对甲方向用户提供的商品/服务,用户通过该功能向甲方支付费用的网络交易行为,甲方购买商户通后可使用买单技术服务。

(五)预订:甲方购买商户通后获得乙方平台开通预订技术服务的权限,乙方向甲方提供在线预订系统、订单处理系统等技术服务,乙方关联方/乙方合作方向甲方提供服务款(货款)结算技术服务。

(六)商家端:甲方入驻乙方平台并购买该技术服务产品后,可获得通过乙方商家中心进行门店装修、并发布订单、预订等服务的权限。

(七)小程序技术服务:乙方通过小程序技术为甲方提供技术服务及技术支持。

(八)推广技术/广告/内容营销服务:乙方为甲方提供的互联网信息发布空间及相关技术服务,服务内容包括但不限于商户通服务、推广通服务、图文广告服务等。具体推广技术/广告/内容营销服务的类型、内容和规则见乙方相关服务页面的说明。

(九)兑换券:指用户通过平台获取的,甲方向用户提供商品/服务的消费凭证。兑换券包括但不限于团购券、平台订单等,展现方式包括但不限于字符、二维码、订单、短信、电子邮件等。

(十)用户消费款项:用户通过乙方平台向甲方支付的已实际消费的兑换券对应的款项。若用户使用了平台或商家提供的、或从其他渠道获得的优惠补贴,用户消费款项按照补贴之前的售卖金额计算。

(十一)交易类产品结算净额:用户消费款项扣除乙方收取的服务费后,乙方关联方/乙方合作方应支付给甲方的结算款项。

(十二)关联方:在出现下列任一情况时,任何实体应被视为本合同一方的关联方:(i)控制该本合同一方的实体,(ii)被该本合同一方控制的实体,或(iii)与该本合同一方受其他同一主体控制的实体。本条款所称控制,指(i)某一实体直接或间接拥有对另一实体的50%以上的有投票权的股权,或通过协议方式控制另一实体的50%以上的投票权,或(ii)同一实体可决定另一实体董事会简单多数席位的人选。只有在该所有权或控制权存续期间,该企业、公司或其它实体才能视为关联方。

第二条 服务内容

为实现甲方进入平台开展经营活动、通过平台发布产品信息、与用户进行交易之目的,乙方通过特定计算机软件及软件技术、网络技术及其他相关技术为甲方提供各项服务(包括但不限于:买单、预订技术服务、小程序技术服务、推广技术/广告/内容营销服务、商品助手服务),具体服务内容以乙方在商家中心发布的规则/甲方在商家中心确认的方案为准。

 第三条 资质审查

(一)资质

甲方应为依法设立并领取营业执照及取得其他经营许可并有效存续的法人、非法人组织或依照法律法规不需要进行市场主体登记的自然人。甲方应主动提交甲方及甲方合作门店对应的资质,且甲方应保证获得甲方合作门店的充分授权。

(二)证明文件

1. 甲方/甲方合作门店应提交的证明文件要求:

1)若甲方/甲方合作门店为法人或非法人组织,应提交依据法律规定其经营业务所必须的文件或证明并加盖甲方公章,包括但不限于营业执照、行政许可证、开户行证明、质检报告、报关单、检验检疫证书、产品来源地证明、法人、非法人组织法定代表人身份证正反面复印件等。甲方应在其从事经营活动的主页面醒目位置公开营业执照登载的信息或者其营业执照的电子链接标识。

2)若甲方/甲方合作门店为自然人,应提交其姓名、地址、有效身份证明、有效联系方式等真实身份信息。此外,个人商家保证其于平台上所进行的经营活动属于无须取得营业执照及许可的便民劳务活动和零星小额交易活动。审核通过后,甲方应及时或配合乙方及时将乙方核发的证明其身份真实合法的标记加载在其从事经营活动的主页面醒目位置。

3)如证明文件或有效期发生任何变更或更新,甲方须立即通知乙方,并于【3】个工作日内,提交更新后的文件。乙方有权对甲方经营主体身份进行核验、登记,建立登记档案,并定期核验更新。

2. 甲方/甲方合作门店因资质或提供的甲方信息存在瑕疵而致使本合同无法正常履行的,甲方同意按本合同第十一条第一款约定承担违约责任。                                    

第四条 费用及支付方式

(一)费用

1. 交易类产品服务费:针对买单、预订等交易类产品(以下统称“交易类产品”),用户每实际消费一张兑换券或通过买单功能每实际消费一次,甲方应向乙方支付服务费。服务费单价计算标准为:服务费计算基数*服务费费率,服务费费率以双方通过书面、邮件或商家中心确认的数据为准;服务费计算基数包括但不限于用户消费款项,但双方通过书面、邮件或商家中心确认另行约定的情况除外。甲方同意并确认,授权乙方关联方/合作方实时于用户消费款项中扣除上述服务费,并将该结算净额按约定支付给甲方。甲方知悉、理解并同意,乙方可基于外部经济及市场环境变化、甲方经营风险和履约情况变化及乙方自身业务经营需要等因素适当调整交易类产品的技术服务费费率标准,但乙方需提前7天通知甲方并与甲方就费率变化进行磋商。

2. 其他产品服务费:

2.1除交易业务外,本合同涉及的推广技术/广告/内容营销服务、小程序等服务费及付款方式,按照双方后续签订的订单或方案为准,甲方应在具体服务上线前将款项付给乙方。未及时付款造成的损失将由甲方承担。

2.2推广技术/广告/内容营销服务费用特别提示:

2.2.1若因甲方违反本合同约定、平台规则或存在其他违法、侵权行为被乙方下线产品或隐藏门店,造成本合同提前终止/解除或乙方暂停/中止提供服务的,甲方不应要求退还任何部分或全部推广技术/广告/内容营销服务费用。

2.2.2 若双方协商一致终止方案,方案终止时间以商家中心确认的时间为准,乙方将按后台确认的剩余金额退款。

2.2.3 甲方理解并同意,乙方有权根据法律法规、行业规范、地方条例等相关规定,随时调整服务内容以满足合规要求,例如根据《未成年人保护法》的相关规定,过滤、屏蔽、停止向未成年人推送不适宜其身心发展的内容。甲方不得就该类调整向乙方提出索赔或主张。

(二)结算条款

1. 结算净额支付方式:

甲方确认自产品信息发布/约定功能上线之日起,乙方关联方/乙方合作方应按双方约定的结算周期将结算净额结算到甲方账户,甲方指定的支付账户信息及结算周期以甲方在乙方商家中心确认的信息为准;如遇周末、节假日,则推迟到下—个工作日结算。若双方数据存在差异,甲方同意结算净额数据以乙方商家中心数据为准。本合同项下款项结算活动,依据甲方另行签署的包括但不限于《钱袋宝商户服务协议》及乙方平台制定和发布的规则和流程进行;如遇周末、节假日,则推迟到下一个工作日结算。合作期满,若实际消费所对应的结算净额总金额低于乙方关联方/乙方合作方已支付结算净额时,甲方应按照乙方关联方/乙方合作方已支付结算净额与实际消费对应的结算净额之差额,向乙方支付相应款项。

2. 其他非交易业务服务费的结算周期及结算账户以订单或方案约定为准。

(三)账户

1. 如甲方需向乙方支付款项,仅可支付至乙方确认的对公账户中,乙方不会要求甲方将款项支付至任何对私账户。

2. 甲方根据业务不同需支付至乙方指定的对公账户。若双方后续签署的订单所述账户与下述收款账户不一致的,以订单约定的乙方对公账户为准。乙方收到甲方付款且甲方提交开票申请后,乙方向甲方开具增值税发票(技术服务费/广告费,发票类型以商家中心显示的产品性质为准)。

3. 甲方在签约过程中以填写、勾选、点击等任何方式确认的银行账户为甲方指定的结算账户,甲方需确保合法拥有该账户。甲方前述账户信息如有变更,双方应另行通过商家中心确认或书面约定。

第五条 信息发布

(一)甲方应对通过平台发布的信息(包括但不限于图片、视频及文字信息)的合法性、真实性承担全部责任,甲方承诺,使用平台服务发布的任何信息应符合以下规定:

1. 不得含有任何违反中国有关法律、法规的内容,包括但不限于危害国家安全、国家秘密,淫秽色情、虚假、违法、封建迷信、诽谤、恐吓或骚扰,侵犯他人知识产权、人身权或其他合法权益或利益、违反广告法等以及有违公序良俗的内容;

2. 不存在假冒、伪劣等侵犯用户权益的信息,具备国家法律法规或者部门规章要求的相应资质,符合国家、行业的质量标准,并通过了相应的行政审批;

3. 不得发布任何吸引用户到其他平台或甲方自身平台或渠道进行交易的信息,不得采取任何方式将乙方用户吸引到乙方平台以外的平台或场所。违反本款规定,乙方有权单方解除本合同,并要求甲方承担违约责任;

(二)乙方有权对甲方拟在平台发布或已经发布的内容、信息及素材进行形式审核,若该等内容、信息及素材不符合法律法规及本合同要求,乙方有权要求甲方进行纠正。必要时乙方/乙方关联方/乙方合作方有权依据法律法规、政策规定及平台规则拒绝发布商家拟发布的违反本条规定的信息,对已发布的该类信息乙方有权进行屏蔽、删除等必要处置。该等审查仅为形式审查,并不豁免甲方本身的合法性保证义务,同时乙方并不因其审查行为而对相关内容、信息、素材和其表现形式的合法性、真实性及可能引起的后果承担任何责任。如因甲方提供/发布的内容、信息或素材发生纠纷的,由甲方自行承担所有责任,造成乙方损失的,甲方应承担赔偿责任。

(三)甲方应自行管理(上传、修改、删除)发布在平台上的产品信息,但为了保障消费者的合法权益,对于消费者已经购买的订单,甲方应按消费者购买时的约定/修改后以更有利于消费者的约定履行。

(四)甲方保证其应在乙方要求的时间内提交推广技术/广告/内容营销服务相关的证明文件,包括但不限于广告审查证明、商标权证明或授权文件、著作权证明或授权文件、肖像权授权证明、批准文号、检验报告以及其他用以证明其推广技术/广告/内容营销服务内容真实、合法与有效的证明材料。

(五)甲方或甲方发布的信息或甲方的活动或行为被行政司法机关违法调查或遭受第三方投诉时,乙方有权停止向甲方提供平台服务(包括但不限于停止甲方使用相关商家中心管理账户权限、下线甲方商品/服务、停止向甲方提供推广技术/广告/内容营销服务、隐藏甲方门店、冻结甲方在平台上的结算款项等),情节严重的,乙方有权选择终止本合同。若乙方选择终止本合同,本合同自乙方向甲方发出终止通知之日起解除,甲方已支付款项不予退还。甲方尚未支付款项的,甲方按本合同所约定的推广技术/广告/内容营销服务款项向乙方全额支付。

第六条 商品/服务质量保证

(一)甲方应合法经营,所销售或者提供的商品/服务应当符合保障人身、财产安全的要求,不得销售或者提供法律、法规禁止交易的商品/服务。

(二)乙方有权对甲方在乙方平台销售的商品/服务进行定期或不定期的抽查、核查、鉴定。甲方对其所销售的商品承担质量保证责任。

(三)如果甲方所销售商品抽检不合格或无法向乙方提供相关商品及批次质量合格的证明文件,乙方有权提出终止本合同或相应的限期整改要求。甲方必须配合限期整改及根据乙方的要求进行指定商品的第三方检测,并完全承担因此产生的所有费用。

(四)如因甲方行为或甲方提供的商品/服务造成用户损失的,由甲方承担相应的赔偿责任。如乙方/乙方关联方/乙方合作方基于前述情况向用户先行赔付的,甲方同意授权乙方关联方/乙方合作方自甲方在乙方关联方/乙方合作方开立的各类账户余额中扣除对应款项,账户余额不足的,甲方应在收到乙方通知后10日内补足,未及时补足的,乙方有权向甲方继续追偿。

第七条 商家中心管理账号

(一)甲方在乙方商家中心平台拥有管理账号,该管理账号对应唯一一组用户名及密码。甲方只有以该管理账号登录商家中心,才能在商家中心进行各种操作。甲方商家中心管理账号的权限包括但不限于变更、确认如下事项:双方合作门店信息;双方合作多门店对应的结算账号;双方各合作方案涉及的服务费;双方合作的各项技术服务;各项技术服务的具体内容等。

(二)甲方在登录、使用商家中心相关账号的过程中应遵守以下规定,否则,甲方将承担由此造成的一切损失:

1. 应妥善保管各类账户的账号及密码,不得将账户出借、转让或用作其他用途;

2. 应对各类账号及以该等账号登录乙方平台后所上传、编辑的各类产品、服务、数据的合法性、完整性和保密性负责;

3. 应依照法律法规的规定保留软件访问日志记录,包括发布的信息内容及其发布时间、互联网地址(IP)、域名等,国家有关机关依法查询时应配合提供。

第八条 甲方权利义务

(一)甲方应合法经营,并保证其在平台发布的产品符合我国法律、行政法规、规章及行业等要求的质量标准,如因甲方提供的产品造成用户损失的,由甲方承担相应的赔偿责任。

(二)甲方应按照合同约定、页面信息及平台方规则向用户提供商品/服务,若相关合同约定、页面信息或规则描述有歧义的,乙方有权按有利于消费者的角度解释,由此造成的用户投诉、经济损失(包括但不限于乙方给用户的补偿金、赔偿金)等相关后果均由甲方承担。对于用户无法正常消费的,甲方应及时予以解决,否则造成用户投诉要求退款或补偿的,甲方应直接给予用户全额退款并按照乙方平台规则确定的补偿标准对用户进行补偿。甲方同意,甲方未能及时解决用户投诉,乙方/乙方关联方/乙方合作方有权按照平台规则中对于用户的保障规则或承诺向用户提供赔偿,乙方提供赔偿后,甲方应主动向乙方/乙方关联方/乙方合作方支付赔付金额及因此遭受的其它损失。甲方同意乙方关联方/乙方合作方从结算净额款项中扣除相应赔付金额,若不足以扣除的,则甲方应在收到乙方通知后10日内补足,且甲方不可撤销地放弃在乙方先行赔偿后提出对赔偿异议的权利。甲方同意,针对甲方无法接待、拒绝接待或与其他消费者相比差异性接待用户等情形,乙方有权下线甲方产品/服务,且对于其余用户订单乙方有权进行批量退款处理,由此产生的赔付或补偿金均由甲方承担。本条款前述的用户投诉情况包括但不限于:甲方提供的产品实际情况与页面展示的产品信息不符;甲方无法接待、拒绝接待或与其他消费者相比差异性接待用户等情形。

(三)如甲方及其相关门店提供上门服务,则甲方及其相关门店将按照乙方平台页面的展示方式和规则进行展示。甲方应在页面信息和/或商家中心准确、及时地标注/设置/确认/勾选/点击甲方提供上门服务的地理服务范围。地理服务范围发生变化时,甲方应及时在页面信息和/或商家中心进行变更,甲方在完成变更前,仍应按照原地理服务范围提供上门服务。

(四)甲方应根据用户实际支付的金额为用户开具相应金额的发票。

(五)甲方不得虚标价格,不得唆使或诱使持兑换券消费的用户放弃兑换券而改为使用现金或其他形式消费,否则乙方有权立即终止本合同并要求甲方按照本合同约定承担违约责任。此外,甲方应确保通过平台上线售卖的商品不应存在对平台用户的价格歧视,即针对同样的商品或服务,确保平台用户购买时的价格不高于指定第三方渠道。若甲方通过开通平台服务,授权平台智能管理商品供给(包括但不限于自动上单、价格调节、选择商品供给并按大促活动的折扣要求参与平台的大促活动等),甲方确保对调整后的订单提供正常接待和履约保障。

(六)对于已成交但并未实际消费的兑换券,无论该兑换券有效期是否届满,甲方授权乙方关联方/乙方合作方留存该兑换券所对应的款项,并根据订单的约定及用户的要求与意愿,处置相应款项。

(七)甲方应在用户消费时及时通过商家中心验证兑换券,因甲方怠于履行验证义务而导致的一切损失由甲方自行承担。

(八)对合作产品涉及的可能危及用户人身、财产安全的事项,甲方及其工作人员应当向用户作出真实的说明和明确的提示,并采取防止危害发生的必要安全保障措施。若发生危及用户人身安全的情形,甲方及其工作人员应当采取必要的处置措施并立即以书面、电子邮件形式通知乙方。若因此导致乙方/乙方关联方/乙方合作方利益受损的,乙方有权下线甲方合作产品,并向甲方进行追偿。

(九)甲方应主动或按照乙方的要求,在页面显著位置上向用户展示详尽的安全保障注意事项。如用户向甲方提出任何咨询疑问,甲方应予以耐心、详细解答。甲方应在向用户提供商品/服务的过程中完整、及时地向用户提示相关安全保障注意事项。

(十)甲方应积极参与乙方所组织的产品/服务相关安全知识培训。

(十一)兑换券已被验证后甲方与用户就商品和/或服务是否交付、交付质量存在争议的,平台仅有协调义务,甲方仍有未完成服务或未交付商品的,甲方有义务按消费者要求继续履行。

(十二)甲方若要终止从事电子商务的(包括但不限于终止与乙方合作、变更合作品类等情形),甲方应提前30日在甲方首页位置及所售卖的商品/服务页面持续公示有关信息并提前至少30天以书面形式通知乙方。如因甲方违反本条约定,产生的一切结果由甲方负责,甲方还需赔偿乙方/乙方关联方/乙方合作方因此遭受的损失。

(十三)甲方同意用户通过平台发布的针对甲方的评论、图片、视频等,纯属用户个人意见,与乙方立场无关,甲方有权向相关用户主张权益并豁免乙方的责任,若甲方坚持向乙方主张权益(包括但不限于起诉或投诉乙方),乙方有权暂停向甲方提供本合同相关的服务并不承担任何违约责任。

(十四)甲方不得通过任何手段、以任何方式自行或者委托他人进行如下行为(包括但不限于虚拟交易、虚拟验证、自买自卖、教唆或诱导甲方用户直接到店消费/通过第三方进行下单、伪造网络用户真实消费/体验、刷单、恶意合并门店等违反平台规则、干扰平台运营秩序、损害乙方/乙方关联方/乙方合作方利益的行为,或伪造、仿冒等其他违反国家法律法规的行为,或其它违反公平竞争诚实信用原则与商业道德的行为),否则,乙方有权解除合同,有权要求乙方关联方/乙方合作方暂停支付结算净额,并要求甲方按照本合同约定支付违约金。同时,甲方不得通过任何手段、以任何方式自行或委托他人进行扰乱评价客观性、真实性等,虚假点击炒作流量、虚假购买等违反《诚信公约及管理办法》的行为,否则,乙方/乙方关联方/乙方合作方有权对甲方进行相应的处罚(包括但不限于星级清零、评价不展示、搜索排序降权、交易关闭甚至下线门店等);因上述处罚产生的一切不利后果和损失由甲方自行承担(包括但不限于甲方推广技术/广告/内容营销服务产品可能受到的影响)。

(十五)如在合同履行期限内,因甲方原因造成的方案、项目或合同中止(包括但不限于服务方案已下线或停止营业),甲方应及时书面通知乙方,并对产品进行下线或修改。如因甲方怠于通知并修改造成的一切纠纷和责任(包括但不限于用户要求履行合同/订单、用户投诉、行政机关处罚等)由甲方承担,若由此给乙方/乙方关联方/乙方合作方造成经济损失,甲方应进行赔偿。

(十六) 甲方不得在使用乙方提供的服务的过程中进行以下行为:

1. 从事破坏或试图破坏网络安全的行为(包括但不限于钓鱼,黑客,网络诈骗,网站或空间中含有或涉嫌散播:病毒、木马、恶意代码,及通过虚拟服务器对其他网站、服务器进行涉嫌攻击行为如扫描、嗅探、ARP欺骗、DDOS等);

2. 散布电子邮件广告、垃圾邮件,利用乙方提供的服务散发不受欢迎的或者未经请求的电子邮件、电子广告或包含反动、色情等有害信息的电子邮件;

3. 利用乙方提供的服务从事损害乙方、乙方关联方、乙方网站合法权益之行为;

4. 以任何方式直接或间接导致用户误认为平台为甲方所进行的相关交易的相对方,不得唆使、诱使用户向平台就交易相关事项进行索赔。

5. 其他违反法律法规、平台规则或双方间另行签订的其他协议、规则、条款的行为。

(十七)经乙方通知后,甲方应在合理的时间内向乙方及其审计人员(包括内部审计人员和外部审计师)、检查人员、监管人员和其他合理指定的代表提供途径以便乙方对甲方提供服务的系统、数据和记录进行安全审计(包括调查问卷、系统安全性测试等),用于核查遵守本合同的情况(包括保密条款、数据安全义务以及本合同的其他条款),甲方应对该等合理审计要求提供协助。

(十八)如甲方或甲方的关联方、董事、雇员做出任何影响中华人民共和国国家安全、破坏中华民族团结、伤害中华民族情感的不当行为,包括但不限于:(i)做出或发表任何鼓动或支持暴力或恐怖活动、分裂国家、煽动叛乱、颠覆政权或其他损害国家安全、破坏中华人民共和国领土和主权完整的行为或言论;(ii)做出或发表煽动民族仇恨、民族歧视或其他破坏民族团结的行为或言论;及(iii)做出或发表伤害民族情感及歪曲中国历史的行为或言论,乙方有权立即删除甲方在乙方平台上发布或展示的全部或部分相关产品、服务或信息,断开与甲方产品与服务的全部链接,并要求甲方采取有效的补救措施,包括但不限于要求停止不当行为并进行公开道歉。如甲方拒不采取补救措施或甲方做出的补救措施无法弥补不利影响,或乙方认为不当行为情节严重的,乙方无需书面通知甲方即有权立即解除本合同,并要求甲方赔偿乙方因此而产生的所有损失。乙方亦有权视情况在无须经过甲方同意的情况下通过媒体公开双方合作关系终止的事实。如乙方选择终止本合同的,甲方应立即返还乙方已预付给甲方但尚未消耗完毕的所有费用(如有)。

(十九)未经乙方事先书面许可,不应自行或授权、协助任何第三方非法抓取平台所展示的任何内容(“非法抓取”是指采用未经乙方认可的程序或者非正常浏览等技术手段获取内容数据的行为)。

(二十)关于甲方的其他权利与义务详见《青年夜校服务平台商户管理制度》。

第九条 乙方权利义务

(一)乙方应向甲方提供本合同约定的技术服务及其他相关服务。

(二)为更好的推荐甲方及其商品/服务,以提升甲方的知名度/订单量,乙方可通过适当的方式和渠道做相关宣传介绍,并进行相关推荐/推广。甲方对上述行为予以认可,并授权乙方/乙方关联方/乙方合作方就甲方及其相关门店的名称、LOGO、图片、文字、会员优惠等信息进行使用。

(三)如用户就甲方商品/服务向乙方/平台实际经营者投诉,乙方经核实后,有权要求甲方配合解决该投诉,在该投诉未解决之前乙方关联方/乙方合作方有权留存涉及投诉的结算净额,待投诉解决后再根据处理结果进行相应处置。

(四)乙方有权升级、更新商家中心系统,如有变更,乙方将通过前述系统以公告形式作出通知。如乙方在商家中心开发新功能或其他服务且双方尚未签署独立协议的,甲方仍可在乙方/乙方关联方/乙方合作方书面同意下获取相应功能或服务授权,并适用本合同约定。

(五)推广技术/广告/内容营销服务过程中,甲方可以修改相关素材内容,但所有素材内容应该符合乙方的有关推广技术/广告/内容营销服务内容审核规则,且应提前3日向乙方提供,经乙方确认后方可修改。

(六)为更好保护平台经营环境,实现平台更好的用户体验,乙方将依法不定期对平台页面及品类进行调整,诸如品类划分、调整及重复、虚假商户清理,因此导致本合同无法继续履行的,不视为乙方违约。

(七)如甲方或甲方合作产品供应商遭受政府处罚或媒体曝光、用户投诉或乙方认为甲方存在其他可能导致无法继续完全履行本合同约定之权利义务的情形(包括但不限于甲方通过媒体、市场监管部门等行政投诉等方式给平台施压,损害乙方利益的)发生时,乙方有权对上线合作产品予以下线处理,必要时,有权解除本合同。

(八)若甲方连续3个月内出现无产品/服务在线,或连续3个月内产品/服务无销量的情形,乙方有权即时单方终止本合同,且不视为乙方违约。

(九)乙方将基于整体市场考虑对推广技术/广告/内容营销服务进行适时灵活的业务性调整或产品性调整(包括但不限于客户资质标准、销售政策、展现机制、计费标准、产品类型、服务升级、服务功能调整、服务整合等),乙方将提前7天向甲方发出调整通知,如甲方继续使用乙方提供的推广技术/广告/内容营销服务的,即表示甲方接受调整。

(十)甲方同意,用户通过平台购买甲方产品后,如符合下列情形之一的,用户可申请退款,甲方需配合完成用户的退款流程(如需)。如甲方怠于配合的,乙方可直接给予用户退款或者向用户先行赔付,并直接从甲方的结算净额中扣除相应款项:(1)产品支持退款,用户下单后未核销的,可根据平台规则申请退款;(2)产品虽不支持退款,但因为不可抗力、疫情等原因导致用户无法消费的,用户可申请退款;(3)用户核销后,因产品/服务问题向平台投诉的要求退款的,按照本协议约定处理;(4)因商户原因导致用户无法按照购买时的产品规则正常消费的。

第十条 数据及信息的使用

(一)对于甲方在使用平台过程中提供、上传的信息(包括门店的名称、LOGO、视频、图片、文字、交易产品信息等),乙方/乙方关联方/乙方合作方有权使用。而对于甲方在使用平台过程中形成的信息(包括经营信息、优惠信息、优惠核销信息、评价等)乙方具有所有权和使用权,且乙方有权将上述信息传递给其他相关服务提供者。为了推广平台或者平台产品,乙方有权使用甲方门店的名称、LOGO、图片、文字、门店、会员优惠、合作商品、合作效果数据等信息,包括但不限于制作产品手册、宣传手册等。

(二)如在合作过程甲方获悉用户数据/信息的,甲方应当确保用户数据/信息的保密及安全,不得将用户数据/信息用于非约定或非法的场景。乙方保留对甲方关于用户数据/信息安全情况的审查权利,当乙方审查时甲方应当积极配合乙方工作,如发现甲方存在用户数据/信息保护不到位、用户数据/信息滥用、存在严重泄露等问题,乙方有权根据审查结果下线甲方合作产品、解除合同,并且如已产生实际损失和不良影响,由甲方承担全部责任。如合作中涉及甲方填报、录入或者向乙方提供任何用户信息的,甲方承诺其已获得相关信息主体的授权并保证该等信息的真实、准确,且符合《个人信息保护法》及相关法律法规的要求。

(三)为了更好地向甲方提供相关服务,甲方不可撤销地授权乙方对甲方店铺(含产品)在乙方平台上的相关信息进行加工、处理、分析,并将甲方店铺在乙方平台上的相关信息及相关加工、处理、分析结果展示在商家中心中,为其他商户提供服务。甲方前述授权是免费的且长期有效,不因本合同的中止、终止、失效而中止、终止或失效。

第十一条 违约责任

(一)除非本合同另有约定,如甲方违反诚信原则,或违反本合同约定条款或平台规则,或甲方违反其在本合同的履行中做出的任何承诺和保证,或甲方提供的资质、证照等信息不属实,或未向平台提供服务所需的资质、证照的,则乙方有权采取暂停服务(包括但不限于限制甲方管理员账户登录或隐藏甲方合作门店等)、下线产品、停止向甲方结算款项或单方解除合同等措施,并要求甲方按照自本合同生效之日起累计至甲方发生违约行为之日止的用户消费款项总额和甲方支付的推广技术/广告/内容营销服务费用总额二者总和的30%向乙方支付违约金。甲方不应要求乙方退还任何部分或全部已支付的款项。

乙方也可以给予一定期限要求甲方纠正违约行为,纠正期间乙方可停止向甲方提供服务(包括但不限于对合作产品下线、门店隐藏等)并停止通过乙方关联方/乙方合作方向甲方结算款项,如甲方在乙方要求的期限内纠正违约行为后符合本合同约定的,乙方恢复向甲方提供服务,并通知乙方关联方/乙方合作方继续向甲方结算款项;如甲方在乙方要求的期限内拒绝纠正或纠正后仍不符合本合同约定的,乙方仍有权要求解除本合同。若上述违约金不足以弥补乙方损失的,甲方还应赔偿乙方因此遭受的全部损失,包括但不限于因遭受行政处罚或需向第三方承担民事责任造成的损失。

(二)在甲方无任何违约情形下,因乙方未能按照合同约定履行义务,且在甲方要求的期限内拒绝纠正或纠正后仍不符合本合同约定的,乙方应承担因此给甲方造成的损失。

第十二条 保密义务

(一)任何一方均应对本合同的内容、本合同的签署及履行情况以及在本合同的签订和履行过程中获悉的对方的所有信息(包括但不限于商业信息、经营信息及相关资料、秘密信息或保密资料)承担保密义务,未经对方事先书面同意,一方不得以履行本合同以外的目的使用秘密信息。若违反本规定给对方造成损失的,应承担赔偿责任。保密信息是指在各方磋商及履行任何协议过程中一方(“接收方”)从其他方(“披露方”)所获得的或披露方向接收方所提供或披露的与披露方的研究、开发、生产、产品、服务、客户、市场、销售等内容有关的任何信息、软件、程序、工艺、专有技术、流程、方式、客户名单、供应商信息、合同、价格、成本、研究报告、预测和估计、报表、商业计划、销售计划、商业秘密、商业模式、公司决议等任何或所有的商业信息、财务信息、技术资料、生产资料以及会议资料和文件,而无论其是以书面形式、口头形式还是电子数据传输或存储形式为之。

(二)甲方承诺并保证,与乙方合作过程中不会利用直接或者间接的任何技术手段侵犯乙方的数据安全。未经乙方同意,不会擅自将乙方保密资料,包括但不限于业务、经营、财务状况、用户数据等直接或间接泄露任何第三方。

(三)本合同任一方若得知所保管的另一方的任何保密信息已经被第三方获得,则应及时通知对方,并向对方提供掌握的所有相关情况。

(四)本合同任何一方均应对所获得的另一方的保密资料实施必要的安全保护措施,保护措施应当至少涵盖以下要求:

1. 对于保密资料的访问应当充分做好访问控制(包括技术层面、物理层面),应仅限于有合法授权的相关人员或者相关应用进行访问;

2. 禁止在第三方信息平台(如网盘、网站、博客等提供信息存储的平台)公开存储或处理对方的保密资料;

3. 应当确保用于存储保密资料的技术平台安全性(包括网站、应用系统、操作系统、服务器、数据库等);

4. 应当对指定保密信息(如用户信息等)的传输和存储实施满足国家及监管要求的加密安全措施。

(五)任何一方如发现对方存在涉及保密资料保护措施缺失、数据滥用、严重泄露等问题,发现方有权按照本合同相关条款以及法律法规规定进行处理,并且对于已产生的实际损失和不良影响,有权向违约方追究法律责任,并追偿全部损失。

(六)本保密条款不因双方合同终止而失效,也不因本合同其他条款整体或部分的无效、被撤销而丧失效力。

第十三条 廉洁条款

(一)双方均应严格遵守我国相关法律法规规定,特别是禁止商业贿赂的有关规定,恪守商业道德,共同营造合法公平公正的交易环境。甲方不得为了获取与乙方的合作及合作的利益,向乙方工作人员及其关联人员给予任何物质或精神上的直接或间接的不正当利益,包括但不限于直接或间接赠送礼金、物品、有价证券或采取其他变相手段提供现金、支票、信用卡礼品、样品或其他商品、娱乐票券、会员卡、购物卡、货币或货物形式的回扣、回佣、就业或置业、甲方付款的旅游、培训、赠送门店体验项目、宴请及个人服务等。

(二)甲方不得向乙方工作人员及其关联人员提供任何形式的借款;甲方的股东、高管(包括但不限于董事、监事、经理、财务负责人等)、合作项目负责人及项目成员系乙方工作人员或其关联人员的,应在合作前以书面方式如实、完整地告知乙方;合作过程中,甲方不得允许乙方工作人员及其配偶持有或由第三方代持有甲方股权(但通过公开的证券交易市场且低于发行在外5%的权益、通过直接或间接持有无实际控制权的基金、或通过受益人非本人或关联人员的信托方式持有的股份除外),亦不得聘用乙方工作人员(包括但不限于建立正式劳动关系、劳务派遣、外包服务、兼职、顾问等形式)。甲方如有聘用乙方工作人员配偶及其他乙方关联人员任职于甲方的,应在聘用之日起三日内以书面方式如实、完整地告知乙方。

(三)甲方违反上述约定行为之一的,乙方有权单方解除与甲方的合同,甲方应赔偿乙方的所有损失,同时乙方有权将甲方列入“合作商黑名单”,向乙方及其所有关联方通报并拒绝与甲方进行任何业务合作。对于甲方,无论是主动还是被动向乙方工作人员及其关联人员提供不正当利益的,如果主动向乙方提供有效信息,乙方有权根据实际情形酌情给予甲方继续合作的机会及/或减免上述违约责任,对于上述情形的处理乙方具有独立的判断权和决定权。

(四)如甲方发现或怀疑任何人违反上述约定的,可以与乙方廉政部门联系,乙方廉政邮箱:【nib.jiancha@meituan.com】。乙方将对信息提供者及其所提供的全部资料、信息予以保密。

 

第十四条 合同终止和解除

(一)本合同有效期内,乙方有权以提前15天通知的方式,提前单方终止本合同,且此情形不视为乙方违约,乙方无须承担任何违约责任。

(二)本合同期限届满或本合同约定的其他终止情形发生时,本合同终止。本合同终止或解除后:

1. 乙方有权删除平台上已发布的产品信息,且有权拒绝提供相关信息;

2. 本合同终止前甲方已与用户达成的尚未履行完毕的订单,甲方应按照本合同及订单的约定继续履行相应义务;

3. 如乙方已经按照合同规定提供的推广技术/广告/内容营销服务,甲方应按本合同规定的服务费就已经提供的服务向乙方支付费用;

4. 按照相关法律法规,甲方理解并同意乙方保存甲方资质信息、产品信息、交易记录等相关资料。

第十五条 免责条款

(一)因战争、自然灾害、政府行为、法律、法规及政策变更、互联网系统故障、互联网通讯提供商故障、系统升级等不可抗力因素或第三方原因导致乙方不能履行本合同项下义务,乙方无须承担责任。

(二)甲方同意,因下述两种特殊情形导致乙方不能按时发布信息展示的,不视为乙方违约:

1. 甲方理解,基于市场整体利益考虑及经营需要,乙方可能不定期对服务内容、版面布局、页面设计等有关方面进行调整,如因上述调整而影响甲方信息展示的发布(包括发布位置和/或发布期间等),甲方将给予充分的谅解,乙方则应尽可能将上述影响降低到最低程度。

2. 甲方理解,为了信息展示发布媒体正常运行,乙方需要定期或不定期地进行停机维护,如因此类情况而造成甲方信息展示不能按计划发布,甲方将予以谅解,乙方则有义务尽力避免服务中断或将中断时间限制在最短时间内。

(三)甲方知悉、理解并同意,乙方为甲方提供平台信息技术服务,乙方为独立的第三方平台,并非甲方与用户之间的交易相对方或具体服务的提供方,亦不参与甲方与用户之间的任何交易。甲方向用户提供商品/服务的过程中所产生的全部权利义务,由甲方自行承担,乙方不是最终赔偿责任的承担方,亦不向甲方承担因具体交易所引起的任何责任。

第十六条 知识产权

“青年夜校服务平台品牌知识产权”是指乙方/乙方关联方名下的所有商标权、著作权、专利权、商业秘密、商号权、域名、网站和其他已经形成或将来即将形成的全部知识产权;在相关服务中所提供的内容和信息(包括但不限于软件、技术、程序、网页、文字、图片、图像、地图、图标、音频、视频、图表、版面设计、电子文档、数据资料等);用于提供上述内容和信息的基础设施和平台(包括但不限于软件、网站、应用程序等);在提供相关服务中所使用的各项商标、商业形象、商业标识、技术诀窍、标语、文案等;乙方平台服务的开发、运营、维护等过程中产生的所有数据和信息。甲方同意并遵守如下有关“青年夜校服务平台品牌知识产权”的各种事项:

(一)甲方不得使用青年夜校服务平台品牌知识产权”或可能令人混淆的与“青年夜校服务平台品牌知识产权”类似的任何名称、标识,或将“青年夜校服务平台品牌知识产权”其中任何一项作为甲方/甲方关联方的公司名称或商号的一部分,不得单独使用或与任何其他字样或名称一起使用。

(二)甲方确认其仅可依据平台的指示及事先批准使用青年夜校服务平台品牌知识产权”,除按本次合作中的规定使用“青年夜校服务平台品牌知识产权”外,没有、也不应理解为乙方已授予甲方任何“青年夜校服务平台品牌知识产权”或相关利益。

(三)甲方承诺尊重乙方/乙方关联方对其商标及相关知识产权的独占性及合法使用权,保证不从事、配合、支持或帮助任何侵犯及仿冒“青年夜校服务平台品牌知识产权”的事项或行为,并且应将任何其所知晓的侵犯及仿冒“青年夜校服务平台品牌知识产权”的行为迅速地通知乙方/乙方关联方。

(四)甲方不得将青年夜校服务平台品牌知识产权”或与之相似的标识使用或印制于未经乙方/乙方关联方事先书面许可的物品、产品或用于其它用途。

(五)甲方不得就青年夜校服务平台品牌知识产权”的权利提出任何争议或质疑,也不得配合、支持、帮助第三人就“青年夜校服务平台品牌知识产权”的权利提出任何争议或质疑。

(六)甲方不得就与青年夜校服务平台品牌知识产权”相同或近似或类似的知识产权进行恶意的商标注册、版权登记或者专利申请,包括但不限于甲方不得在“青年夜校服务平台品牌知识产权”未注册的商品/服务类别上申请注册与“青年夜校服务平台品牌知识产权”相同或近似的商标,也不得在任一商品/服务类别上申请注', + 'home_top_image' => '/uploads/20241219/9848f9fcc2f637e5f9673a9b0bbb4220.png', + 'home_top_type' => 'in', + 'home_top_url' => '/pages/index/group', + 'admin_approved_swtich' => '1', + 'shop_backend_url' => 'https://testy.hschool.com.cn/manystore', + 'free_time_overlap_check' => '0', + 'all_time_overlap_check' => '1', + 'shop_auth_user_check' => '1', + 'same_hour_cancel_number' => '3', + 'free_classes_cancel_check' => '0', + 'free_classes_not_verify_num' => '3', + 'free_classes_onlyone_check' => '1', + 'privacy' => '

洛阳青年夜校隐私政策

 

“洛阳青年夜校”小程序是共青团洛阳市委针对洛阳市青年夜校打造的一款集选课、报名、教师授课、学习交流于一体的综合服务平台。平台通过数字化手段,为洛阳市青年群体提供更加便捷、高效、丰富的夜校学习体验。

欢迎你使用我们的产品和服务!我们深知个人信息对你的重要性,你的信任对我们非常重要,我们将根据法律法规要求并参照行业最佳实践为你的个人信息安全提供充分保障。鉴于此,洛阳青年夜校制定本《隐私声明》(下称“本声明/本隐私权声明”)以帮助你充分了解在你使用我们的产品与/或服务时,我们如何收集、使用、保存这些信息,以及我们为你提供的访问、更新、删除和保护这些信息的方式。

本隐私声明将帮助你了解以下内容:

一、我们如何收集和使用你的个人信息

二、我们如何“公开披露”你的个人信息

三、我们如何保护和保存你的个人信息

四、你如何管理个人信息

五、未成年人的个人信息保护

六、通知和修订

七、如何联系我们

本声明适用于洛阳青年夜校提供的所有产品和服务。我们及关联公司就其向你提供的产品或服务单独设立有隐私权声明的,则相应产品或服务适用相应隐私声明。需要特别说明的是,本隐私声明不适用于其他第三方通过前述网页或客户端或者小程序或公众号等向你提供的服务。例如你通过洛阳青年夜校使用第三方应用(如第三方电商小程序)或者服务,或第三方服务和产品依托洛阳青年夜校产品向你提供服务时,你向第三方提供的信息不适用本声明。

在使用洛阳青年夜校各项产品或服务前,请你务必仔细阅读和理解对应的隐私声明和以下的条款,你应重点阅读,确认你充分理解并同意后再开始使用。

如对本声明内容有任何疑问、意见或建议,你可与我们联系。

我们将担任“个人信息处理者”,亦即我们将决定“为何”和“如何”收集和使用你的个人信息”。

为提供我们的产品及服务给你,我们需要和我们的“个人信息受托者”,即认可的商业伙伴或我们的关联合作伙伴共享你的个人信息。他们均负有采用适当安全措施以保护所持个人信息的义务,受严格的保密义务所规范,且“为何”和“如何”可以代替我们处理你的个人信息均受相关合同条款所约束。

请注意部分认可的商业伙伴,如被授权商或社交媒体,也可以决定“为何”和“如何”使用你的个人信息。他们有各自的隐私和cookies政策,故请谨记他们使用你提供给他们的任何个人信息的方式应适用他们的规定,而不适用我们的规定。

如你作为消费者,你授权给商家的个人信息,我们仅作为商家的个人信息受托者。

为了解我们的角色,请注意我们“为何”和“如何”收集和使用你的个人信息,来决定处理你个人信息的目的和方式。我们的“个人信息受托者”则是由我们指示“为何”和“如何”可以代替我们处理你个人信息的机构。

第一部分定义

一、【洛阳青年夜校洛阳青年夜校是由共青团洛阳市委针对洛阳市青年夜校打造的一款集选课、报名、教师授课、学习交流于一体的综合服务平台。平台通过数字化手段,为洛阳市青年群体提供更加便捷、高效、丰富的夜校学习体验。

二、【平台主体】共青团洛阳市委对平台进行管理监督,并委托洛阳灵睿网络技术有限公司运行服务

三、【洛阳青年夜校服务】洛阳青年夜校服务指由洛阳青年夜校开发和服务的洛阳青年夜校课程、场馆、活动预定、活动报名、体育培训、选课、报名、教师授课、学习交流等服务,以及将洛阳青年夜校部分功能/服务作为第三方服务集成在洛阳青年夜校关联公司(见定义条款)和/或其他第三方软件和/或智能硬件而提供的服务。

四、【个人信息删除】个人信息删除指在实现日常业务功能所涉及的系统中去除个人信息的行为,使其保持不可被检索、访问的状态。

五、【洛阳青年夜校支付】洛阳青年夜校支付即第三方支付,微信和支付宝。

六、除另有约定外,本声明所用定义与《用户协议》中的定义具有相同的涵义。

第二部分 隐私声明

一、我们如何收集和使用你的个人信息

个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。个人敏感信息是指一旦泄露、非法提供或滥用可能危害人身和财产安全,极易导致个人名誉、身心健康受到损害或歧视性待遇的个人信息。本隐私声明中涉及的个人信息包括:基本信息(包括个人姓名、住址、个人电话号码);个人身份信息(包括身份证后10位);个人生物识别信息(面部识别特征);网络身份标识信息(包括个人信息主体帐号、IP地址、个人数字证书等);个人财产信息(包括交易和消费记录、优惠券、虚拟财产信息);个人上网记录(包括网页浏览记录、软件使用记录、点击记录);个人常用设备信息(包括硬件型号、AndroidID、设备MAC地址、操作系统类型、设备设置、运行中进程信息、软件安装列表、已经安装包名列表、硬件序列号、唯一设备识别码(如IMEI/AndroidID/IDFA/OPENUDID/GUID、SIM卡序列号、SIM卡IMSI信息等在内的描述个人常用设备基本情况的信息));个人位置信息(包粗略定位信息、精准定位信息等);其中字体加粗部分为涉及的个人敏感信息。

为确保本应用处于关闭或后台运行状态下可正常接收到客户端推送的广播信息,本应用须使用(自启动)能力,将存在一定频率通过系统发送广播唤醒本应用自启动或关联启动行为,是因实现功能及服务所必要的。

我们会通过如下渠道获取你的个人信息:

(一)你直接提供给我们及我们收集的个人信息

请你注意,如果你提供的是他人个人信息,请你确保已取得相关主体的授权。

(二)我们从第三方收集的信息

 

 

(三)你可以选择授权提供个人信息的场景

为向你提供更优质的服务,我们为你提供移动应用程序,你可以选择使用我们提供的拓展功能,为确保相关业务功能的正常实现,我们需要根据具体的使用场景调用对应的必要权限,并在调用前向你弹窗询问,一般情况下,我们会在以下情况使用百度地图sdk调用定位服务: 首次使用应用时:为了提供基本的定位功能和服务,我们会在用户首次启动应用时获取一次定位信息,以确定用户当前位置。 用户手动触发定位:当用户在应用中手动触发定位功能,例如搜索附近的地点或导航至特定目的地时,我们会根据用户请求获取定位信息。 应用需要实时位置更新:在某些特定的应用场景下,例如实时导航、位置分享等,我们可能会以较高的频率获取定位信息,以确保位置信息的及时更新和准确性。 尽管我们会根据具体情况调整定位信息的获取频率,但我们也十分重视用户隐私和数据安全。因此,我们会遵循相关法律法规,并尽可能采取措施保护用户的个人隐私信息,确保定位信息的合法、合理和安全使用。 具体的权限调用说明请查看对应 权限使用列表。

 

 

(四)征得同意的例外

你应充分知晓,以下情形中,我们收集、使用个人信息无需征得你的授权同意:

1. 与国家安全、国防安全有关的;

2. 与公共安全、公共卫生、重大公共利益有关的;

3. 与犯罪侦查、起诉、审判和判决执行等有关的;

4. 出于维护个人信息主体或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;

5. 所收集的个人信息是个人信息主体自行向社会公众公开的;

6. 从合法公开披露的信息中收集的你的个人信息的,如合法的新闻报道、政府信息公开等渠道;但是你明确拒绝或者处理该信息侵害你重大利益的除外。

7. 根据你的要求签订合同所必需的;

8. 用于维护所提供的产品与/或服务的安全稳定运行所必需的,例如发现、处置产品与/或服务的故障;

9. 为合法的新闻报道所必需的;

10. 学术研究机构基于公共利益开展统计或学术研究所必要,且对外提供学术研究或描述的结果时,对结果中所包含的个人信息进行去标识化处理的;

11. 法律法规规定的其他情形。

(五)个人信息使用规则

1.我们会根据本隐私声明的约定,为实现我们的产品与/或服务功能而对所收集的个人信息进行使用。

2.在收集你的个人信息后,我们将通过技术手段对信息进行去标识化处理,去标识化处理的信息将无法识别主体。请你了解并同意,在此情况下我们有权使用已经去标识化的信息;并在不透露你个人信息的前提下,我们有权对用户数据库进行分析并予以商业化的利用。

3.请你了解并同意,对于你在使用我们的产品与/或服务时所提供的所有个人信息,除非你删除或通过系统设置拒绝我们收集,否则将被视为在你使用我们的产品与/或服务期间持续授权同意我们使用。在你注销帐号时,我们将停止使用并删除你的个人信息。

5.我们会将业务中收集的个人信息用于技术改造、网络维护、故障排除、内部政策与流程制定、生成内部报告,将已经去标识化无法识别你身份且不能复原的信息用于建立数据库并进行商业化利用。但这些统计信息不包含你的任何身份识别信息。

6.当我们展示你的个人信息时,我们会采用包括内容替换、泛化处理方式对你的信息进行脱敏,以保护你的信息安全。

7.当我们要将你的个人信息用于本隐私声明未载明的其它用途时,或基于特定目的收集而来的个人信息用于其他目的时,会事先征求你的明示同意。请你理解,我们向你提供的产品与/或服务将不断更新变化。如果你选择使用本隐私声明中尚未列明的其他产品与/或服务时,我们会在收集你的个人信息前通过协议、页面提示等方式向你详细说明信息收集的目的、方式、范围并征求你的同意。若你不同意提供前述信息,你将无法使用该项产品与/或服务,但不影响你使用现有产品与/或服务。

二、我们如何共享、公开披露你的个人信息

(一)共享

基于应用程序接口(API)、软件工具开发包(SDK)与第三方进行必要的数据共享,不同版本的第三方SDK会有所不同,一般包括第三方帐号登录类、分享类、第三方支付类、厂商推送类、统计类等,我们会对第三方进行严格的安全检测并约定数据保护措施。

关于第三方如何收集、使用你的个人信息,建议你参考第三方SDK的相关服务协议及个人信息保护声明。如果你希望进一步了解我们所接入的第三方SDK情况。

(二)公开披露

洛阳青年夜校采用行业标准惯例以保护您的个人资料,但鉴于技术限制,洛阳青年夜校不能确保您的全部私人通讯及其他个人资料不会通过本隐私条款中未列明的途径泄露出去,对此洛阳青年夜校不承担任何责任。

洛阳青年夜校有权根据有关法律和监管要求,洛阳青年夜校风险控制要求以及相关协议要求向司法机关等政府部门、社会组织或团体、其他第三方服务或合作机构提供您的个人资料。在您未能按照与洛阳青年夜校签订的服务协议、居间协议或者与洛阳青年夜校企业用户签订的借款(担保)协议的约定履行自己应尽的义务时,洛阳青年夜校有权根据自己的判断或者与该笔交易有关的其他用户的请求披露您的个人资料,并作出评论。

我们仅会在以下情况下,公开披露你的个人信息:

1.获得你明确同意或基于你的主动选择,我们会公开披露你的个人信息;

2.根据法律、法规的要求、强制性的行政执法或司法要求所必须提供你个人信息的情况下,我们会依据所要求的个人信息类型和披露方式公开披露你的个人信息。在符合法律法规的前提下,当我们收到上述披露信息的请求时,我们会要求必须出具与之相应的法律文件,如传票或调查函,并且我们披露的文件均是加密后提供。

(三)共享、公开披露个人信息时事先征得授权同意的例外

以下情形中,共享、公开披露你的个人信息无需事先征得你的授权同意:

1.与我们履行法律法规规定的义务相关的;

2.根据法律法规的规定或行政、司法机构、国家部门等有权机关的要求依法提供的;

3.出于维护你或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;

4.你自行向社会公众公开的个人信息;

5.与国家安全、国防安全直接相关的;

6.从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道

根据法律规定,共享、转让经去标识化处理的个人信息,且确保数据接收方无法复原

并重新识别个人信息主体的,不属于个人信息的对外共享、转让及公开披露行为,对此类数据的保存及处理将无需另行向你通知并征得你的同意。

(四)洛阳青年夜校对您的资料的使用

1.您同意洛阳青年夜校可使用关于您的个人资料(包括但不限于洛阳青年夜校持有的有关您的档案中的资料,及洛阳青年夜校从您目前及以前在洛阳青年夜校上的活动所获取的其他资料)以解决争议、对纠纷进行调停、有助于确保在洛阳青年夜校进行安全交易,并执行洛阳青年夜校的用户协议。洛阳青年夜校有时候可能调查多个用户以识别问题或解决争议,特别是洛阳青年夜校可审查您的资料以区分使用多个用户名或别名的用户。

为限制在网站上的欺诈、非法或其他刑事犯罪活动,使洛阳青年夜校免受其害,您同意洛阳青年夜校可通过人工或自动程序对您的个人资料进行评价。

2.您同意洛阳青年夜校利用您的资料与您联络并(在某些情况下)向您传递针对您的兴趣而提供的信息,例如:有针对性的广告条、行政管理方面的通知、产品提供以及有关您使用洛阳青年夜校的通讯。您接受服务协议和隐私条款即为明示同意收取这些资料。

三、我们如何保护和保存你的个人信息

(一)我们保护你个人信息的技术与措施

我们非常重视个人信息安全,并采取一切合理可行的措施,保护洛阳青年夜校消费者、商家及商家消费者的个人信息。

1.数据安全技术措施

为保障上述人员的信息安全,我们努力采取各种符合业界标准的安全防护措施,包括建立合理的制度规范、实施合宜的安全技术来防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。

我们会使用受信赖的保护机制防止数据遭到恶意攻击,例如在浏览器与“服务”之间交换数据(如订单信息)时采用SSL加密保护技术,同时对网站本身提供https安全浏览方式,以保障数据在传输过程中的安全。

使用加密技术对个人信息加密保存,确保数据的保密性。在个人信息使用时,例如订单查询、展示时,我们会采用多种脱敏技术增强个人信息在使用中的安全性。我们会采用严格的数据访问控制权限控制和多重身份验证机制,确保只有授权人员才可访问个人信息。同时,在数据使用过程中,我们提供数据安全审计,避免数据被违规使用。

对于我们作为中立技术服务提供方的商家所存储于洛阳青年夜校的个人信息,我们也将使用不低于以上的数据安全技术措施进行保护。

2.洛阳青年夜校为保护个人系信息采取的其他安全措施

我们建立了数据分类分级制度、数据安全管理规范来管理及规范个人信息的存储和使用,并通过审计机制对数据安全进行全面检查。我们的系统通过了公安部安全等级保护二级认证。

我们会采取一切合理可行的措施,确保未收集无关的个人信息。

我们定期进行安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。

互联网并非绝对安全的环境,而且电子邮件、即时通讯、社交软件等与其他用户的交流方式无法确定是否完全加密,我们建议你使用此类工具时请使用复杂密码,并注意保护你的个人信息安全。在通过洛阳青年夜校与第三方进行网上产品与/或服务的交易时,你不可避免的要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或者邮政地址等。请你妥善保护自己的个人信息,仅在必要的情形下向他人提供。如你发现自己的个人信息尤其是你的帐号或密码发生泄露,请你立即通过本隐私声明【八、如何联系我们】中约定的联系方式联络我们,以便我们采取相应措施。

3.安全事件处理

(一)我们保护你个人信息的技术与措施

为应对个人信息泄露、损毁和丢失等可能出现的风险,洛阳青年夜校制定了多项制度,明确安全事件、安全漏洞的分类分级标准及相应的处理流程。洛阳青年夜校也为安全事件建立了专门的应急响应团队,按照安全事件处置规范要求,针对不同安全事件启动安全预案,进行止损、分析、定位、制定补救措施并联合相关部门进行溯源和打击。

如果我们的物理、技术或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改或毁坏,导致你的合法权益受损的,我们会及时启动应急预案,采取合理救济措施,以尽可能降低对你个人信息和其他权益的影响。一旦发生个人信息安全事件,我们将按照法律法规的要求,及时向你告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、你可自主防范和降低风险的建议、对你的补救措施等。我们同时将及时将事件相关情况以邮件、信函、电话、推送通知等方式告知你,当难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。

互联网环境并非百分之百安全,我们将尽力确保或担保你发送给我们的任何信息的安全性。如果我们的物理、技术或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改或毁坏,导致你的合法权益受损,我们将承担相应的法律责任。

(二)你个人信息的保存

1.存储地点:你的个人信息将存储于中华人民共和国境内。

2.存储期限:依据《常见类型移动互联网应用程序必要个人信息范围规定》在提前征得您同意的情况下,采取合理可行的措施,仅收集保障App基本功能服务正常运行所必需的个人信息。我们只会在达成本声明所述目的所需的期限内保留你的个人信息,除非法律有强制的存留要求,例如《中华人民共和国电子商务法》要求商品和服务信息、交易信息保存时间自交易完成之日起不少于三年。而我们判断前述期限的标准包括:

1)完成与你相关的交易目的、维护相应交易及业务记录、应对你可能的查询或投诉;

2)保证我们为你提供服务的安全和质量;

3)你是否同意更长的留存期间;

4)是否存在保留期限的其他特别约定。

在你的个人信息超出保留期间后,我们会根据适用法律的要求删除你的个人信息,或使其匿名化处理。

五、你如何管理个人信息

(一)查询、更正和补充你的个人信息

你有权查询、或补充你的信息。你可以通过以下方式自行进行:

进入洛阳青年夜校app,选择“我的-头像”后对个人资料、个人帐号相关信息进行查询、更正或补充。

(二)删除你的个人信息

在以下情形中,你可以向我们提出删除个人信息的请求:

1.如果我们处理个人信息的行为违反法律法规;

2.如果我们收集、使用你的个人信息,却未征得你的明确同意;

3.如果我们处理个人信息的行为严重违反了与你的约定;

4.如果你不再使用我们的产品或服务,或你主动注销了帐号;

5.如果我们停止为你提供产品或服务。

若我们决定响应你的删除请求,我们还将同时尽可能通知从我们处获得你的个人信息的主体,并要求其及时删除(除非法律法规另有规定,或这些主体已独立获得你的授权)。

当你或我们协助你删除相关信息后,因为适用的法律和安全技术,我们可能无法立即从备份系统中删除相应的信息,我们将安全地存储你的个人信息并将其与任何进一步处理隔离,直到备份可以清除或实现匿名。

请你注意,当你成功注销洛阳青年夜校帐号后,我们将对你的个人信息进行删除或匿名化处理。

若你为消费者角色,当你或我们协助你删除相关信息后,非必要信息,我们将在15天内自动删除。

若你为课程、场馆、活动角色,我们将根据与你另行签订的合同处理。

因为适用的法律和安全技术限制,我们无法立即从备份系统中删除相应的信息,我们将安全地存储你的个人信息并限制对其的任何进一步的处理,直到备份可以删除或实现匿名化。

如果我们终止服务或运营,我们会至少提前三十日向你通知,并在终止服务或运营后对你的个人信息进行删除或匿名化处理。

(三)改变你授权同意的范围或撤回你的授权

每个业务功能需要一些基本的个人信息才能得以完成(见本隐私权声明“第一部分”)。

请你理解,每个业务功能需要一些基本的个人信息才能得以完成,当你撤回同意或授权后,我们无法继续为你提供撤回同意或授权所对应的服务,也不再处理你相应的个人信息。但你撤回同意或授权的决定,不会影响此前基于你的授权而开展的个人信息处理。

(四)注销帐号

你可以在我们的产品中直接申请注销帐号:

1.“洛阳青年夜校公众号-联系客服-提交注销申请-完成帐号注销”;

2.“洛阳青年夜校精选App/小程序-我的-设置-账号注销申请-完成帐号注销”;

平台在您提交注销申请后的7个工作日内完成审核,您的账号注销成功后,我们将不会在平台内展示您的相关信息,并依据法律法规的要求去标识化保存所必需的信息至法定期限届满。你注销帐号后,我们将停止为你提供产品与/或服务,并依据你的要求,除法律法规另有规定外,我们将删除你的个人信息。

(五)拒绝自动化决策

在某些业务功能中,我们会依据信息系统、算法等在内的非人工自动决策机制做出决定。如果这些决定显著影响你的合法权益,你有权要求我们做出解释,我们也将在不侵害洛阳青年夜校商业秘密或其他用户权益、社会公共利益的前提下提供申诉方法。

(六)获取你的个人信息副本

你有权获取你的个人信息副本。如你需要获取我们收集的你的个人信息副本,你可通过本隐私声明【七、如何联系我们】中约定的联系方式联络我们。在符合相关法律规定且技术可行的前提下,我们将根据你的要求向您提供你的个人信息副本。

(七)您对其他用户的资料的使用

洛阳青年夜校提供的交易活动中,您无权要求洛阳青年夜校提供其他用户的个人资料,除非符合以下条件:

1.您已向法院起诉其他用户的在洛阳青年夜校活动中的违约行为;

2.洛阳青年夜校被吊销营业执照、解散、清算、宣告破产或者其他有碍于您收回借款本息的情形。

(八)其他

若出于你的合法、正当利益,你需要对已死亡用户相关的个人信息行使前述权利,你需要向我们提供你是其近亲属或执行人的证明。我们将依据个人信息保护相关法律,尽可能支持你的要求。

(九)响应你的请求

为保障安全,你可能需要提供书面请求,或以其他方式证明你的身份。我们将会先要求你验证自己的身份,然后再处理你的请求。

我们将在15天内做出答复。如你不满意,还可以通过洛阳青年夜校客服发起投诉。

对于与你的身份不直接关联的信息、无端重复信息,或者需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者不切实际的请求,我们可能会予以拒绝。

在以下情形中,按照法律法规要求,我们将无法响应你的请求:

1.与我们履行法律法规规定的义务相关的;

2.与国家安全、国防安全有关的;

3.与公共安全、公共卫生、重大公共利益有关的;

4.与犯罪侦查、起诉、审判和执行判决等有关的;

5.有充分证据表明个人信息主体存在主观恶意或滥用权利的;

6.响应你的请求将导致你或其他个人、组织的合法权益受到严重损害的;

7.涉及商业秘密的。

五、未成年人的个人信息保护

本声明所指的儿童是指不满14周岁的个人,如果没有父母或监护人的同意,儿童不得创建自己的用户帐号。如你为未成年人的,建议你请你的父母或监护人仔细阅读本隐私声明与《儿童个人信息保护规则及监护人须知》,并在征得你的父母或监护人同意的前提下使用我们的服务或向我们提供信息。

对于经父母或监护人同意使用我们的产品或服务而收集未成年人个人信息的情况,我们只会在法律法规允许、父母或监护人明确同意或者保护未成年人所必要的情况下使用、共享、转让或披露此信息。如果我们发现自己在未事先获得可证实的父母同意的情况下收集了儿童的个人信息,则会设法尽快删除相关数据。

六、通知和修订

我们的隐私权声明可能变更。

未经你明确同意,我们不会限制你按照本隐私权声明所应享有的权利。我们会在洛阳青年夜校规则中心专门页面上发布对隐私权声明所做的任何变更。

对于重大变更,我们还会提供更为显著的通知(包括我们会通过在洛阳青年夜校规则中心公示的方式进行通知甚至向你提供弹窗提示)。

如你在本声明更新生效后继续使用我们的服务,即代表你已充分阅读、理解并接受更新后的声明并愿意受更新后的声明约束。我们鼓励你在每次使用我们服务时都查阅本声明。你可以在通过洛阳青年夜校小程序、移动应用程序及官网查看本声明。

本声明所指的重大变更包括但不限于:

1.我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式等;

2.我们在控制权等方面发生重大变化。如并购重组等引起的信息控制者变更等;

3.个人信息共享、转让或公开披露的主要对象发生变化;

4.你参与个人信息处理方面的权利及其行使方式发生重大变化;

5.我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化;

6.个人信息安全影响评估报告表明存在高风险。

七、如何联系我们

您可以通过一下方式与我们联系,我们将在15天内答复您的请求;

1.您可以联系洛阳青年夜校客服电话进行反馈:15503791530;

2.我们设立了个人信息保护部门,如对本声明内容有任何疑问、意见或建议,或发现你的个人信息可能被泄露或你觉得需要撤回、更正、删除你的个人信息授权,你可以发邮件到804272385@qq.com与我们联系。

如果你对我们的回复不满意,特别是你认为我们的个人信息处理行为损害了你的合法权益,你还可以通过被告住所地有管辖权的法院提起诉讼来寻求解决方案。

本协议生效日期:

 

', + 'classes_evaluate_number' => '1', + 'user_protocol' => '

洛阳青年夜校用户协议

 

洛阳青年夜校与用户共同确认:

1. 用户点击洛阳青年夜校注册页面的同意注册按钮并完成注册程序、获得洛阳青年夜校账号和手机号码授权登录时,视为用户与洛阳青年夜校已达成《洛阳青年夜校用户协议》,就用户进入洛阳青年夜校消费(即用户通过洛阳青年夜校提供的功能服务进行交易)达成本协议的全部约定。

2. 洛阳青年夜校及用户均已认真阅读本《洛阳青年夜校用户协议》(下称“本协议”)中全部条款及洛阳青年夜校发布的其他全部服务条款和操作规则的内容,对本协议及前述服务条款和规则均以知晓、理解并接受,同意将其作为确定双方权利义务的依据。洛阳青年夜校《法律声明》为本协议的必要组成部分,用户接受本协议的同时即视为接受洛阳青年夜校《法律声明》的全部内容。

一、用户注册

1.1.注册资格

用户承诺:用户具有完全民事权利能力和行为能力或虽不具有完全民事权利能力和行为能力但经其法定代理人同意并由其法定代理人代理注册及应用洛阳青年夜校服务。

1.2.注册目的

用户承诺:用户进行用户注册并非出于违反法律法规或破坏洛阳青年夜校的交易秩序的目的。

1.3.注册流程

1.3.1.用户同意根据洛阳青年夜校用户注册页面的要求提供有效电子邮箱、所在城市等信息,设置洛阳青年夜校账号及密码,用户应确保所提供全部信息的真实性、完整性和准确性。

1.3.2.用户合法、完整并有效提供注册所需信息的,有权获得洛阳青年夜校账号和密码,洛阳青年夜校账号和密码用于用户在洛阳青年夜校进行会员登录。洛阳青年夜校用户必须使用本人手机号码进行注册,一个用户只支持注册一个账号,每个用户具有唯一性(同一手机号、支付账号、移动设备号、身份证件号均视为同一账号)。

1.3.3.用户获得洛阳青年夜校账号及密码时视为用户注册成功,用户同意接收洛阳青年夜校发送的与洛阳青年夜校网站管理、运营相关的电子邮件和或短消息。

1.3.4.用户在洛阳青年夜校平台注册成功后,可享用平台的各种优惠措施,但需遵守平台的各项规则,如使用优惠券下单的账号需先进行实名认证,同意授权平台对其填写的身份信息进行实名校验,校验通过后可使用优惠券下单。

二、用户服务

洛阳青年夜校为用户通过洛阳青年夜校进行网络交易活动提供网络交易平台服务。

2.1.服务内容

2.1.1.用户有权在洛阳青年夜校浏览运动课程、场馆、活动信息,有权通过洛阳青年夜校与商家进行场次/课程预订。

2.1.2.用户有权在洛阳青年夜校浏览课程、活动赛事信息,有权通过洛阳青年夜校报名参加学习、活动赛事。

2.1.3.用户有权在洛阳青年夜校查看其洛阳青年夜校会员账号下的信息,有权应用洛阳青年夜校提供的功能进行操作。

2.1.4.用户有权按照洛阳青年夜校发布的活动规则参与洛阳青年夜校组织的网站活动。

2.1.5.我们将做出合理的努力,让您获得所需的订课、订场服务,但这受制于您请求服务之时所在位置周边是否有可提供服务的课程或充足的课程、场馆、活动数量。

2.1.6.洛阳青年夜校承诺为用户提供的其他服务。

2.2.服务规则

用户承诺遵守下列洛阳青年夜校服务规则:

2.2.1.用户应当遵守法律法规、规章、规范性文件及政策要求的规定,不得在洛阳青年夜校或利用洛阳青年夜校服务从事非法或其他损害洛阳青年夜校或第三方权益的活动,如发送或接收任何违法、违规、违反公序良俗、侵犯他人权益的信息,发送或接收传销材料或存在其他危害的信息或言论,未经洛阳青年夜校授权使用或伪造洛阳青年夜校电子邮件题头信息等。

2.2.2.用户应当遵守法律法规应当妥善使用和保管洛阳青年夜校账号河手机号,对其洛阳青年夜校账号和手机号下进行的行为和发生的事件负责。当用户发现洛阳青年夜校账号被未经其授权的第三方使用或存在其他账号安全问题时应立即有效通知洛阳青年夜校,要求洛阳青年夜校暂停该洛阳青年夜校账号的服务。洛阳青年夜校有权在合理时间内对用户的该等请求采取行动,但对采取行动前用户已经遭受的损失不承担任何责任。用户在未经洛阳青年夜校同意的情况下不得将洛阳青年夜校账号以赠与、借用、租用、转让或其他方式处分给他人。

2.2.3.用户通过洛阳青年夜校与商家进行课程、课程、场馆、活动、活动预订时,应当遵守本协议的全部约定及洛阳青年夜校发布的其他关于课程、场馆、活动交易的服务条款和操作规则的全部规定。

2.2.4.用户在洛阳青年夜校对服务进行评价时应当根据实际情况如实进行评价。

2.2.5.用户应当按照洛阳青年夜校发布的规则参加洛阳青年夜校抽奖等活动,遵守活动秩序。

2.2.6.洛阳青年夜校发布的其他服务条款和操作规则。

三、用户的权利和义务

您须保证向我们提供的信息真实、准确、完整。为实现预订服务功能,我们有权验证您所提供的信息,并有权根据验证结果是否向您提供服务。

3.1.用户有权按照本协议约定接受洛阳青年夜校提供的洛阳青年夜校网络交易平台服务。

3.2.如用户要求获得课程、场馆、活动的发票、其他付款凭证、购货凭证或服务单据,有权且应当在对课程、场馆、活动进行消费时向课程、场馆、活动方提出,发票金额以实际支付的价款为准。

3.3.用户在消费的过程中,如发现课程、场馆、活动服务与订单内容不符或存在质量、服务态度等其他问题的,应与商家采取协商或其他方式予以解决,洛阳青年夜校可向用户提供商家的真实网站登记信息并积极协助用户与商家解决争议。

3.4.用户有权随时注销账号,终止使用洛阳青年夜校服务。

3.5.用户应保证其在注册时和提交订单时所提供的姓名、联系方式、联系地址等全部信息真实、完整、准确,并当上述信息发生变更时及时进行更新提供给洛阳青年夜校的信息。

3.6.用户在洛阳青年夜校进行交易时不得恶意干扰交易的正常进行、破坏洛阳青年夜校的交易秩序。

3.7.用户不得以任何技术手段或其他方式干扰洛阳青年夜校的正常运行或干扰其他用户对洛阳青年夜校服务的使用。

3.8.用户不得以虚构事实等方式恶意诋毁洛阳青年夜校或商家的商誉。

3.9.用户通过洛阳青年夜校进行交易应出于真实消费目的,不得以转售等商业目的进行交易。

3.10.用户不得对课程、场馆、活动服务进行虚假评价或虚假投诉。

3.11.用户使用“洛阳青年夜校”平台预订课程、场馆、活动,在使用课程、场馆、活动运动过程中,应严格遵循课程、场馆、活动方的安全规定。若用户在使用课程、场馆、活动运动过程中,发生任何人身伤害、财产损失等情况,由用户与课程、场馆、活动双方协商解决,洛阳青年夜校”平台对此不承担任何连带责任;若因此造成“洛阳青年夜校”平台声誉受损或其它损害的,平台有权保留追究。

3.12您将遵守所有适用的法律法规规定及公序良俗。

3.13您认可与我们建立协议关系并接受其服务。

如果您违反以上任一约定,我们保留立即终止向您提供服务的权利。平台规则尚无规定的,平台可以遵照平等、公平、诚实信用等基本原则,结合用户行为危害程度,酌情制定临时性规则,在平台规则修订并重新发布前予以适用。

四、洛阳青年夜校的权利和义务

4.1.如用户不具备本协议约定的注册资格,则洛阳青年夜校有权拒绝用户进行注册,对已注册的用户有权注销其洛阳青年夜校会员账号,洛阳青年夜校因此而遭受损失的有权向前述用户或其法定代理人主张赔偿。同时,洛阳青年夜校保留其他任何情况下决定是否接受用户注册的权利。

4.2.洛阳青年夜校发现账户使用者并非账户初始注册人时,有权中止该账户的使用。

4.3.洛阳青年夜校通过技术检测、人工抽检等检测方式合理怀疑用户提供的信息错误、不实、失效或不完整时,有权通知用户更正、更新信息或中止、终止为其提供洛阳青年夜校服务。

4.4.洛阳青年夜校有权在发现洛阳青年夜校上显示的任何信息存在明显错误时,对信息予以更正。

4.5.用户付款成功前,洛阳青年夜校有权接受商家委托对订单内容作出变更,如用户接受变更后的内容则用户可确认订单及付款,如用户不接受变更后内容则有权取消订单。用户付款成功后,如确因情况变化导致商家需对订单内容作出变更的,洛阳青年夜校有权接受商家委托单方对订单内容作出变更,如用户接受变更则按变更后的订单内容进行消费,如用户不接受变更则用户有权取消订单并要求洛阳青年夜校代商家全额退款。

4.6.洛阳青年夜校保留随时修改、中止或终止洛阳青年夜校服务的权利,洛阳青年夜校行使修改或中止服务的权利不需事先告知用户,洛阳青年夜校终止洛阳青年夜校一项或多项服务的,终止自洛阳青年夜校在网站上发布终止公告之日生效。

4.7.洛阳青年夜校应当采取必要的技术手段和管理措施保障洛阳青年夜校的正常运行,并提供必要、可靠的交易环境和交易服务,维护交易秩序。

4.8.如用户连续一年未使用洛阳青年夜校会员账号和密码登录洛阳青年夜校,则洛阳青年夜校有权注销用户的洛阳青年夜校账号。账号注销后,洛阳青年夜校有权将相应的会员名开放给其他用户注册使用。

4.9.洛阳青年夜校有权在本协议履行期间及本协议终止后保留用户的注册信息及用户应用洛阳青年夜校服务期间的全部交易信息,但不得非法使用该等信息。

4.10.洛阳青年夜校有权随时删除洛阳青年夜校网站内各类不符合国家法律法规、规范性文件或洛阳青年夜校网站规定的用户评价等内容信息,洛阳青年夜校行使该等权利不需提前通知用户。

五、特别声明

5.1.用户未通过洛阳青年夜校与商家之间进行的交易不属于洛阳青年夜校的交易,洛阳青年夜校对不属于洛阳青年夜校交易的交易事项不承担任何责任,用户不得因其与商家之间因此类交易发生的任何争议投诉洛阳青年夜校或要求洛阳青年夜校承担任何责任。不属于洛阳青年夜校交易的情况具体包括:用户未在洛阳青年夜校与商家成立订单;用户虽在洛阳青年夜校与商家成立订单,但未通过洛阳青年夜校而直接向商家支付价款。

5.2.不论在何种情况下,洛阳青年夜校对由于信息网络设备维护、信息网络连接故障、电脑、通讯或其他系统的故障、电力故障、罢工、劳动争议、暴乱、起义、骚乱、生产力或生产资料不足、火灾、洪水、风暴、爆炸、战争、政府行为、司法行政机关的命令、其他不可抗力或第三方的不作为而造成的不能服务或延迟服务承担责任。

5.3.为了用户更加方便和安全的使用洛阳青年夜校的服务,洛阳青年夜校将使用cookie,收集用户与洛阳青年夜校站点有关的特征信息,用于标识用户的设备。同时,洛阳青年夜校会积极采取先进的技术手段和有效的管理机制来保障用户的账户安全,保障用户的隐私信息不被任何未授权的使用或者泄露。

六、知识产权

6.1.洛阳青年夜校所包含的全部智力成果包括但不限于数据库、网站设计、文字和图表、软件、照片、录像、音乐、声音及其前述组合,软件编译、相关源代码和软件 (包括小应用程序和脚本) 的知识产权权利均归洛阳青年夜校所有。用户不得为商业目的复制、更改、拷贝、发送或使用前述任何材料或内容。

6.2.洛阳青年夜校名称中包含的所有权利 (包括商誉和商标) 均归洛阳青年夜校所有。

6.3.用户接受本协议即视为用户主动将其在洛阳青年夜校发表的任何形式的信息的著作权,包括但不限于:复制权、发行权、出租权、展览权、表演权、放映权、广播权、信息网络传播权、摄制权、改编权、翻译权、汇编权以及应当由著作权人享有的其他可转让权利无偿独家转让给洛阳青年夜校所有,洛阳青年夜校有权利就任何主体侵权单独提起诉讼并获得全部赔偿。本协议属于《中华人民共和国著作权法》第二十五条规定的书面协议,其效力及于用户在洛阳青年夜校发布的任何受著作权法保护的作品内 容,无论该内容形成于本协议签订前还是本协议签订后。

6.4.用户在使用洛阳青年夜校服务过程中不得非法使用或处分洛阳青年夜校或他人的知识产权权利。用户不得将已发表于洛阳青年夜校的信息以任何形式发布或授权其它网站(及媒体)使用。

七、客户服务

洛阳青年夜校建立专业的客服团队,并建立完善的客户服务制度,从技术、人员和制度上保障用户提问及投诉渠道的畅通,为用户提供及时的疑难解答与投诉反馈。

八、协议的变更和终止

8.1.协议的变更洛阳青年夜校有权随时对本协议内容或洛阳青年夜校发布的其他服务条款及操作规则的内容进行变更,变更时洛阳青年夜校将在洛阳青年夜校网站显著位置内发布公告,变更自公告发布之时生效,如用户继续使用洛阳青年夜校提供的服务即视为用户同意该等内容变更,如用户不同意变更后的内容则用户有权注销洛阳青年夜校账户、停止使用洛阳青年夜校服务。

8.2.协议的终止

8.2.1.洛阳青年夜校有权依据本协议约定注销用户的洛阳青年夜校账号,本协议于账号注销之日终止。

8.2.2.洛阳青年夜校有权依据本协议约定终止全部洛阳青年夜校服务,本协议于洛阳青年夜校全部服务终止之日终止。

8.2.3.本协议终止后,用户无权要求洛阳青年夜校继续向其提供任何服务或履行任何其他义务,包括但不限于要求洛阳青年夜校为用户保留或向用户披露其原洛阳青年夜校账号中的任何信息,向用户或第三方转发任何其未曾阅读或发送过的信息等。

8.2.4.本协议的终止不影响守约方向违约方追究违约责任。

九、违约责任

基于有效维护平台交易秩序,保护用户合法权益的目的,平台有权根据运营实际情况,通过本协议设定、调整违规处置措施。

用户涉嫌违法犯罪或可能存在其他危害人身安全的行为,处于调查、侦查、审查起诉或审判阶段的,平台可暂停该用户使用平台全部或部分功能,待相关方出具最终意见后,平台根据其行为性质采取相应措施。

违约处置原则

(一) 同一用户在同一订单中的单个行为,同时违反多条平台规则的,应承担数个违规责任中最高的违规责任。

(二) 同一用户在同一订单中存在多个违规行为的,每个行为分别确定违规责任,多个违规责任相加,合并执行。

(三) 同一账号特定时段内高频访问平台,触发平台风控规则,将因其异常行为轻重判定,实施访问时图形码验证、暂停服务、终止服务或其他限制措施。

(四) 同一账号1周内存在5次以上“提交订单成功,取消不支付”行为的(含5次),平台将暂停其课程、场馆、活动预订服务1周,暂停服务自其第5次取消起执行。

9.1.洛阳青年夜校或用户违反本协议的约定即构成违约,违约方应当向守约方承担违约责任。我们有权根据您违约的严重程度对您采取暂停服务、终止服务或其他限制措施。如您违反平台用户规则,我们有权依据平台规则追究您的违规责任。

9.2.如用户违反本协议约定,以转售等商业目的进行交易,则洛阳青年夜校有权代商家取消相关交易,并有权注销其洛阳青年夜校 号,终止为其提供洛阳青年夜校服务,如洛阳青年夜校因此而遭受损失的,有权要求用户赔偿损失。

9.3.如因用户提供的信息不真实、不完整或不准确给洛阳青年夜校或商家造成损失的,洛阳青年夜校有权要求用户对洛阳青年夜校或对商家进行损失的赔偿。

9.4.如因用户违反法律法规规定或本协议约定,在洛阳青年夜校或利用洛阳青年夜校服务从事非法活动的,洛阳青年夜校有权立即终止继续对其提供洛阳青年夜校服务,注销其账号,并要求其赔偿由此给洛阳青年夜校造成的损失。

9.5.如用户以技术手段干扰洛阳青年夜校的运行或干扰其他用户对洛阳青年夜校使用的,洛阳青年夜校有权立即注销其洛阳青年夜校账号,并有权要求其赔偿由此给洛阳青年夜校造成的损失。

9.6.如用户以虚构事实等方式恶意诋毁洛阳青年夜校或商家的商誉,洛阳青年夜校有权要求用户向洛阳青年夜校或商家公开道歉,赔偿其给洛阳青年夜校或商家造成的损失,并有权终止对其提供洛阳青年夜校服务。

十、争议解决

用户与洛阳青年夜校因本协议的履行发生争议的应通过友好协商解决,协商解决不成的,任何一方均可向人民法院提起诉讼。

十一、协议生效

本协议于用户点击洛阳青年夜校注册页面的同意注册并完成注册程序、获得洛阳青年夜校账号和密码时生效,对洛阳青年夜校和用户均具有约束力。

 

', + 'entry_agreement_file' => '/uploads/20241212/a5ff2f0b18aa1c9d548f9c2dd3edad1d.docx', + 'privacy_file' => '/uploads/20241212/1f2e58762a9b9f9923be456d42ca9127.docx', + 'user_protocol_file' => '/uploads/20241212/cddfe46df4a345f4664d1dc3fa486aa9.docx', + 'classes_timeout_time' => '86400', + 'classes_number_only_one' => '1', + 'classes_edit_shop_limit' => '1', + 'free_time_activity_check' => '0', + 'all_time_activity_check' => '1', ); diff --git a/application/extra/upload.php b/application/extra/upload.php index e4cdab1..3d4da3b 100644 --- a/application/extra/upload.php +++ b/application/extra/upload.php @@ -9,7 +9,7 @@ return [ /** * CDN地址 */ - 'cdnurl' => '', + 'cdnurl' => 'https://testy1.hschool.com.cn', /** * 文件保存格式 */ diff --git a/application/manystore/controller/school/classes/activity/Activity.php b/application/manystore/controller/school/classes/activity/Activity.php index 872fc40..6705085 100644 --- a/application/manystore/controller/school/classes/activity/Activity.php +++ b/application/manystore/controller/school/classes/activity/Activity.php @@ -84,7 +84,7 @@ class Activity extends ManystoreBase if ($this->request->request('keyField')) { return $this->selectpage(); } - list($where, $sort, $order, $offset, $limit, $page, $alias, $bind, $excludearray) = $this->buildparams(null, null, ["has_expire"]); + list($where, $sort, $order, $offset, $limit, $page, $alias, $bind, $excludearray) = $this->buildparams(null, null, ["has_expire","has_sign_expire"]); if (isset($excludearray['has_expire']['value']) && $excludearray['has_expire']['value']) { $has_expire = $excludearray['has_expire']['value']; @@ -107,10 +107,34 @@ class Activity extends ManystoreBase $expireWhere = [[]]; } + if (isset($excludearray['has_sign_expire']['value']) && $excludearray['has_sign_expire']['value']) { + $has_expire = $excludearray['has_sign_expire']['value']; + $as = (new \app\common\model\school\classes\activity\Activity)->getWithAlisaName(); + switch ($has_expire) { + case '1': //查过期 + $expireSignWhere = [ + $as . '.sign_end_time', '<=', time(), + ]; + break; + case '2': //查未过期 + $expireSignWhere = [ + $as . '.sign_end_time', '>', time(), + ]; + break; + default: + } + + } else { + $expireSignWhere = [[]]; + } + + + $list = $this->model ->with(['manystore','manystoreshop']) ->where($where) ->where(...$expireWhere) + ->where(...$expireSignWhere) ->order($sort, $order) ->paginate($limit); @@ -128,7 +152,7 @@ class Activity extends ManystoreBase } protected function update_classes($classes_activity_id){ - + if($classes_activity_id) \app\common\model\school\classes\activity\Activity::update_classes($classes_activity_id); } diff --git a/application/manystore/controller/school/classes/activity/order/OrderItem.php b/application/manystore/controller/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..40d28ac --- /dev/null +++ b/application/manystore/controller/school/classes/activity/order/OrderItem.php @@ -0,0 +1,80 @@ +model = new \app\manystore\model\school\classes\activity\order\OrderItem; + $this->view->assign("statusList", $this->model->getStatusList()); + $this->view->assign("sexList", $this->model->getSexList()); + $this->view->assign("feelList", $this->model->getFeelList()); + } + + public function import() + { + parent::import(); + } + + /** + * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 + * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 + * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 + */ + + + /** + * 查看 + */ + public function index() + { + //当前是否为关联查询 + $this->relationSearch = true; + //设置过滤方法 + $this->request->filter(['strip_tags', 'trim']); + if ($this->request->isAjax()) { + //如果发送的来源是Selectpage,则转发到Selectpage + if ($this->request->request('keyField')) { + return $this->selectpage(); + } + list($where, $sort, $order, $offset, $limit) = $this->buildparams(); + + $list = $this->model + ->with(['schoolclassesactivityorder','manystore','manystoreshop','schoolclassesactivity','schoolclassesactivityitem']) + ->where($where) + ->order($sort, $order) + ->paginate($limit); + + foreach ($list as $row) { + + $row->getRelation('schoolclassesactivityorder')->visible(['order_no','pay_no']); + $row->getRelation('manystore')->visible(['nickname']); + $row->getRelation('manystoreshop')->visible(['name','logo']); + $row->getRelation('schoolclassesactivity')->visible(['title','headimage']); + $row->getRelation('schoolclassesactivityitem')->visible(['name','price']); + } + + $result = array("total" => $list->total(), "rows" => $list->items()); + + return json($result); + } + return $this->view->fetch(); + } + +} diff --git a/application/manystore/lang/zh-cn/school/classes/activity/activity.php b/application/manystore/lang/zh-cn/school/classes/activity/activity.php index b5e153f..a1ac964 100644 --- a/application/manystore/lang/zh-cn/school/classes/activity/activity.php +++ b/application/manystore/lang/zh-cn/school/classes/activity/activity.php @@ -65,8 +65,9 @@ return [ 'Limit_num' => '本项目限定人数', 'Age' => '年龄限制描述', 'Item_json' => '活动项目', - 'Has_expire' => '是否过期', + 'Has_expire' => '活动是否过期', 'Has_expire 1' => '往期活动', 'Has_expire 2' => '进行中活动', 'OK' => '确认提交审核', + 'Has_sign_expire' => '报名是否过期', ]; diff --git a/application/manystore/lang/zh-cn/school/classes/activity/order/order_item.php b/application/manystore/lang/zh-cn/school/classes/activity/order/order_item.php new file mode 100644 index 0000000..d0c0d9e --- /dev/null +++ b/application/manystore/lang/zh-cn/school/classes/activity/order/order_item.php @@ -0,0 +1,38 @@ + '课程活动订单id', + 'Manystore_id' => '机构账号id', + 'Shop_id' => '机构店铺id', + 'Classes_activity_id' => '课程活动id', + 'Classes_activity_item_id' => '课程活动项id', + 'Name' => '活动项名称', + 'Price' => '项目价格(0为免费)', + 'Limit_num' => '本项目限定人数', + 'Age' => '年龄限制描述', + 'Status' => '状态', + 'Status 1' => '上架', + 'Status 2' => '下架', + 'Sex' => '性别限制', + 'Sex 1' => '男', + 'Sex 2' => '女', + 'Sex 3' => '男女不限', + 'Weigh' => '权重', + 'Sign_num' => '已报名人数', + 'Verification_num' => '已核销人数', + 'Createtime' => '创建时间', + 'Updatetime' => '修改时间', + 'Deletetime' => '删除时间', + 'Feel' => '是否免费', + 'Feel 0' => '否', + 'Feel 1' => '是', + 'Schoolclassesactivityorder.order_no' => '订单号', + 'Schoolclassesactivityorder.pay_no' => '微信支付单号', + 'Manystore.nickname' => '昵称', + 'Manystoreshop.name' => '店铺名称', + 'Manystoreshop.logo' => '品牌LOGO', + 'Schoolclassesactivity.title' => '标题', + 'Schoolclassesactivity.headimage' => '头图', + 'Schoolclassesactivityitem.name' => '活动项名称', + 'Schoolclassesactivityitem.price' => '项目价格(0为免费)' +]; diff --git a/application/manystore/library/Auth.php b/application/manystore/library/Auth.php index e4a97a5..6c40b36 100644 --- a/application/manystore/library/Auth.php +++ b/application/manystore/library/Auth.php @@ -475,6 +475,9 @@ class Auth extends ManystoreAuth } $v['icon'] = $v['icon'] . ' fa-fw'; $v['url'] = '/' . $module . '/' . $v['name']; + + + $v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : ''; $v['py'] = $pinyin->abbr($v['title'], ''); $v['pinyin'] = $pinyin->permalink($v['title'], ''); diff --git a/application/manystore/library/ManystoreAuth.php b/application/manystore/library/ManystoreAuth.php index f0d2451..0b4bb8b 100644 --- a/application/manystore/library/ManystoreAuth.php +++ b/application/manystore/library/ManystoreAuth.php @@ -117,7 +117,7 @@ class ManystoreAuth parse_str($query, $param); //解析规则中的param $intersect = array_intersect_assoc($REQUEST, $param); $rule = preg_replace('/\?.*$/U', '', $rule); - if (in_array($rule, $name) && $intersect == $param) { + if (in_array($rule, $name)) { //如果节点相符且url参数满足 $list[] = $rule; } diff --git a/application/manystore/model/school/classes/ClassesLib.php b/application/manystore/model/school/classes/ClassesLib.php index 4747938..69d14f8 100644 --- a/application/manystore/model/school/classes/ClassesLib.php +++ b/application/manystore/model/school/classes/ClassesLib.php @@ -82,7 +82,8 @@ class ClassesLib extends Model { self::afterInsert(function ($row) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); }); } diff --git a/application/manystore/model/school/classes/activity/Activity.php b/application/manystore/model/school/classes/activity/Activity.php index ace6792..c7ffc74 100644 --- a/application/manystore/model/school/classes/activity/Activity.php +++ b/application/manystore/model/school/classes/activity/Activity.php @@ -40,8 +40,25 @@ class Activity extends Model 'expirestatus_text', 'add_type_text', 'has_expire', + 'has_sign_expire', ]; + + public function getHasSignExpireAttr($value, $data) + { + $sign_start_time = (isset($data['sign_start_time']) ? $data['sign_start_time'] : ''); + $sign_end_time = (isset($data['sign_end_time']) ? $data['sign_end_time'] : ''); + + if(!$sign_end_time) return '2'; + + if( $sign_end_time < time()) { + return '1'; + }else{ + return '2'; + } + + } + public function getHasExpireList() { return ['1' => __('Has_expire 1'), '2' => __('Has_expire 2')]; @@ -66,7 +83,8 @@ class Activity extends Model { self::afterInsert(function ($row) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); }); } diff --git a/application/manystore/model/school/classes/activity/ActivityAuth.php b/application/manystore/model/school/classes/activity/ActivityAuth.php index fa19ccd..8321d00 100644 --- a/application/manystore/model/school/classes/activity/ActivityAuth.php +++ b/application/manystore/model/school/classes/activity/ActivityAuth.php @@ -68,7 +68,8 @@ class ActivityAuth extends Model { self::afterInsert(function ($row) { $pk = $row->getPk(); - $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); +// $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => 0]); }); } diff --git a/application/manystore/model/school/classes/activity/order/OrderItem.php b/application/manystore/model/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..b509125 --- /dev/null +++ b/application/manystore/model/school/classes/activity/order/OrderItem.php @@ -0,0 +1,117 @@ +getPk(); + $row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]); + }); + } + + + public function getStatusList() + { + return ['1' => __('Status 1'), '2' => __('Status 2')]; + } + + public function getSexList() + { + return ['1' => __('Sex 1'), '2' => __('Sex 2'), '3' => __('Sex 3')]; + } + + public function getFeelList() + { + return ['0' => __('Feel 0'), '1' => __('Feel 1')]; + } + + + public function getStatusTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['status']) ? $data['status'] : ''); + $list = $this->getStatusList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + public function getSexTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['sex']) ? $data['sex'] : ''); + $list = $this->getSexList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + public function getFeelTextAttr($value, $data) + { + $value = $value ? $value : (isset($data['feel']) ? $data['feel'] : ''); + $list = $this->getFeelList(); + return isset($list[$value]) ? $list[$value] : ''; + } + + + + + public function schoolclassesactivityorder() + { + return $this->belongsTo(Order::class, 'classes_activity_order_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function manystore() + { + return $this->belongsTo(Manystore::class, 'manystore_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function manystoreshop() + { + return $this->belongsTo(Shop::class, 'shop_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function schoolclassesactivity() + { + return $this->belongsTo(Activity::class, 'classes_activity_id', 'id', [], 'LEFT')->setEagerlyType(0); + } + + + public function schoolclassesactivityitem() + { + return $this->belongsTo(ActivityItem::class, 'classes_activity_item_id', 'id', [], 'LEFT')->setEagerlyType(0); + } +} diff --git a/application/manystore/validate/school/classes/activity/order/OrderItem.php b/application/manystore/validate/school/classes/activity/order/OrderItem.php new file mode 100644 index 0000000..4b49379 --- /dev/null +++ b/application/manystore/validate/school/classes/activity/order/OrderItem.php @@ -0,0 +1,27 @@ + [], + 'edit' => [], + ]; + +} diff --git a/application/manystore/view/general/profile/index.html b/application/manystore/view/general/profile/index.html index 5eec66b..db0c695 100644 --- a/application/manystore/view/general/profile/index.html +++ b/application/manystore/view/general/profile/index.html @@ -206,11 +206,13 @@ value="{$shop_info.images}">
- diff --git a/application/manystore/view/school/classes/activity/activity/add.html b/application/manystore/view/school/classes/activity/activity/add.html index 0fffa6f..eecc0fd 100644 --- a/application/manystore/view/school/classes/activity/activity/add.html +++ b/application/manystore/view/school/classes/activity/activity/add.html @@ -28,8 +28,8 @@
- - + +
@@ -229,42 +229,42 @@
-
- -
+ + + - + + + + + -
-
-
- -
+ + + + + - + + + + + -
-
-
- -
+ + + + + - + + + + + -
-
+ +
diff --git a/application/manystore/view/school/classes/activity/activity/edit.html b/application/manystore/view/school/classes/activity/activity/edit.html index 15860a3..4eba5ee 100644 --- a/application/manystore/view/school/classes/activity/activity/edit.html +++ b/application/manystore/view/school/classes/activity/activity/edit.html @@ -27,8 +27,8 @@
- - + +
@@ -218,42 +218,42 @@
-
- -
+ + + - + + + + + -
-
-
- -
+ + + + + - + + + + + -
-
-
- -
+ + + + + - + + + + + -
-
+ +
diff --git a/application/manystore/view/school/classes/activity/activity_auth/add.html b/application/manystore/view/school/classes/activity/activity_auth/add.html index 0fffa6f..254afb8 100644 --- a/application/manystore/view/school/classes/activity/activity_auth/add.html +++ b/application/manystore/view/school/classes/activity/activity_auth/add.html @@ -28,8 +28,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/activity/activity_auth/edit.html b/application/manystore/view/school/classes/activity/activity_auth/edit.html index 8b2df0d..a72d6de 100644 --- a/application/manystore/view/school/classes/activity/activity_auth/edit.html +++ b/application/manystore/view/school/classes/activity/activity_auth/edit.html @@ -46,8 +46,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/activity/order/order_item/add.html b/application/manystore/view/school/classes/activity/order/order_item/add.html new file mode 100644 index 0000000..52ce440 --- /dev/null +++ b/application/manystore/view/school/classes/activity/order/order_item/add.html @@ -0,0 +1,112 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +
+
+ +
diff --git a/application/manystore/view/school/classes/activity/order/order_item/edit.html b/application/manystore/view/school/classes/activity/order/order_item/edit.html new file mode 100644 index 0000000..6ace745 --- /dev/null +++ b/application/manystore/view/school/classes/activity/order/order_item/edit.html @@ -0,0 +1,112 @@ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ {foreach name="statusList" item="vo"} + + {/foreach} +
+ +
+
+
+ +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + + +
+
+ +
diff --git a/application/manystore/view/school/classes/activity/order/order_item/index.html b/application/manystore/view/school/classes/activity/order/order_item/index.html new file mode 100644 index 0000000..52ba31b --- /dev/null +++ b/application/manystore/view/school/classes/activity/order/order_item/index.html @@ -0,0 +1,44 @@ +
+ +
+ {:build_heading(null,FALSE)} + +
+ + + +
diff --git a/application/manystore/view/school/classes/activity/order/order_item/recyclebin.html b/application/manystore/view/school/classes/activity/order/order_item/recyclebin.html new file mode 100644 index 0000000..e985ac3 --- /dev/null +++ b/application/manystore/view/school/classes/activity/order/order_item/recyclebin.html @@ -0,0 +1,25 @@ +
+ {:build_heading()} + +
+
+
+ +
+ +
+
+
diff --git a/application/manystore/view/school/classes/classes_lib/addnew.html b/application/manystore/view/school/classes/classes_lib/addnew.html index ab47894..d98cce7 100644 --- a/application/manystore/view/school/classes/classes_lib/addnew.html +++ b/application/manystore/view/school/classes/classes_lib/addnew.html @@ -114,8 +114,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/classes_lib/edit.html b/application/manystore/view/school/classes/classes_lib/edit.html index 619b313..d655881 100644 --- a/application/manystore/view/school/classes/classes_lib/edit.html +++ b/application/manystore/view/school/classes/classes_lib/edit.html @@ -149,8 +149,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/order/service_order/admin_confirmation.html b/application/manystore/view/school/classes/order/service_order/admin_confirmation.html index 6a5327f..e5989aa 100644 --- a/application/manystore/view/school/classes/order/service_order/admin_confirmation.html +++ b/application/manystore/view/school/classes/order/service_order/admin_confirmation.html @@ -40,8 +40,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/order/service_order/shop_confirmation.html b/application/manystore/view/school/classes/order/service_order/shop_confirmation.html index a4ae086..4653d65 100644 --- a/application/manystore/view/school/classes/order/service_order/shop_confirmation.html +++ b/application/manystore/view/school/classes/order/service_order/shop_confirmation.html @@ -40,8 +40,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/order/service_order/user_confirmation.html b/application/manystore/view/school/classes/order/service_order/user_confirmation.html index e3a7b10..54f465b 100644 --- a/application/manystore/view/school/classes/order/service_order/user_confirmation.html +++ b/application/manystore/view/school/classes/order/service_order/user_confirmation.html @@ -40,8 +40,8 @@
- - + +
diff --git a/application/manystore/view/school/classes/teacher/add.html b/application/manystore/view/school/classes/teacher/add.html index 7e70e23..8907159 100644 --- a/application/manystore/view/school/classes/teacher/add.html +++ b/application/manystore/view/school/classes/teacher/add.html @@ -26,14 +26,14 @@
- +
- +
diff --git a/application/manystore/view/school/classes/teacher/edit.html b/application/manystore/view/school/classes/teacher/edit.html index 2af5948..52077f2 100644 --- a/application/manystore/view/school/classes/teacher/edit.html +++ b/application/manystore/view/school/classes/teacher/edit.html @@ -23,14 +23,14 @@
- +
- +
diff --git a/public/assets/js/backend/school/classes/activity/activity.js b/public/assets/js/backend/school/classes/activity/activity.js index 92d1723..91682c3 100644 --- a/public/assets/js/backend/school/classes/activity/activity.js +++ b/public/assets/js/backend/school/classes/activity/activity.js @@ -36,6 +36,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'status', title: __('Status'), searchList: {"1":__('Status 1'),"2":__('Status 2'),"3":__('Status 3')}, formatter: Table.api.formatter.status}, {field: 'has_expire', title: __('Has_expire'), searchList: {"1":__('Has_expire 1'),"2":__('Has_expire 2')}, formatter: Table.api.formatter.normal}, + {field: 'has_sign_expire', title: __('Has_sign_expire'), searchList: {"1":__('Has_expire 1'),"2":__('Has_expire 2')}, formatter: Table.api.formatter.normal}, + {field: 'feel', title: __('是否免费'), searchList: {"0":__('付费活动'),"1":__('免费活动')}, formatter: Table.api.formatter.normal}, @@ -65,7 +67,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'sale', title: __('Sale')}, {field: 'stock', title: __('Stock')}, {field: 'views', title: __('Views')}, - {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, + // {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, {field: 'add_type', title: __('Add_type'), searchList: {"1":__('Add_type 1'),"2":__('Add_type 2')}, formatter: Table.api.formatter.normal}, {field: 'add_id', title: __('Add_id')}, {field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, @@ -355,7 +357,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin } var activity_auth_url = function (row,dom) { - return 'school/classes/activity/activity_auth/index?classes_activity_id='+row.id; + return 'school/classes/activity/activity_auth/index?classes_activity_id='+row.id ; } var activity_url = function (row,dom) { return 'school/classes/activity/activity_auth/edit/ids/'+row.classes_activity_auth_id; diff --git a/public/assets/js/backend/school/classes/activity/activity_auth.js b/public/assets/js/backend/school/classes/activity/activity_auth.js index b661f71..6e66b1d 100644 --- a/public/assets/js/backend/school/classes/activity/activity_auth.js +++ b/public/assets/js/backend/school/classes/activity/activity_auth.js @@ -67,7 +67,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'sale', title: __('Sale')}, {field: 'stock', title: __('Stock')}, {field: 'views', title: __('Views')}, - {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, + // {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, {field: 'add_type', title: __('Add_type'), searchList: {"1":__('Add_type 1'),"2":__('Add_type 2')}, formatter: Table.api.formatter.normal}, {field: 'add_id', title: __('Add_id')}, {field: 'admin_id', title: __('Admin_id')}, diff --git a/public/assets/js/backend/school/classes/activity/order/order_detail.js b/public/assets/js/backend/school/classes/activity/order/order_detail.js index 4b09b9f..41ea0cf 100644 --- a/public/assets/js/backend/school/classes/activity/order/order_detail.js +++ b/public/assets/js/backend/school/classes/activity/order/order_detail.js @@ -61,7 +61,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'sale', title: __('Sale')}, {field: 'stock', title: __('Stock')}, {field: 'views', title: __('Views')}, - {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, + // {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, {field: 'add_type', title: __('Add_type'), searchList: {"1":__('Add_type 1'),"2":__('Add_type 2')}, formatter: Table.api.formatter.normal}, {field: 'add_id', title: __('Add_id')}, {field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, diff --git a/public/assets/js/backend/school/classes/activity/order/order_item.js b/public/assets/js/backend/school/classes/activity/order/order_item.js new file mode 100644 index 0000000..e12031c --- /dev/null +++ b/public/assets/js/backend/school/classes/activity/order/order_item.js @@ -0,0 +1,139 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'school/classes/activity/order/order_item/index' + location.search, + add_url: 'school/classes/activity/order/order_item/add', + edit_url: 'school/classes/activity/order/order_item/edit', + del_url: 'school/classes/activity/order/order_item/del', + multi_url: 'school/classes/activity/order/order_item/multi', + import_url: 'school/classes/activity/order/order_item/import', + table: 'school_classes_activity_order_item', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'weigh', + fixedColumns: true, + fixedRightNumber: 1, + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'classes_activity_order_id', title: __('Classes_activity_order_id')}, + {field: 'manystore_id', title: __('Manystore_id')}, + {field: 'shop_id', title: __('Shop_id')}, + {field: 'classes_activity_id', title: __('Classes_activity_id')}, + {field: 'classes_activity_item_id', title: __('Classes_activity_item_id')}, + {field: 'name', title: __('Name'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'price', title: __('Price'), operate:'BETWEEN'}, + {field: 'limit_num', title: __('Limit_num')}, + {field: 'age', title: __('Age'), operate: 'LIKE'}, + {field: 'status', title: __('Status'), searchList: {"1":__('Status 1'),"2":__('Status 2')}, formatter: Table.api.formatter.status}, + {field: 'sex', title: __('Sex'), searchList: {"1":__('Sex 1'),"2":__('Sex 2'),"3":__('Sex 3')}, formatter: Table.api.formatter.normal}, + {field: 'weigh', title: __('Weigh'), operate: false}, + {field: 'sign_num', title: __('Sign_num')}, + {field: 'verification_num', title: __('Verification_num')}, + {field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, + {field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime}, + {field: 'feel', title: __('Feel'), searchList: {"0":__('Feel 0'),"1":__('Feel 1')}, formatter: Table.api.formatter.normal}, + {field: 'activityorder.order_no', title: __('Order.order_no'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'activityorder.pay_no', title: __('Order.pay_no'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'manystore.nickname', title: __('Manystore.nickname'), operate: 'LIKE'}, + {field: 'shop.name', title: __('Shop.name'), operate: 'LIKE'}, + {field: 'shop.logo', title: __('Shop.logo'), operate: 'LIKE'}, + {field: 'activity.title', title: __('Activity.title'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'activity.headimage', title: __('Activity.headimage'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image}, + {field: 'item.name', title: __('Item.name'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content}, + {field: 'item.price', title: __('Item.price'), operate:'BETWEEN'}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + recyclebin: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + 'dragsort_url': '' + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: 'school/classes/activity/order/order_item/recyclebin' + location.search, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'name', title: __('Name'), align: 'left'}, + { + field: 'deletetime', + title: __('Deletetime'), + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'operate', + width: '140px', + title: __('Operate'), + table: table, + events: Table.api.events.operate, + buttons: [ + { + name: 'Restore', + text: __('Restore'), + classname: 'btn btn-xs btn-info btn-ajax btn-restoreit', + icon: 'fa fa-rotate-left', + url: 'school/classes/activity/order/order_item/restore', + refresh: true + }, + { + name: 'Destroy', + text: __('Destroy'), + classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit', + icon: 'fa fa-times', + url: 'school/classes/activity/order/order_item/destroy', + refresh: true + } + ], + 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/manystore/school/classes/activity/activity.js b/public/assets/js/manystore/school/classes/activity/activity.js index f696b7b..964680a 100644 --- a/public/assets/js/manystore/school/classes/activity/activity.js +++ b/public/assets/js/manystore/school/classes/activity/activity.js @@ -38,6 +38,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'has_expire', title: __('Has_expire'), searchList: {"1":__('Has_expire 1'),"2":__('Has_expire 2')}, formatter: Table.api.formatter.normal}, + {field: 'has_sign_expire', title: __('Has_sign_expire'), searchList: {"1":__('Has_expire 1'),"2":__('Has_expire 2')}, formatter: Table.api.formatter.normal}, {field: 'feel', title: __('是否免费'), searchList: {"0":__('付费活动'),"1":__('免费活动')}, formatter: Table.api.formatter.normal}, @@ -68,7 +69,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'sale', title: __('Sale')}, {field: 'stock', title: __('Stock')}, {field: 'views', title: __('Views')}, - {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, + // {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, {field: 'add_type', title: __('Add_type'), searchList: {"1":__('Add_type 1'),"2":__('Add_type 2')}, formatter: Table.api.formatter.normal}, {field: 'add_id', title: __('Add_id')}, {field: 'createtime', title: __('Createtime')}, diff --git a/public/assets/js/manystore/school/classes/activity/activity_auth.js b/public/assets/js/manystore/school/classes/activity/activity_auth.js index 93d8b32..c14840e 100644 --- a/public/assets/js/manystore/school/classes/activity/activity_auth.js +++ b/public/assets/js/manystore/school/classes/activity/activity_auth.js @@ -66,7 +66,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'sale', title: __('Sale')}, {field: 'stock', title: __('Stock')}, {field: 'views', title: __('Views')}, - {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, + // {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, {field: 'add_type', title: __('Add_type'), searchList: {"1":__('Add_type 1'),"2":__('Add_type 2')}, formatter: Table.api.formatter.normal}, {field: 'add_id', title: __('Add_id')}, {field: 'admin_id', title: __('Admin_id')}, diff --git a/public/assets/js/manystore/school/classes/activity/order/order_detail.js b/public/assets/js/manystore/school/classes/activity/order/order_detail.js index d77d94a..5cbda23 100644 --- a/public/assets/js/manystore/school/classes/activity/order/order_detail.js +++ b/public/assets/js/manystore/school/classes/activity/order/order_detail.js @@ -59,7 +59,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'sale', title: __('Sale')}, {field: 'stock', title: __('Stock')}, {field: 'views', title: __('Views')}, - {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, + // {field: 'expirestatus', title: __('Expirestatus'), searchList: {"1":__('Expirestatus 1'),"2":__('Expirestatus 2')}, formatter: Table.api.formatter.status}, {field: 'add_type', title: __('Add_type'), searchList: {"1":__('Add_type 1'),"2":__('Add_type 2')}, formatter: Table.api.formatter.normal}, {field: 'add_id', title: __('Add_id')}, {field: 'createtime', title: __('Createtime')}, diff --git a/public/assets/js/manystore/school/classes/activity/order/order_item.js b/public/assets/js/manystore/school/classes/activity/order/order_item.js new file mode 100644 index 0000000..4473fe8 --- /dev/null +++ b/public/assets/js/manystore/school/classes/activity/order/order_item.js @@ -0,0 +1,136 @@ +define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) { + + var Controller = { + index: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + index_url: 'school/classes/activity/order/order_item/index' + location.search, + add_url: 'school/classes/activity/order/order_item/add', + edit_url: 'school/classes/activity/order/order_item/edit', + del_url: 'school/classes/activity/order/order_item/del', + multi_url: 'school/classes/activity/order/order_item/multi', + import_url: 'school/classes/activity/order/order_item/import', + table: 'school_classes_activity_order_item', + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: $.fn.bootstrapTable.defaults.extend.index_url, + pk: 'id', + sortName: 'weigh', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'classes_activity_order_id', title: __('Classes_activity_order_id')}, + {field: 'manystore_id', title: __('Manystore_id')}, + {field: 'shop_id', title: __('Shop_id')}, + {field: 'classes_activity_id', title: __('Classes_activity_id')}, + {field: 'classes_activity_item_id', title: __('Classes_activity_item_id')}, + {field: 'name', title: __('Name'), operate: 'LIKE'}, + {field: 'price', title: __('Price'), operate:'BETWEEN'}, + {field: 'limit_num', title: __('Limit_num')}, + {field: 'age', title: __('Age'), operate: 'LIKE'}, + {field: 'status', title: __('Status'), searchList: {"1":__('Status 1'),"2":__('Status 2')}, formatter: Table.api.formatter.status}, + {field: 'sex', title: __('Sex'), searchList: {"1":__('Sex 1'),"2":__('Sex 2'),"3":__('Sex 3')}, formatter: Table.api.formatter.normal}, + {field: 'weigh', title: __('Weigh'), operate: false}, + {field: 'sign_num', title: __('Sign_num')}, + {field: 'verification_num', title: __('Verification_num')}, + {field: 'createtime', title: __('Createtime')}, + {field: 'updatetime', title: __('Updatetime')}, + {field: 'feel', title: __('Feel'), searchList: {"0":__('Feel 0'),"1":__('Feel 1')}, formatter: Table.api.formatter.normal}, + {field: 'schoolclassesactivityorder.order_no', title: __('Schoolclassesactivityorder.order_no'), operate: 'LIKE'}, + {field: 'schoolclassesactivityorder.pay_no', title: __('Schoolclassesactivityorder.pay_no'), operate: 'LIKE'}, + {field: 'manystore.nickname', title: __('Manystore.nickname'), operate: 'LIKE'}, + {field: 'manystoreshop.name', title: __('Manystoreshop.name'), operate: 'LIKE'}, + {field: 'manystoreshop.logo', title: __('Manystoreshop.logo'), operate: 'LIKE'}, + {field: 'schoolclassesactivity.title', title: __('Schoolclassesactivity.title'), operate: 'LIKE'}, + {field: 'schoolclassesactivity.headimage', title: __('Schoolclassesactivity.headimage'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image}, + {field: 'schoolclassesactivityitem.name', title: __('Schoolclassesactivityitem.name'), operate: 'LIKE'}, + {field: 'schoolclassesactivityitem.price', title: __('Schoolclassesactivityitem.price'), operate:'BETWEEN'}, + {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate} + ] + ] + }); + + // 为表格绑定事件 + Table.api.bindevent(table); + }, + recyclebin: function () { + // 初始化表格参数配置 + Table.api.init({ + extend: { + 'dragsort_url': '' + } + }); + + var table = $("#table"); + + // 初始化表格 + table.bootstrapTable({ + url: 'school/classes/activity/order/order_item/recyclebin' + location.search, + pk: 'id', + sortName: 'id', + columns: [ + [ + {checkbox: true}, + {field: 'id', title: __('Id')}, + {field: 'name', title: __('Name'), align: 'left'}, + { + field: 'deletetime', + title: __('Deletetime'), + operate: 'RANGE', + addclass: 'datetimerange', + formatter: Table.api.formatter.datetime + }, + { + field: 'operate', + width: '130px', + title: __('Operate'), + table: table, + events: Table.api.events.operate, + buttons: [ + { + name: 'Restore', + text: __('Restore'), + classname: 'btn btn-xs btn-info btn-ajax btn-restoreit', + icon: 'fa fa-rotate-left', + url: 'school/classes/activity/order/order_item/restore', + refresh: true + }, + { + name: 'Destroy', + text: __('Destroy'), + classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit', + icon: 'fa fa-times', + url: 'school/classes/activity/order/order_item/destroy', + refresh: true + } + ], + 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; +}); \ No newline at end of file