diff --git a/app/ExceptionHandler.php b/app/ExceptionHandler.php
new file mode 100644
index 0000000..6412fa9
--- /dev/null
+++ b/app/ExceptionHandler.php
@@ -0,0 +1,45 @@
+ 401, 'msg' => $exception->getMessage()], JSON_UNESCAPED_UNICODE);
+ return new Response(401, ['Content-Type' => 'application/json'], $json);
+ } elseif ($exception instanceof BusinessException) {
+ return json(['code' => 0, 'msg' => $exception->getMessage(), 'show' => 1]);
+ } elseif ($exception instanceof \Exception) {
+ $isDebug = config('app.debug');
+ $error = [
+ 'show' => 1,
+ 'code' => $isDebug ? $exception->getCode() : 0,
+ 'msg' => $isDebug ? $exception->getMessage() : '服务器内部错误',
+ ];
+ if ($isDebug) {
+ $error['file'] = $exception->getFile();
+ $error['line'] = $exception->getLine();
+ }
+ $json = json_encode($error, JSON_UNESCAPED_UNICODE);
+ return new Response(200, ['Content-Type' => 'application/json'], $json);
+ }
+ // 非json请求则返回一个页面
+ return new Response(200, [], 'msg:' . $exception->getMessage() . '。line:' . $exception->getLine() . '。file:' . $exception->getFile());
+ }
+}
diff --git a/app/admin/controller/DishesCategoryController.php b/app/admin/controller/DishesCategoryController.php
new file mode 100644
index 0000000..04edcce
--- /dev/null
+++ b/app/admin/controller/DishesCategoryController.php
@@ -0,0 +1,102 @@
+dataLists(new DishesCategoryLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function add()
+ {
+ $params = (new DishesCategoryValidate())->post()->goCheck('add');
+ $result = DishesCategoryLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(DishesCategoryLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function edit()
+ {
+ $params = (new DishesCategoryValidate())->post()->goCheck('edit');
+ $result = DishesCategoryLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(DishesCategoryLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function delete()
+ {
+ $params = (new DishesCategoryValidate())->post()->goCheck('delete');
+ DishesCategoryLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function detail()
+ {
+ $params = (new DishesCategoryValidate())->goCheck('detail');
+ $result = DishesCategoryLogic::detail($params);
+ return $this->data($result);
+ }
+
+ public function all(Request $request)
+ {
+ $params = $request->get();
+ $result = DishesCategoryLogic::all($params);
+ return $this->data($result);
+ }
+
+}
diff --git a/app/admin/controller/DishesController.php b/app/admin/controller/DishesController.php
new file mode 100644
index 0000000..fe91640
--- /dev/null
+++ b/app/admin/controller/DishesController.php
@@ -0,0 +1,95 @@
+dataLists(new DishesLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function add()
+ {
+ $params = (new DishesValidate())->post()->goCheck('add');
+ $result = DishesLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(DishesLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function edit()
+ {
+ $params = (new DishesValidate())->post()->goCheck('edit');
+ $result = DishesLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(DishesLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function delete()
+ {
+ $params = (new DishesValidate())->post()->goCheck('delete');
+ DishesLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function detail()
+ {
+ $params = (new DishesValidate())->goCheck('detail');
+ $result = DishesLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/DishesProductController.php b/app/admin/controller/DishesProductController.php
new file mode 100644
index 0000000..aac087e
--- /dev/null
+++ b/app/admin/controller/DishesProductController.php
@@ -0,0 +1,95 @@
+dataLists(new DishesProductLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function add()
+ {
+ $params = (new DishesProductValidate())->post()->goCheck('add');
+ $result = DishesProductLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(DishesProductLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function edit()
+ {
+ $params = (new DishesProductValidate())->post()->goCheck('edit');
+ $result = DishesProductLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(DishesProductLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function delete()
+ {
+ $params = (new DishesProductValidate())->post()->goCheck('delete');
+ DishesProductLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function detail()
+ {
+ $params = (new DishesProductValidate())->goCheck('detail');
+ $result = DishesProductLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/OrderController.php b/app/admin/controller/OrderController.php
new file mode 100644
index 0000000..2ae5a26
--- /dev/null
+++ b/app/admin/controller/OrderController.php
@@ -0,0 +1,95 @@
+dataLists(new OrderLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function add()
+ {
+ $params = (new OrderValidate())->post()->goCheck('add');
+ $result = OrderLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(OrderLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function edit()
+ {
+ $params = (new OrderValidate())->post()->goCheck('edit');
+ $result = OrderLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(OrderLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function delete()
+ {
+ $params = (new OrderValidate())->post()->goCheck('delete');
+ OrderLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function detail()
+ {
+ $params = (new OrderValidate())->goCheck('detail');
+ $result = OrderLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/ProductCategoryController.php b/app/admin/controller/ProductCategoryController.php
new file mode 100644
index 0000000..7774303
--- /dev/null
+++ b/app/admin/controller/ProductCategoryController.php
@@ -0,0 +1,102 @@
+dataLists(new ProductCategoryLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function add()
+ {
+ $params = (new ProductCategoryValidate())->post()->goCheck('add');
+ $result = ProductCategoryLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(ProductCategoryLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function edit()
+ {
+ $params = (new ProductCategoryValidate())->post()->goCheck('edit');
+ $result = ProductCategoryLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(ProductCategoryLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function delete()
+ {
+ $params = (new ProductCategoryValidate())->post()->goCheck('delete');
+ ProductCategoryLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function detail()
+ {
+ $params = (new ProductCategoryValidate())->goCheck('detail');
+ $result = ProductCategoryLogic::detail($params);
+ return $this->data($result);
+ }
+
+ public function all(Request $request)
+ {
+ $params = $request->get();
+ $result = ProductCategoryLogic::all($params);
+ return $this->data($result);
+ }
+
+}
diff --git a/app/admin/controller/ProductController.php b/app/admin/controller/ProductController.php
new file mode 100644
index 0000000..697ad3e
--- /dev/null
+++ b/app/admin/controller/ProductController.php
@@ -0,0 +1,95 @@
+dataLists(new ProductLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function add()
+ {
+ $params = (new ProductValidate())->post()->goCheck('add');
+ $result = ProductLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(ProductLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function edit()
+ {
+ $params = (new ProductValidate())->post()->goCheck('edit');
+ $result = ProductLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(ProductLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function delete()
+ {
+ $params = (new ProductValidate())->post()->goCheck('delete');
+ ProductLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function detail()
+ {
+ $params = (new ProductValidate())->goCheck('detail');
+ $result = ProductLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/ProductUnitController.php b/app/admin/controller/ProductUnitController.php
new file mode 100644
index 0000000..3793c31
--- /dev/null
+++ b/app/admin/controller/ProductUnitController.php
@@ -0,0 +1,95 @@
+dataLists(new ProductUnitLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function add()
+ {
+ $params = (new ProductUnitValidate())->post()->goCheck('add');
+ $result = ProductUnitLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(ProductUnitLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function edit()
+ {
+ $params = (new ProductUnitValidate())->post()->goCheck('edit');
+ $result = ProductUnitLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(ProductUnitLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function delete()
+ {
+ $params = (new ProductUnitValidate())->post()->goCheck('delete');
+ ProductUnitLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function detail()
+ {
+ $params = (new ProductUnitValidate())->goCheck('detail');
+ $result = ProductUnitLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/ProjectController.php b/app/admin/controller/ProjectController.php
new file mode 100644
index 0000000..10b590e
--- /dev/null
+++ b/app/admin/controller/ProjectController.php
@@ -0,0 +1,95 @@
+dataLists(new ProjectLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function add()
+ {
+ $params = (new ProjectValidate())->post()->goCheck('add');
+ $result = ProjectLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(ProjectLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function edit()
+ {
+ $params = (new ProjectValidate())->post()->goCheck('edit');
+ $result = ProjectLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(ProjectLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function delete()
+ {
+ $params = (new ProjectValidate())->post()->goCheck('delete');
+ ProjectLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function detail()
+ {
+ $params = (new ProjectValidate())->goCheck('detail');
+ $result = ProjectLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/ProjectDishesController.php b/app/admin/controller/ProjectDishesController.php
new file mode 100644
index 0000000..afadafa
--- /dev/null
+++ b/app/admin/controller/ProjectDishesController.php
@@ -0,0 +1,95 @@
+dataLists(new ProjectDishesLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function add()
+ {
+ $params = (new ProjectDishesValidate())->post()->goCheck('add');
+ $result = ProjectDishesLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(ProjectDishesLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function edit()
+ {
+ $params = (new ProjectDishesValidate())->post()->goCheck('edit');
+ $result = ProjectDishesLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(ProjectDishesLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function delete()
+ {
+ $params = (new ProjectDishesValidate())->post()->goCheck('delete');
+ ProjectDishesLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function detail()
+ {
+ $params = (new ProjectDishesValidate())->goCheck('detail');
+ $result = ProjectDishesLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/controller/ProjectDishesProductController.php b/app/admin/controller/ProjectDishesProductController.php
new file mode 100644
index 0000000..40e1bd0
--- /dev/null
+++ b/app/admin/controller/ProjectDishesProductController.php
@@ -0,0 +1,95 @@
+dataLists(new ProjectDishesProductLists());
+ }
+
+
+ /**
+ * @notes 添加
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function add()
+ {
+ $params = (new ProjectDishesProductValidate())->post()->goCheck('add');
+ $result = ProjectDishesProductLogic::add($params);
+ if (true === $result) {
+ return $this->success('添加成功', [], 1, 1);
+ }
+ return $this->fail(ProjectDishesProductLogic::getError());
+ }
+
+
+ /**
+ * @notes 编辑
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function edit()
+ {
+ $params = (new ProjectDishesProductValidate())->post()->goCheck('edit');
+ $result = ProjectDishesProductLogic::edit($params);
+ if (true === $result) {
+ return $this->success('编辑成功', [], 1, 1);
+ }
+ return $this->fail(ProjectDishesProductLogic::getError());
+ }
+
+
+ /**
+ * @notes 删除
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function delete()
+ {
+ $params = (new ProjectDishesProductValidate())->post()->goCheck('delete');
+ ProjectDishesProductLogic::delete($params);
+ return $this->success('删除成功', [], 1, 1);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @return \think\response\Json
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function detail()
+ {
+ $params = (new ProjectDishesProductValidate())->goCheck('detail');
+ $result = ProjectDishesProductLogic::detail($params);
+ return $this->data($result);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/admin/lists/DishesCategoryLists.php b/app/admin/lists/DishesCategoryLists.php
new file mode 100644
index 0000000..78bc809
--- /dev/null
+++ b/app/admin/lists/DishesCategoryLists.php
@@ -0,0 +1,81 @@
+ ['pid', 'name'],
+
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function lists(): array
+ {
+ $list = DishesCategory::where($this->searchWhere)
+ ->field(['id', 'pid', 'name', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ $list = linear_to_tree($list, 'children');
+ if (isset($this->params['disable'])) {
+ $list = $this->setDisable($list);
+ }
+ return $list;
+ }
+
+ public function setDisable($list)
+ {
+ foreach ($list as &$item) {
+ $item['disabled'] = $item['level'] > 0;
+ if (isset($item['children'])) {
+ $item['children'] = $this->setDisable($item['children']);
+ }
+ }
+ return $list;
+ }
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function count(): int
+ {
+ return DishesCategory::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/DishesLists.php b/app/admin/lists/DishesLists.php
new file mode 100644
index 0000000..2cd74c0
--- /dev/null
+++ b/app/admin/lists/DishesLists.php
@@ -0,0 +1,70 @@
+ ['name'],
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function lists(): array
+ {
+ $query = Dishes::where($this->searchWhere)->with('dishesCategory');
+ if (!empty($this->params['dishes_category_id'])) {
+ $dishesCategoryIds = DishesCategory::where('id', $this->params['dishes_category_id'])->whereOr('pid', $this->params['dishes_category_id'])->column('id');
+ $query->whereIn('dishes_category_id', $dishesCategoryIds);
+ }
+ return $query->field(['id', 'name', 'dishes_category_id', 'create_time', 'image', 'intro', 'min_num', 'sale_num', 'time_type', 'feature', 'people', 'status'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function count(): int
+ {
+ return Dishes::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/DishesProductLists.php b/app/admin/lists/DishesProductLists.php
new file mode 100644
index 0000000..655bda9
--- /dev/null
+++ b/app/admin/lists/DishesProductLists.php
@@ -0,0 +1,67 @@
+ ['dishes_id', 'product_id'],
+
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function lists(): array
+ {
+ return DishesProduct::where($this->searchWhere)
+ ->with(['unit', 'product', 'dishes'])
+ ->field(['id', 'dishes_id', 'product_id', 'unit_id', 'nums', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function count(): int
+ {
+ return DishesProduct::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/OrderLists.php b/app/admin/lists/OrderLists.php
new file mode 100644
index 0000000..7fd2663
--- /dev/null
+++ b/app/admin/lists/OrderLists.php
@@ -0,0 +1,72 @@
+ ['order_sn', 'uid', 'project_id', 'order_type', 'status', 'paid', 'pay_time', 'customer_name', 'phone'],
+
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function lists(): array
+ {
+ return Order::where($this->searchWhere)
+ ->with(['project'])
+ ->field(['id', 'order_sn', 'uid', 'project_id', 'order_type', 'total_amount', 'pay_amount', 'status', 'paid', 'pay_time', 'customer_name', 'phone', 'address', 'delivery_time', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->each(function ($item) {
+ $item['status_text'] = $item->statusText;
+ $item['pay_status_text'] = $item->payStatusText;
+ $item['order_type_text'] = $item->orderTypeText;
+ })
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function count(): int
+ {
+ return Order::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/ProductCategoryLists.php b/app/admin/lists/ProductCategoryLists.php
new file mode 100644
index 0000000..43b2135
--- /dev/null
+++ b/app/admin/lists/ProductCategoryLists.php
@@ -0,0 +1,67 @@
+ ['pid', 'name'],
+
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function lists(): array
+ {
+ $lists = ProductCategory::where($this->searchWhere)
+ ->field(['id', 'pid', 'name', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ return linear_to_tree($lists, 'children');
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function count(): int
+ {
+ return ProductCategory::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/ProductLists.php b/app/admin/lists/ProductLists.php
new file mode 100644
index 0000000..0f0ba93
--- /dev/null
+++ b/app/admin/lists/ProductLists.php
@@ -0,0 +1,75 @@
+ ['unit_id', 'name', 'product_type'],
+
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function lists(): array
+ {
+ $query = Product::where($this->searchWhere);
+ if (!empty($this->params['category_id'])) {
+ $query->whereFindInSet('category_ids', $this->params['category_id']);
+ }
+ return $query->with(['unit', 'category'])
+ ->field(['id', 'category_id', 'category_ids', 'unit_id', 'name', 'image', 'product_type', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->each(function ($item) {
+ $categories = ProductCategory::whereIn('id', $item['category_ids'])->column('name');
+ $item['categories'] = implode('/', $categories);
+ })
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function count(): int
+ {
+ return Product::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/ProductUnitLists.php b/app/admin/lists/ProductUnitLists.php
new file mode 100644
index 0000000..a82f788
--- /dev/null
+++ b/app/admin/lists/ProductUnitLists.php
@@ -0,0 +1,65 @@
+ ['name'],
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function lists(): array
+ {
+ return ProductUnit::where($this->searchWhere)
+ ->field(['id', 'name', 'conversion_value', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function count(): int
+ {
+ return ProductUnit::where($this->searchWhere)->count();
+ }
+
+}
\ No newline at end of file
diff --git a/app/admin/lists/ProjectDishesLists.php b/app/admin/lists/ProjectDishesLists.php
new file mode 100644
index 0000000..686b152
--- /dev/null
+++ b/app/admin/lists/ProjectDishesLists.php
@@ -0,0 +1,66 @@
+ ['project_id', 'dishes_id'],
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function lists(): array
+ {
+ return ProjectDishes::where($this->searchWhere)
+ ->with(['dishes', 'project'])
+ ->field(['id', 'project_id', 'dishes_id', 'consume_time', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function count(): int
+ {
+ return ProjectDishes::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/ProjectDishesProductLists.php b/app/admin/lists/ProjectDishesProductLists.php
new file mode 100644
index 0000000..6938a1b
--- /dev/null
+++ b/app/admin/lists/ProjectDishesProductLists.php
@@ -0,0 +1,67 @@
+ ['project_id', 'dishes_id', 'product_id'],
+
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function lists(): array
+ {
+ return ProjectDishesProduct::where($this->searchWhere)
+ ->with(['dishes', 'project', 'product', 'unit'])
+ ->field(['id', 'project_id', 'dishes_id', 'product_id', 'unit_id', 'nums', 'consume_time', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function count(): int
+ {
+ return ProjectDishesProduct::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/lists/ProjectLists.php b/app/admin/lists/ProjectLists.php
new file mode 100644
index 0000000..ff1a5b6
--- /dev/null
+++ b/app/admin/lists/ProjectLists.php
@@ -0,0 +1,73 @@
+ ['project_status'],
+ '>=' => ['start_time'],
+ '<=' => ['end_time'],
+ '%like%' => ['name', 'linkman', 'contact_number'],
+ ];
+ }
+
+
+ /**
+ * @notes 获取列表
+ * @return array
+ * @throws \think\db\exception\DataNotFoundException
+ * @throws \think\db\exception\DbException
+ * @throws \think\db\exception\ModelNotFoundException
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function lists(): array
+ {
+ $query = Project::where($this->searchWhere);
+ $sql = $query->field(['id', 'name', 'address', 'project_status', 'start_time', 'end_time', 'linkman', 'contacts_dept', 'contact_number', 'area_manager_id', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->fetchSql()
+ ->select();
+ return $query->field(['id', 'name', 'address', 'project_status', 'start_time', 'end_time', 'linkman', 'contacts_dept', 'contact_number', 'area_manager_id', 'create_time'])
+ ->limit($this->limitOffset, $this->limitLength)
+ ->order(['id' => 'desc'])
+ ->select()
+ ->toArray();
+ }
+
+
+ /**
+ * @notes 获取数量
+ * @return int
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function count(): int
+ {
+ return Project::where($this->searchWhere)->count();
+ }
+
+}
diff --git a/app/admin/logic/DishesCategoryLogic.php b/app/admin/logic/DishesCategoryLogic.php
new file mode 100644
index 0000000..a07e110
--- /dev/null
+++ b/app/admin/logic/DishesCategoryLogic.php
@@ -0,0 +1,106 @@
+ $params['pid'],
+ 'name' => $params['name'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ DishesCategory::where('id', $params['id'])->update([
+ 'pid' => $params['pid'],
+ 'name' => $params['name'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function delete(array $params): bool
+ {
+ return DishesCategory::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function detail($params): array
+ {
+ return DishesCategory::findOrEmpty($params['id'])->toArray();
+ }
+
+ public static function all($params)
+ {
+ $query = DishesCategory::field(['id', 'pid', 'name', 'create_time']);
+ if (!empty($params['name'])) {
+ $query->where('name', 'like', '%' . $params['name'] . '%');
+ }
+ return $query->order(['id' => 'desc'])->limit(1, 20)->select()->toArray();
+ }
+
+}
diff --git a/app/admin/logic/DishesLogic.php b/app/admin/logic/DishesLogic.php
new file mode 100644
index 0000000..90f7694
--- /dev/null
+++ b/app/admin/logic/DishesLogic.php
@@ -0,0 +1,121 @@
+ $params['name'],
+ 'image' => implode(',', $params['image']),
+ 'intro' => $params['intro'],
+ 'min_num' => $params['min_num'],
+ 'sale_num' => $params['sale_num'],
+ 'time_type' => $params['time_type'],
+ 'feature' => $params['feature'],
+ 'people' => $params['people'],
+ 'status' => $params['status'],
+ 'dishes_category_id' => $params['dishes_category_id'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ Dishes::where('id', $params['id'])->update([
+ 'name' => $params['name'],
+ 'image' => implode(',', $params['image']),
+ 'intro' => $params['intro'],
+ 'min_num' => $params['min_num'],
+ 'sale_num' => $params['sale_num'],
+ 'time_type' => $params['time_type'],
+ 'feature' => $params['feature'],
+ 'people' => $params['people'],
+ 'status' => $params['status'],
+ 'dishes_category_id' => $params['dishes_category_id'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function delete(array $params): bool
+ {
+ Dishes::destroy($params['id']);
+ DishesProduct::destroy(['dishes_id' => $params['id']]);
+ return true;
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function detail($params): array
+ {
+ $data = Dishes::findOrEmpty($params['id'])->toArray();
+ $data['image'] = !empty($data['image']) ? explode(',', $data['image']) : [];
+ foreach ($data['image'] as &$v) {
+ $v = FileService::getFileUrl($v) ;
+ }
+ return $data;
+ }
+}
diff --git a/app/admin/logic/DishesProductLogic.php b/app/admin/logic/DishesProductLogic.php
new file mode 100644
index 0000000..c2302d1
--- /dev/null
+++ b/app/admin/logic/DishesProductLogic.php
@@ -0,0 +1,100 @@
+ $params['dishes_id'],
+ 'product_id' => $params['product_id'],
+ 'unit_id' => $params['unit_id'],
+ 'nums' => $params['nums'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ DishesProduct::where('id', $params['id'])->update([
+ 'dishes_id' => $params['dishes_id'],
+ 'product_id' => $params['product_id'],
+ 'unit_id' => $params['unit_id'],
+ 'nums' => $params['nums'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function delete(array $params): bool
+ {
+ return DishesProduct::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function detail($params): array
+ {
+ return DishesProduct::findOrEmpty($params['id'])->toArray();
+ }
+}
\ No newline at end of file
diff --git a/app/admin/logic/OrderLogic.php b/app/admin/logic/OrderLogic.php
new file mode 100644
index 0000000..018f7f9
--- /dev/null
+++ b/app/admin/logic/OrderLogic.php
@@ -0,0 +1,130 @@
+ $params['order_sn'],
+ 'uid' => $params['uid'],
+ 'project_id' => $params['project_id'],
+ 'order_type' => $params['order_type'],
+ 'total_amount' => $params['total_amount'],
+ 'pay_amount' => $params['pay_amount'],
+ 'status' => $params['status'],
+ 'paid' => $params['paid'],
+ 'pay_time' => $params['pay_time'],
+ 'customer_name' => $params['customer_name'],
+ 'phone' => $params['phone'],
+ 'address' => $params['address'],
+ 'delivery_time' => $params['delivery_time'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ Order::where('id', $params['id'])->update([
+ 'order_sn' => $params['order_sn'],
+ 'uid' => $params['uid'],
+ 'project_id' => $params['project_id'],
+ 'order_type' => $params['order_type'],
+ 'total_amount' => $params['total_amount'],
+ 'pay_amount' => $params['pay_amount'],
+ 'status' => $params['status'],
+ 'paid' => $params['paid'],
+ 'pay_time' => $params['pay_time'],
+ 'customer_name' => $params['customer_name'],
+ 'phone' => $params['phone'],
+ 'address' => $params['address'],
+ 'delivery_time' => $params['delivery_time'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public static function delete(array $params): bool
+ {
+ return Order::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public static function detail($params): array
+ {
+ $data = Order::with(['orderDishes' => function ($query) {
+ $query->with('dishes');
+ }, 'orderProduct' => function ($query) {
+ $query->with('product');
+ }])->findOrEmpty($params['id']);
+ if (empty($data)) {
+ self::setError('订单不存在');
+ return [];
+ }
+ $data['status_text'] = $data->statusText;
+ $data['pay_status_text'] = $data->payStatusText;
+ $data['order_type_text'] = $data->orderTypeText;
+ return $data->toArray();
+ }
+}
diff --git a/app/admin/logic/ProductCategoryLogic.php b/app/admin/logic/ProductCategoryLogic.php
new file mode 100644
index 0000000..c02c9e2
--- /dev/null
+++ b/app/admin/logic/ProductCategoryLogic.php
@@ -0,0 +1,104 @@
+ $params['pid'],
+ 'name' => $params['name'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ ProductCategory::where('id', $params['id'])->update([
+ 'pid' => $params['pid'],
+ 'name' => $params['name'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function delete(array $params): bool
+ {
+ return ProductCategory::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function detail($params): array
+ {
+ return ProductCategory::findOrEmpty($params['id'])->toArray();
+ }
+
+ public static function all($params)
+ {
+ $query = ProductCategory::field(['id', 'pid', 'name', 'create_time']);
+ $list = $query->order(['id' => 'desc'])->select()->toArray();
+ return linear_to_tree($list, 'children');
+ }
+
+}
diff --git a/app/admin/logic/ProductLogic.php b/app/admin/logic/ProductLogic.php
new file mode 100644
index 0000000..dae4458
--- /dev/null
+++ b/app/admin/logic/ProductLogic.php
@@ -0,0 +1,116 @@
+ $params['category_id'],
+ 'category_ids' => implode(',', $params['category_ids']),
+ 'unit_id' => $params['unit_id'],
+ 'name' => $params['name'],
+ 'image' => implode(',', $params['image']),
+ 'intro' => $params['intro'],
+ 'conent' => $params['conent'],
+ 'product_type' => $params['product_type'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ $params['category_ids'] = ProductCategory::getParentUntilRoot($params['category_id']);
+ Product::where('id', $params['id'])->update([
+ 'category_id' => $params['category_id'],
+ 'category_ids' => implode(',', $params['category_ids']),
+ 'unit_id' => $params['unit_id'],
+ 'name' => $params['name'],
+ 'image' => implode(',', $params['image']),
+ 'intro' => $params['intro'],
+ 'conent' => $params['conent'],
+ 'product_type' => $params['product_type'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function delete(array $params): bool
+ {
+ return Product::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function detail($params): array
+ {
+ $data = Product::findOrEmpty($params['id'])->toArray();
+ $data['image'] = !empty($data['image']) ? explode(',', $data['image']) : [];
+ foreach ($data['image'] as &$v) {
+ $v = FileService::getFileUrl($v) ;
+ }
+ return $data;
+ }
+}
diff --git a/app/admin/logic/ProductUnitLogic.php b/app/admin/logic/ProductUnitLogic.php
new file mode 100644
index 0000000..4da640b
--- /dev/null
+++ b/app/admin/logic/ProductUnitLogic.php
@@ -0,0 +1,96 @@
+ $params['name'],
+ 'conversion_value' => $params['conversion_value'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ ProductUnit::where('id', $params['id'])->update([
+ 'name' => $params['name'],
+ 'conversion_value' => $params['conversion_value'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function delete(array $params): bool
+ {
+ return ProductUnit::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public static function detail($params): array
+ {
+ return ProductUnit::findOrEmpty($params['id'])->toArray();
+ }
+}
\ No newline at end of file
diff --git a/app/admin/logic/ProjectDishesLogic.php b/app/admin/logic/ProjectDishesLogic.php
new file mode 100644
index 0000000..13ba959
--- /dev/null
+++ b/app/admin/logic/ProjectDishesLogic.php
@@ -0,0 +1,98 @@
+ $params['project_id'],
+ 'dishes_id' => $params['dishes_id'],
+ 'consume_time' => $params['consume_time'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ ProjectDishes::where('id', $params['id'])->update([
+ 'project_id' => $params['project_id'],
+ 'dishes_id' => $params['dishes_id'],
+ 'consume_time' => $params['consume_time'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function delete(array $params): bool
+ {
+ return ProjectDishes::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function detail($params): array
+ {
+ return ProjectDishes::findOrEmpty($params['id'])->toArray();
+ }
+}
diff --git a/app/admin/logic/ProjectDishesProductLogic.php b/app/admin/logic/ProjectDishesProductLogic.php
new file mode 100644
index 0000000..7a70db5
--- /dev/null
+++ b/app/admin/logic/ProjectDishesProductLogic.php
@@ -0,0 +1,104 @@
+ $params['project_id'],
+ 'dishes_id' => $params['dishes_id'],
+ 'product_id' => $params['product_id'],
+ 'unit_id' => $params['unit_id'],
+ 'nums' => $params['nums'],
+ 'consume_time' => strtotime($params['consume_time']),
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ ProjectDishesProduct::where('id', $params['id'])->update([
+ 'project_id' => $params['project_id'],
+ 'dishes_id' => $params['dishes_id'],
+ 'product_id' => $params['product_id'],
+ 'unit_id' => $params['unit_id'],
+ 'nums' => $params['nums'],
+ 'consume_time' => strtotime($params['consume_time']),
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function delete(array $params): bool
+ {
+ return ProjectDishesProduct::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function detail($params): array
+ {
+ return ProjectDishesProduct::findOrEmpty($params['id'])->toArray();
+ }
+}
\ No newline at end of file
diff --git a/app/admin/logic/ProjectLogic.php b/app/admin/logic/ProjectLogic.php
new file mode 100644
index 0000000..4bc1b5c
--- /dev/null
+++ b/app/admin/logic/ProjectLogic.php
@@ -0,0 +1,110 @@
+ $params['name'],
+ 'address' => $params['address'],
+ 'project_status' => $params['project_status'],
+ 'start_time' => $params['start_time'],
+ 'end_time' => $params['end_time'],
+ 'linkman' => $params['linkman'],
+ 'contacts_dept' => $params['contacts_dept'],
+ 'contact_number' => $params['contact_number'],
+ 'area_manager_id' => $params['area_manager_id'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 编辑
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function edit(array $params): bool
+ {
+ Db::startTrans();
+ try {
+ Project::where('id', $params['id'])->update([
+ 'name' => $params['name'],
+ 'address' => $params['address'],
+ 'project_status' => $params['project_status'],
+ 'start_time' => $params['start_time'],
+ 'end_time' => $params['end_time'],
+ 'linkman' => $params['linkman'],
+ 'contacts_dept' => $params['contacts_dept'],
+ 'contact_number' => $params['contact_number'],
+ 'area_manager_id' => $params['area_manager_id'],
+ ]);
+
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ self::setError($e->getMessage());
+ return false;
+ }
+ }
+
+
+ /**
+ * @notes 删除
+ * @param array $params
+ * @return bool
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function delete(array $params): bool
+ {
+ return Project::destroy($params['id']);
+ }
+
+
+ /**
+ * @notes 获取详情
+ * @param $params
+ * @return array
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public static function detail($params): array
+ {
+ return Project::findOrEmpty($params['id'])->toArray();
+ }
+}
diff --git a/app/admin/validate/DishesCategoryValidate.php b/app/admin/validate/DishesCategoryValidate.php
new file mode 100644
index 0000000..40da5aa
--- /dev/null
+++ b/app/admin/validate/DishesCategoryValidate.php
@@ -0,0 +1,82 @@
+ 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return DishesCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return DishesCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return DishesCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return DishesCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
\ No newline at end of file
diff --git a/app/admin/validate/DishesProductValidate.php b/app/admin/validate/DishesProductValidate.php
new file mode 100644
index 0000000..23643ba
--- /dev/null
+++ b/app/admin/validate/DishesProductValidate.php
@@ -0,0 +1,90 @@
+ 'require',
+ 'dishes_id' => 'require',
+ 'product_id' => 'require',
+ 'unit_id' => 'require',
+ 'nums' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'dishes_id' => '菜品ID',
+ 'product_id' => '商品ID',
+ 'unit_id' => '单位ID',
+ 'nums' => '数量',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return DishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return DishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id', 'dishes_id', 'product_id', 'unit_id', 'nums']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return DishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return DishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/DishesValidate.php b/app/admin/validate/DishesValidate.php
new file mode 100644
index 0000000..b000600
--- /dev/null
+++ b/app/admin/validate/DishesValidate.php
@@ -0,0 +1,90 @@
+ 'require',
+ 'name' => 'require',
+ 'dishes_category_id' => 'require',
+ 'image' => 'require',
+ 'intro' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'name' => '名称',
+ 'dishes_category_id' => '菜品分类id',
+ 'image' => '图片',
+ 'intro' => '简介',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return DishesValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return DishesValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id', 'dishes_category_id', 'name', 'image', 'intro']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return DishesValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return DishesValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/OrderValidate.php b/app/admin/validate/OrderValidate.php
new file mode 100644
index 0000000..90113df
--- /dev/null
+++ b/app/admin/validate/OrderValidate.php
@@ -0,0 +1,82 @@
+ 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return OrderValidate
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return OrderValidate
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return OrderValidate
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return OrderValidate
+ * @author likeadmin
+ * @date 2025/07/17 17:16
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
\ No newline at end of file
diff --git a/app/admin/validate/ProductCategoryValidate.php b/app/admin/validate/ProductCategoryValidate.php
new file mode 100644
index 0000000..27eaa4d
--- /dev/null
+++ b/app/admin/validate/ProductCategoryValidate.php
@@ -0,0 +1,86 @@
+ 'require',
+ 'pid' => 'require',
+ 'name' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'pid' => '上级',
+ 'name' => '名称',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return ProductCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return ProductCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id', 'pid', 'name']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return ProductCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return ProductCategoryValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/ProductUnitValidate.php b/app/admin/validate/ProductUnitValidate.php
new file mode 100644
index 0000000..8608684
--- /dev/null
+++ b/app/admin/validate/ProductUnitValidate.php
@@ -0,0 +1,86 @@
+ 'require',
+ 'name' => 'require',
+ 'conversion_value' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'name' => '名称',
+ 'conversion_value' => '换算值',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return ProductUnitValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return ProductUnitValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return ProductUnitValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return ProductUnitValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/ProductValidate.php b/app/admin/validate/ProductValidate.php
new file mode 100644
index 0000000..cb6a364
--- /dev/null
+++ b/app/admin/validate/ProductValidate.php
@@ -0,0 +1,96 @@
+ 'require',
+ 'category_id' => 'require',
+ 'unit_id' => 'require',
+ 'name' => 'require',
+ 'image' => 'require',
+ 'intro' => 'require',
+ 'conent' => 'require',
+ 'product_type' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'category_id' => '分类',
+ 'unit_id' => '单位',
+ 'name' => '名称',
+ 'image' => '图片',
+ 'intro' => '简介',
+ 'conent' => '内容',
+ 'product_type' => '商品类型',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return ProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return ProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id', 'category_id', 'unit_id', 'name', 'image', 'intro', 'conent', 'product_type']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return ProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return ProductValidate
+ * @author likeadmin
+ * @date 2025/07/11 11:41
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/ProjectDishesProductValidate.php b/app/admin/validate/ProjectDishesProductValidate.php
new file mode 100644
index 0000000..2fb1027
--- /dev/null
+++ b/app/admin/validate/ProjectDishesProductValidate.php
@@ -0,0 +1,94 @@
+ 'require',
+ 'project_id' => 'require',
+ 'dishes_id' => 'require',
+ 'product_id' => 'require',
+ 'unit_id' => 'require',
+ 'nums' => 'require',
+ 'consume_time' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'project_id' => '项目ID',
+ 'dishes_id' => '菜品ID',
+ 'product_id' => '商品ID',
+ 'unit_id' => '单位ID',
+ 'nums' => '数量',
+ 'consume_time' => '食用时间',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return ProjectDishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return ProjectDishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id', 'project_id', 'dishes_id', 'product_id', 'unit_id', 'nums', 'consume_time']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return ProjectDishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return ProjectDishesProductValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/ProjectDishesValidate.php b/app/admin/validate/ProjectDishesValidate.php
new file mode 100644
index 0000000..3f1a45d
--- /dev/null
+++ b/app/admin/validate/ProjectDishesValidate.php
@@ -0,0 +1,88 @@
+ 'require',
+ 'project_id' => 'require',
+ 'dishes_id' => 'require',
+ 'consume_time' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'project_id' => '项目ID',
+ 'dishes_id' => '菜品ID',
+ 'consume_time' => '食用时间',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return ProjectDishesValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return ProjectDishesValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return ProjectDishesValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id', 'project_id', 'dishes_id', 'consume_time']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return ProjectDishesValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/admin/validate/ProjectValidate.php b/app/admin/validate/ProjectValidate.php
new file mode 100644
index 0000000..cb9bef2
--- /dev/null
+++ b/app/admin/validate/ProjectValidate.php
@@ -0,0 +1,100 @@
+ 'require',
+ 'name' => 'require',
+ 'address' => 'require',
+ 'start_time' => 'require',
+ 'end_time' => 'require',
+ 'linkman' => 'require',
+ 'contacts_dept' => 'require',
+ 'contact_number' => 'require',
+ 'area_manager_id' => 'require',
+ 'project_status' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'name' => '名称',
+ 'address' => '地址',
+ 'start_time' => '开始时间',
+ 'end_time' => '结束时间',
+ 'linkman' => '联系人',
+ 'contacts_dept' => '联系部门',
+ 'contact_number' => '联系电话',
+ 'area_manager_id' => '区域经理',
+ 'project_status' => '项目状态',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return ProjectValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return ProjectValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id', 'name', 'address', 'start_time', 'end_time', 'linkman', 'contacts_dept', 'contact_number', 'area_manager_id', 'project_status']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return ProjectValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return ProjectValidate
+ * @author likeadmin
+ * @date 2025/07/16 15:09
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/api/controller/AuthController.php b/app/api/controller/AuthController.php
new file mode 100644
index 0000000..964156b
--- /dev/null
+++ b/app/api/controller/AuthController.php
@@ -0,0 +1,22 @@
+post('type', 'wechat');
+ $code = $request->post('code', '', 1);
+ $token = $userLogic->login($type, $code);
+ return $this->data($token);
+ }
+
+}
diff --git a/app/api/controller/CartController.php b/app/api/controller/CartController.php
new file mode 100644
index 0000000..4c4c478
--- /dev/null
+++ b/app/api/controller/CartController.php
@@ -0,0 +1,77 @@
+request->get('keyword');
+ $params['uid'] = $this->request->user->id;
+ $params['page'] = $this->request->page();
+ $params['limit'] = $this->request->limit();
+ $data = $cartLogic->list($params);
+ return $this->data($data);
+ }
+
+ public function add(CartValidate $cartValidate, CartLogic $cartLogic)
+ {
+ $params = $this->request->post();
+ $params['uid'] = $this->request->user->id;
+ $params = $cartValidate->goCheck('add', $params);
+ $cartLogic->add($params);
+ return $this->success('添加成功', [], 1, 1);
+ }
+
+ public function delete(CartValidate $cartValidate, CartLogic $cartLogic)
+ {
+ $params = $cartValidate->post()->goCheck('delete');
+ $params['uid'] = $this->request->user->id;
+ if ($cartLogic->delete($params)) {
+ return $this->success('删除成功', [], 1, 1);
+ }
+ return $this->fail('删除失败');
+ }
+
+ public function count(CartLogic $cartLogic)
+ {
+ $params['uid'] = $this->request->user->id;
+ $data = $cartLogic->count($params);
+ return $this->data(['count' => $data]);
+ }
+
+ public function productList(CartLogic $cartLogic)
+ {
+ $params['keyword'] = $this->request->get('keyword');
+ $params['uid'] = $this->request->user->id;
+ $params['page'] = $this->request->page();
+ $params['limit'] = $this->request->limit();
+ $data = $cartLogic->productList($params);
+ return $this->data($data);
+ }
+
+ public function changeNumber(CartLogic $cartLogic)
+ {
+ $params['uid'] = $this->request->user->id;
+ $params['id'] = $this->request->post('id');
+ $params['nums'] = $this->request->post('nums');
+ $cartLogic->changeNumber($params);
+ return $this->success('修改成功', [], 1, 1);
+ }
+
+ public function changePeopleNumber(CartLogic $cartLogic)
+ {
+ $params['uid'] = $this->request->user->id;
+ $params['people_number'] = $this->request->post('people_number');
+ if ($cartLogic->changePeopleNumber($params)) {
+ return $this->success('修改成功', [], 1, 1);
+ }
+ return $this->fail('修改失败');
+ }
+
+}
diff --git a/app/api/controller/DishesController.php b/app/api/controller/DishesController.php
new file mode 100644
index 0000000..092933e
--- /dev/null
+++ b/app/api/controller/DishesController.php
@@ -0,0 +1,49 @@
+select()->toArray();
+ $category = linear_to_tree($category, 'children');
+ return $this->data($category);
+ }
+
+ public function dishes()
+ {
+ $categoryId = $this->request->get('category_id');
+ $keyword = $this->request->get('keyword');
+ $query = Dishes::field('id,dishes_category_id,name,image,intro')->where('status', 1);
+ if (!empty($categoryId)) {
+ $query->where('dishes_category_id', $categoryId);
+ }
+ if (!empty($keyword)) {
+ $query->whereLike('name', "%$keyword%");
+ }
+ $data = $query->select()->toArray();
+ return $this->data($data);
+ }
+
+ public function detail()
+ {
+ $id = $this->request->get('id');
+ $data = Dishes::with(['dishesProduct' => function ($query) {
+ $query->with(['product', 'unit']);
+ }])->where('id', $id)->where('status', 1)->find();
+ if (empty($data)) {
+ return $this->fail('菜品不存在');
+ }
+ $data = $data->toArray();
+ return $this->data($data);
+ }
+
+}
diff --git a/app/api/controller/OrderController.php b/app/api/controller/OrderController.php
new file mode 100644
index 0000000..69c26b3
--- /dev/null
+++ b/app/api/controller/OrderController.php
@@ -0,0 +1,33 @@
+request->user->id;
+ $data = $logic->check($params);
+ return $this->data($data);
+ }
+
+ public function create(OrderValidate $validate, OrderLogic $logic)
+ {
+ $params = $this->request->post();
+ $params['uid'] = $this->request->user->id;
+ $params = $validate->goCheck('add', $params);
+ $logic->create($params);
+ return $this->success('订单创建成功', [], 1, 1);
+ }
+
+ public function list(OrderLogic $logic)
+ {
+
+ }
+
+}
diff --git a/app/api/controller/UserController.php b/app/api/controller/UserController.php
new file mode 100644
index 0000000..17056cb
--- /dev/null
+++ b/app/api/controller/UserController.php
@@ -0,0 +1,16 @@
+address($this->request->user->id);
+ }
+
+}
diff --git a/app/api/logic/CartLogic.php b/app/api/logic/CartLogic.php
new file mode 100644
index 0000000..fc20d0c
--- /dev/null
+++ b/app/api/logic/CartLogic.php
@@ -0,0 +1,120 @@
+ function ($query) {
+ $query->with(['product', 'unit']);
+ }])->where('uid', $params['uid'])->where('paid', 0)->where('buy_now', 0);
+ if (!empty($params['keyword'])) {
+ $dishesIds = Dishes::whereLike('name', "%{$params['keyword']}%")->column('id');
+ $query->whereIn('dishes_id', $dishesIds);
+ }
+ return $query->page($params['page'], $params['limit'])->select()->toArray();
+ }
+
+ public function count($params)
+ {
+ return Cart::where('uid', $params['uid'])->where('paid', 0)->where('buy_now', 0)->count();
+ }
+
+ public function delete($params)
+ {
+ Db::startTrans();
+ try {
+ CartProduct::destroy(['cart_id' => $params['id']]);
+ Cart::destroy(['id' => $params['id'], 'uid' => $params['uid']]);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ return false;
+ }
+ }
+
+ public function add($params)
+ {
+ Db::startTrans();
+ try {
+ $cart = new Cart();
+ if (empty($params['people_number'])) {
+ $params['people_number'] = 1;
+ }
+ if (!$cart->save($params)) {
+ throw new \Exception('添加购物车失败');
+ }
+ $products = DishesProduct::where('dishes_id', $params['dishes_id'])->select()->toArray();
+ $cartProductData = [];
+ $datetime = date('Y-m-d H:i:s');
+ foreach ($products as $product) {
+ $cartProductData[] = [
+ 'uid' => $params['uid'],
+ 'dishes_id' => $params['dishes_id'],
+ 'product_id' => $product['product_id'],
+ 'cart_id' => $cart->id,
+ 'nums' => $product['nums'],
+ 'unit_id' => $product['unit_id'],
+ 'create_time' => $datetime,
+ 'update_time' => $datetime,
+ ];
+ }
+ if (!CartProduct::insertAll($cartProductData)) {
+ throw new \Exception('添加购物车商品失败');
+ }
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ throw $e;
+ }
+ }
+
+ public function productList($params)
+ {
+ $query = CartProduct::alias('t1')
+ ->with(['dishes', 'product', 'unit'])
+ ->join('cart t2', 't1.cart_id = t2.id')
+ ->where('t2.uid', $params['uid'])
+ ->where('t2.buy_now', 0)
+ ->where('t2.paid', 0);
+ if (!empty($params['keyword'])) {
+ $dishesIds = Dishes::whereLike('name', "%{$params['keyword']}%")->column('id');
+ $query->whereIn('t2.dishes_id', $dishesIds);
+ }
+ return $query->page($params['page'], $params['limit'])->select()->toArray();
+ }
+
+ public function changePeopleNumber($params)
+ {
+ Db::startTrans();
+ try {
+ $cartWhere = ['uid' => $params['uid'], 'paid' => 0, 'buy_now' => 0];
+ Cart::update(['people_number' => $params['people_number']], $cartWhere);
+ $cartIds = Cart::where($cartWhere)->column('id');
+ CartProduct::whereIn('cart_id', $cartIds)->where('uid', $params['uid'])->update(['people_number' => $params['people_number']]);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ return false;
+ }
+ }
+
+ public function changeNumber($params)
+ {
+ CartProduct::whereIn('id', $params['id'])->where('uid', $params['uid'])->update(['nums' => $params['nums']]);
+ return true;
+ }
+
+}
diff --git a/app/api/logic/OrderLogic.php b/app/api/logic/OrderLogic.php
new file mode 100644
index 0000000..10593ec
--- /dev/null
+++ b/app/api/logic/OrderLogic.php
@@ -0,0 +1,56 @@
+where('uid', $params['uid'])
+ ->where('buy_now', 0)
+ ->where('.paid', 0);
+ return $query->select()->toArray();
+ }
+
+ public function create($params)
+ {
+ Db::startTrans();
+ try {
+ $carts = Cart::with(['cartDishes', 'cartProduct'])->where('uid', $params['uid'])->whereIn('id', $params['cart_ids'])->where('paid', 0)->where('buy_now', 0)->select()->toArray();
+ $orderData = [
+ 'uid' => $params['uid'],
+ 'order_sn' => Order::generateOrderSn(),
+ 'order_type' => 0,
+ ];
+ foreach ($carts as $cart) {
+ $orderData[] = [];
+ }
+ $cartWhere = ['uid' => $params['uid'], 'paid' => 0, 'buy_now' => 0];
+ Cart::update(['people_number' => $params['people_number']], $cartWhere);
+ $cartIds = Cart::where($cartWhere)->column('id');
+ CartProduct::whereIn('cart_id', $cartIds)->where('uid', $params['uid'])->update(['people_number' => $params['people_number']]);
+ Db::commit();
+ return true;
+ } catch (\Exception $e) {
+ Db::rollback();
+ return false;
+ }
+ }
+
+ public function list()
+ {
+
+ }
+
+}
diff --git a/app/api/logic/UserLogic.php b/app/api/logic/UserLogic.php
new file mode 100644
index 0000000..2bb26d1
--- /dev/null
+++ b/app/api/logic/UserLogic.php
@@ -0,0 +1,39 @@
+order('is_default desc,id desc')->select()->toArray();
+ }
+
+ public function login($code, $type)
+ {
+ if (env('environment') == 'local') {
+ $user = User::find(1);
+ $data = [
+ 'id' => $user->id,
+ 'nickname' => $user->nickname,
+ 'avatar' => $user->avatar,
+ 'code' => $user->code,
+ ];
+ $token = JwtToken::generateToken(['id' => $user->id]);
+ $token['expires_in'] = $token['expires_in'] + time();
+ $token['refresh_token_expire'] = time() + config('plugin.tinywan.jwt.app.jwt.refresh_exp');
+ $data['token'] = $token;
+ } else {
+ $wechatUserLogic = new WechatUserLogic();
+ $data = $wechatUserLogic->findOrCreate($code);
+ }
+ return $data;
+ }
+
+}
diff --git a/app/api/logic/WechatUserLogic.php b/app/api/logic/WechatUserLogic.php
new file mode 100644
index 0000000..088dc33
--- /dev/null
+++ b/app/api/logic/WechatUserLogic.php
@@ -0,0 +1,68 @@
+appId();
+ $res = $handler->login($code);
+ Db::startTrans();
+ try {
+ $wechatUser = WechatUser::withTrashed()->where('app_id', $appId)->where('routine_openid', $res['openid'])->find();
+ if (empty($wechatUser)) {
+ $wechatUser = new WechatUser();
+ $wechatUser->app_id = $appId;
+ $wechatUser->unionid = $res['union_id'] ?? $res['unionid'] ?? '';
+ $wechatUser->routine_openid = $res['openid'];
+ $wechatUser->nickname = !empty($this->nickname) ? $this->nickname : $handler->nickname();
+ $wechatUser->headimgurl = $handler->avatar();
+ if (!$wechatUser->save()) {
+ throw new \Exception('三方登录信息保存出错', 500);
+ }
+ }
+ $user = User::withTrashed()->where('wechat_user_id', $wechatUser->id)->field('id,nickname,avatar')->find();
+ if (!empty($user['delete_time'])) {
+ throw new BusinessException('账号已注销', 500);
+ }
+ if (empty($user)) {
+ $user = new User();
+ $user->wechat_user_id = $wechatUser->id;
+ $user->real_name = '';
+ $user->nickname = $wechatUser->nickname;
+ $user->avatar = $wechatUser->headimgurl;
+ }
+ $user->last_time = date('Y-m-d H:i:s');
+ if (!$user->save()) {
+ throw new \Exception('用户信息保存出错', 500);
+ }
+ Db::commit();
+ } catch (\Exception $exception) {
+ Db::rollback();
+ throw new \Exception($exception->getMessage(), $exception->getCode());
+ }
+ $tokenParam = [
+ 'id' => $user->id,
+ 'nickname' => $user->nickname,
+ 'avatar' => $user->avatar,
+ 'code' => $user->code,
+ ];
+ $token = JwtToken::generateToken(['id' => $user->id]);
+ $token['expires_in'] = $token['expires_in'] + time();
+ $token['refresh_token_expire'] = time() + config('plugin.tinywan.jwt.app.jwt.refresh_exp');
+ $tokenParam['token'] = $token;
+ return $tokenParam;
+ }
+
+}
diff --git a/app/api/middleware/AuthMiddleware.php b/app/api/middleware/AuthMiddleware.php
new file mode 100644
index 0000000..5715234
--- /dev/null
+++ b/app/api/middleware/AuthMiddleware.php
@@ -0,0 +1,37 @@
+user = User::withTrashed()->find($payload['extend']['id']);
+ if (empty($request->user)) {
+ throw new UnauthorizedException('用户不存在', 401);
+ }
+ } catch (\Throwable $e) {
+ $controller = new $request->controller;
+ if ((!isset($controller->optional) || !in_array($request->action, $controller->optional))) {
+ throw new UnauthorizedException('请登录', 401);
+ }
+ }
+
+ /** @var Response $response */
+ $response = $handler($request);
+ return $response;
+ }
+}
diff --git a/app/api/validate/CartValidate.php b/app/api/validate/CartValidate.php
new file mode 100644
index 0000000..0708856
--- /dev/null
+++ b/app/api/validate/CartValidate.php
@@ -0,0 +1,79 @@
+ 'require',
+ 'uid' => 'require',
+ 'dishes_id' => 'require',
+// 'project_id' => 'require',
+// 'cart_num' => 'require',
+// 'paid' => 'require',
+ 'buy_now' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'uid' => '用户id',
+ 'dishes_id' => '菜品id',
+ 'project_id' => '项目id',
+ 'cart_num' => '购买数量',
+ 'paid' => '支付状态',
+ 'buy_now' => '立即购买',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return CartValidate
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return CartValidate
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return CartValidate
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return CartValidate
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/api/validate/OrderValidate.php b/app/api/validate/OrderValidate.php
new file mode 100644
index 0000000..ed28e39
--- /dev/null
+++ b/app/api/validate/OrderValidate.php
@@ -0,0 +1,77 @@
+ 'require',
+ 'uid' => 'require',
+ 'address_id' => 'require',
+ 'delivery_date' => 'require',
+ 'delivery_time ' => 'require',
+ 'cart_ids' => 'require',
+ ];
+
+
+ /**
+ * 参数描述
+ * @var string[]
+ */
+ protected $field = [
+ 'id' => 'id',
+ 'uid' => '用户id',
+ 'address_id' => '地址id',
+ 'delivery_date' => '配送日期',
+ 'delivery_time' => '配送时间',
+ 'cart_ids' => '购物车id',
+ ];
+
+
+ /**
+ * @notes 添加场景
+ * @return OrderValidate
+ */
+ public function sceneAdd()
+ {
+ return $this->remove('id', true);
+ }
+
+
+ /**
+ * @notes 编辑场景
+ * @return OrderValidate
+ */
+ public function sceneEdit()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 删除场景
+ * @return OrderValidate
+ */
+ public function sceneDelete()
+ {
+ return $this->only(['id']);
+ }
+
+
+ /**
+ * @notes 详情场景
+ * @return OrderValidate
+ */
+ public function sceneDetail()
+ {
+ return $this->only(['id']);
+ }
+
+}
diff --git a/app/common/exception/UnauthorizedException.php b/app/common/exception/UnauthorizedException.php
new file mode 100644
index 0000000..3fdc70d
--- /dev/null
+++ b/app/common/exception/UnauthorizedException.php
@@ -0,0 +1,20 @@
+response = json(json_decode($message,true));
+ parent::__construct($message, $code, $previous);
+ }
+
+ public function getResponse(){
+ return $this->response;
+ }
+}
diff --git a/app/common/model/Cart.php b/app/common/model/Cart.php
new file mode 100644
index 0000000..b8c3664
--- /dev/null
+++ b/app/common/model/Cart.php
@@ -0,0 +1,23 @@
+hasOne(Dishes::class, 'id', 'dishes_id')->bind(['dishes_name' => 'name', 'image']);
+ }
+
+ public function cartProduct()
+ {
+ return $this->hasMany(CartProduct::class, 'cart_id', 'id');
+ }
+
+}
diff --git a/app/common/model/CartProduct.php b/app/common/model/CartProduct.php
new file mode 100644
index 0000000..3a0e368
--- /dev/null
+++ b/app/common/model/CartProduct.php
@@ -0,0 +1,29 @@
+hasOne(Dishes::class, 'id', 'dishes_id')->bind(['dishes_name' => 'name']);
+ }
+
+ public function product()
+ {
+ return $this->hasOne(Product::class, 'id', 'product_id')->bind(['product_name' => 'name', 'image', 'product_type']);
+ }
+
+ public function unit()
+ {
+ return $this->hasOne(ProductUnit::class, 'id', 'unit_id')->bind(['unit_name' => 'name']);
+ }
+
+}
diff --git a/app/common/model/Dishes.php b/app/common/model/Dishes.php
new file mode 100644
index 0000000..3217ecb
--- /dev/null
+++ b/app/common/model/Dishes.php
@@ -0,0 +1,31 @@
+hasOne(DishesCategory::class, 'id', 'dishes_category_id');
+ }
+
+ public function dishesProduct()
+ {
+ return $this->hasMany(DishesProduct::class, 'dishes_id', 'id');
+ }
+
+}
diff --git a/app/common/model/DishesCategory.php b/app/common/model/DishesCategory.php
new file mode 100644
index 0000000..401795a
--- /dev/null
+++ b/app/common/model/DishesCategory.php
@@ -0,0 +1,22 @@
+hasOne(Dishes::class, 'id', 'dishes_id')->field('id,name');
+ }
+
+ public function product()
+ {
+ return $this->hasOne(Product::class, 'id', 'product_id')->field('id,name,image');
+ }
+
+ public function unit()
+ {
+ return $this->hasOne(ProductUnit::class, 'id', 'unit_id')->field('id,name');
+ }
+
+}
diff --git a/app/common/model/Order.php b/app/common/model/Order.php
new file mode 100644
index 0000000..86c7173
--- /dev/null
+++ b/app/common/model/Order.php
@@ -0,0 +1,78 @@
+ '待发货',
+ 1 => '待收货',
+ 2 => '待评价',
+ 3 => '已完成',
+ 9 => '拼团中',
+ 10 => '待付尾款',
+ 11 => '尾款超时未付',
+ -1 => '已退款',
+ ];
+ const OrderTypeMap = [
+ 1 => '普通订单',
+ 2 => '自提订单',
+ ];
+ const PayStatusMap = [
+ 0 => '待支付',
+ 1 => '已支付',
+ ];
+
+ protected $name = 'order';
+ protected $deleteTime = 'delete_time';
+
+ public function project()
+ {
+ return $this->hasOne(Project::class, 'id', 'project_id')->field('id,name');
+ }
+
+ public function orderDishes()
+ {
+ return $this->hasMany(OrderDishes::class, 'order_id', 'id');
+ }
+
+ public function orderProduct()
+ {
+ return $this->hasMany(OrderProduct::class, 'order_id', 'id');
+ }
+
+ public function getStatusTextAttr($value)
+ {
+ return self::StatusMap[$this->status];
+ }
+
+ public function getOrderTypeTextAttr($value)
+ {
+ return self::OrderTypeMap[$this->order_type];
+ }
+
+ public function getPayStatusTextAttr($value)
+ {
+ return self::PayStatusMap[$this->paid];
+ }
+
+ public static function generateOrderSn($type = 'wxo')
+ {
+ list($msec, $sec) = explode(' ', microtime());
+ $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
+ return $type . $msectime . mt_rand(10000, max(intval($msec * 10000) + 10000, 98369));
+ }
+
+}
diff --git a/app/common/model/OrderDishes.php b/app/common/model/OrderDishes.php
new file mode 100644
index 0000000..3ac7366
--- /dev/null
+++ b/app/common/model/OrderDishes.php
@@ -0,0 +1,24 @@
+hasOne(Dishes::class, 'id', 'dishes_id');
+ }
+
+}
diff --git a/app/common/model/OrderProduct.php b/app/common/model/OrderProduct.php
new file mode 100644
index 0000000..882d7ea
--- /dev/null
+++ b/app/common/model/OrderProduct.php
@@ -0,0 +1,25 @@
+hasOne(Product::class, 'id', 'product_id');
+ }
+
+}
diff --git a/app/common/model/Product.php b/app/common/model/Product.php
new file mode 100644
index 0000000..5fec5a1
--- /dev/null
+++ b/app/common/model/Product.php
@@ -0,0 +1,31 @@
+hasOne(ProductUnit::class, 'id', 'unit_id')->field('id,name,conversion_value');
+ }
+
+ public function category()
+ {
+ return $this->hasOne(ProductCategory::class, 'id', 'category_id')->field('id,name,pid');
+ }
+
+}
diff --git a/app/common/model/ProductCategory.php b/app/common/model/ProductCategory.php
new file mode 100644
index 0000000..19bc84d
--- /dev/null
+++ b/app/common/model/ProductCategory.php
@@ -0,0 +1,32 @@
+value('pid');
+ if ($pid) {
+ self::getParentUntilRoot($pid);
+ }
+ return $parentIds;
+ }
+
+}
diff --git a/app/common/model/ProductUnit.php b/app/common/model/ProductUnit.php
new file mode 100644
index 0000000..6564033
--- /dev/null
+++ b/app/common/model/ProductUnit.php
@@ -0,0 +1,22 @@
+hasOne(Project::class, 'id', 'project_id')->field('id,name');
+ }
+
+ public function dishes()
+ {
+ return $this->hasOne(Dishes::class, 'id', 'dishes_id')->field('id,name');
+ }
+
+}
diff --git a/app/common/model/ProjectDishesProduct.php b/app/common/model/ProjectDishesProduct.php
new file mode 100644
index 0000000..6424d8b
--- /dev/null
+++ b/app/common/model/ProjectDishesProduct.php
@@ -0,0 +1,41 @@
+hasOne(Project::class, 'id', 'project_id')->field('id,name');
+ }
+
+ public function dishes()
+ {
+ return $this->hasOne(Dishes::class, 'id', 'dishes_id')->field('id,name');
+ }
+
+ public function product()
+ {
+ return $this->hasOne(Product::class, 'id', 'product_id')->field('id,name');
+ }
+
+ public function unit()
+ {
+ return $this->hasOne(ProductUnit::class, 'id', 'unit_id')->field('id,name');
+ }
+
+}
diff --git a/app/common/model/user/UserAddress.php b/app/common/model/user/UserAddress.php
new file mode 100644
index 0000000..34cb091
--- /dev/null
+++ b/app/common/model/user/UserAddress.php
@@ -0,0 +1,10 @@
+file)) {
throw new Exception('未找到上传文件的信息');
}
- $this->file->extension = pathinfo($this->file->getUploadName(), PATHINFO_EXTENSION);
+ $extension = pathinfo($this->file->getUploadName(), PATHINFO_EXTENSION);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
- $this->file->getMime = finfo_file($finfo, $this->file->getPathname());
+ $mimeType = finfo_file($finfo, $this->file->getPathname());
// 校验上传文件后缀
$limit = array_merge(config('project.file_image'), config('project.file_video'));
- if (!in_array(strtolower($this->file->extension), $limit)) {
- throw new Exception('不允许上传' . $this->file->extension . '后缀文件');
+ if (!in_array(strtolower($extension), $limit)) {
+ throw new Exception('不允许上传' . $extension . '后缀文件');
}
// 文件信息
$this->fileInfo = [
- 'ext' => $this->file->extension,
+ 'ext' => $extension,
'size' => $this->file->getSize(),
- 'mime' => $this->file->getMime,
+ 'mime' => $mimeType,
'name' => $this->file->getUploadName(),
'realPath' => $this->file->getRealPath(),
];
diff --git a/app/common/validate/BaseValidate.php b/app/common/validate/BaseValidate.php
index 5be1236..8259f2e 100755
--- a/app/common/validate/BaseValidate.php
+++ b/app/common/validate/BaseValidate.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
namespace app\common\validate;
use app\common\service\JsonService;
+use support\exception\BusinessException;
use taoser\Validate;
class BaseValidate extends Validate
@@ -79,9 +80,9 @@ class BaseValidate extends Validate
if (!$result) {
$exception = is_array($this->error) ? implode(';', $this->error) : $this->error;
- JsonService::throw($exception);
+ throw new BusinessException($exception);
}
// 3.成功返回数据
return $params;
}
-}
\ No newline at end of file
+}
diff --git a/app/functions.php b/app/functions.php
index bfd66a8..2ff634c 100644
--- a/app/functions.php
+++ b/app/functions.php
@@ -92,15 +92,17 @@ function create_password(string $plaintext, string $salt) : string
* @param string $parent_id_name 数组祖先id名
* @param int $level 此值请勿给参数
* @param int $parent_id 此值请勿给参数
+ * @param int $level 等级
* @return array
*/
-function linear_to_tree($data, $sub_key_name = 'sub', $id_name = 'id', $parent_id_name = 'pid', $parent_id = 0)
+function linear_to_tree($data, $sub_key_name = 'sub', $id_name = 'id', $parent_id_name = 'pid', $parent_id = 0, $level = 0)
{
$tree = [];
foreach ($data as $row) {
+ $row['level'] = $level;
if ($row[$parent_id_name] == $parent_id) {
$temp = $row;
- $child = linear_to_tree($data, $sub_key_name, $id_name, $parent_id_name, $row[$id_name]);
+ $child = linear_to_tree($data, $sub_key_name, $id_name, $parent_id_name, $row[$id_name], $level + 1);
if ($child) {
$temp[$sub_key_name] = $child;
}
@@ -206,4 +208,4 @@ function get_file_domain($content)
$preg = '/(
)/is';
$fileUrl = FileService::getFileUrl();
return preg_replace($preg, "\${1}$fileUrl\${2}\${3}", $content);
-}
\ No newline at end of file
+}
diff --git a/composer.lock b/composer.lock
index 860c272..13dff43 100644
--- a/composer.lock
+++ b/composer.lock
@@ -361,6 +361,69 @@
],
"time": "2022-09-18T07:06:19+00:00"
},
+ {
+ "name": "firebase/php-jwt",
+ "version": "v6.11.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/firebase/php-jwt.git",
+ "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
+ "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^2.0||^3.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
+ },
+ "suggest": {
+ "ext-sodium": "Support EdDSA (Ed25519) signatures",
+ "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Firebase\\JWT\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Neuman Vong",
+ "email": "neuman+pear@twilio.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Anant Narayanan",
+ "email": "anant@php.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
+ "homepage": "https://github.com/firebase/php-jwt",
+ "keywords": [
+ "jwt",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/firebase/php-jwt/issues",
+ "source": "https://github.com/firebase/php-jwt/tree/v6.11.1"
+ },
+ "time": "2025-04-09T20:32:01+00:00"
+ },
{
"name": "graham-campbell/result-type",
"version": "v1.1.1",
@@ -1534,6 +1597,221 @@
],
"time": "2018-02-13T20:26:39+00:00"
},
+ {
+ "name": "nyholm/psr7",
+ "version": "1.8.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Nyholm/psr7.git",
+ "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Nyholm/psr7/zipball/a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
+ "reference": "a71f2b11690f4b24d099d6b16690a90ae14fc6f3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0"
+ },
+ "provide": {
+ "php-http/message-factory-implementation": "1.0",
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "http-interop/http-factory-tests": "^0.9",
+ "php-http/message-factory": "^1.0",
+ "php-http/psr7-integration-tests": "^1.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
+ "symfony/error-handler": "^4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.8-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Nyholm\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com"
+ },
+ {
+ "name": "Martijn van der Ven",
+ "email": "martijn@vanderven.se"
+ }
+ ],
+ "description": "A fast PHP7 implementation of PSR-7",
+ "homepage": "https://tnyholm.se",
+ "keywords": [
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "issues": "https://github.com/Nyholm/psr7/issues",
+ "source": "https://github.com/Nyholm/psr7/tree/1.8.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Zegnat",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nyholm",
+ "type": "github"
+ }
+ ],
+ "time": "2024-09-09T07:06:30+00:00"
+ },
+ {
+ "name": "nyholm/psr7-server",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Nyholm/psr7-server.git",
+ "reference": "4335801d851f554ca43fa6e7d2602141538854dc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Nyholm/psr7-server/zipball/4335801d851f554ca43fa6e7d2602141538854dc",
+ "reference": "4335801d851f554ca43fa6e7d2602141538854dc",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "require-dev": {
+ "nyholm/nsa": "^1.1",
+ "nyholm/psr7": "^1.3",
+ "phpunit/phpunit": "^7.0 || ^8.5 || ^9.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Nyholm\\Psr7Server\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com"
+ },
+ {
+ "name": "Martijn van der Ven",
+ "email": "martijn@vanderven.se"
+ }
+ ],
+ "description": "Helper classes to handle PSR-7 server requests",
+ "homepage": "http://tnyholm.se",
+ "keywords": [
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "issues": "https://github.com/Nyholm/psr7-server/issues",
+ "source": "https://github.com/Nyholm/psr7-server/tree/1.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Zegnat",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nyholm",
+ "type": "github"
+ }
+ ],
+ "time": "2023-11-08T09:30:43+00:00"
+ },
+ {
+ "name": "overtrue/socialite",
+ "version": "4.11.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/overtrue/socialite.git",
+ "reference": "83dd537a88b30cd9204ee2c46a5b2e181bc1fa66"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/overtrue/socialite/zipball/83dd537a88b30cd9204ee2c46a5b2e181bc1fa66",
+ "reference": "83dd537a88b30cd9204ee2c46a5b2e181bc1fa66",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-openssl": "*",
+ "guzzlehttp/guzzle": "^7.0",
+ "php": ">=8.0.2"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "^1.0",
+ "laravel/pint": "^1.2",
+ "mockery/mockery": "^1.3",
+ "phpstan/phpstan": "^1.7",
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Contracts/FactoryInterface.php",
+ "src/Contracts/UserInterface.php",
+ "src/Contracts/ProviderInterface.php"
+ ],
+ "psr-4": {
+ "Overtrue\\Socialite\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "overtrue",
+ "email": "anzhengchao@gmail.com"
+ }
+ ],
+ "description": "A collection of OAuth 2 packages.",
+ "keywords": [
+ "Feishu",
+ "login",
+ "oauth",
+ "qcloud",
+ "qq",
+ "social",
+ "wechat",
+ "weibo"
+ ],
+ "support": {
+ "issues": "https://github.com/overtrue/socialite/issues",
+ "source": "https://github.com/overtrue/socialite/tree/4.11.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/overtrue",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-08T16:23:14+00:00"
+ },
{
"name": "php-di/invoker",
"version": "2.3.4",
@@ -2521,6 +2799,332 @@
"homepage": "https://symfony.com",
"time": "2023-05-23T14:45:45+00:00"
},
+ {
+ "name": "symfony/http-client",
+ "version": "v6.2.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-client.git",
+ "reference": "297374a399ce6852d5905d92a1351df00bb9dd10"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-client/zipball/297374a399ce6852d5905d92a1351df00bb9dd10",
+ "reference": "297374a399ce6852d5905d92a1351df00bb9dd10",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/log": "^1|^2|^3",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/http-client-contracts": "^3",
+ "symfony/service-contracts": "^1.0|^2|^3"
+ },
+ "provide": {
+ "php-http/async-client-implementation": "*",
+ "php-http/client-implementation": "*",
+ "psr/http-client-implementation": "1.0",
+ "symfony/http-client-implementation": "3.0"
+ },
+ "require-dev": {
+ "amphp/amp": "^2.5",
+ "amphp/http-client": "^4.2.1",
+ "amphp/http-tunnel": "^1.0",
+ "amphp/socket": "^1.1",
+ "guzzlehttp/promises": "^1.4",
+ "nyholm/psr7": "^1.0",
+ "php-http/httplug": "^1.0|^2.0",
+ "php-http/message-factory": "^1.0",
+ "psr/http-client": "^1.0",
+ "symfony/dependency-injection": "^5.4|^6.0",
+ "symfony/http-kernel": "^5.4|^6.0",
+ "symfony/process": "^5.4|^6.0",
+ "symfony/stopwatch": "^5.4|^6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpClient\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "http"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/http-client/tree/v6.2.13"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-07-03T12:13:45+00:00"
+ },
+ {
+ "name": "symfony/http-client-contracts",
+ "version": "v3.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-client-contracts.git",
+ "reference": "75d7043853a42837e68111812f4d964b01e5101c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c",
+ "reference": "75d7043853a42837e68111812f4d964b01e5101c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
+ "branch-alias": {
+ "dev-main": "3.6-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\HttpClient\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to HTTP clients",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-04-29T11:18:49+00:00"
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "v6.1.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "bd1bcfb0eba14de22c4d086c5023e608f37366ed"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/bd1bcfb0eba14de22c4d086c5023e608f37366ed",
+ "reference": "bd1bcfb0eba14de22c4d086c5023e608f37366ed",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.1|^3",
+ "symfony/polyfill-mbstring": "~1.1"
+ },
+ "require-dev": {
+ "predis/predis": "~1.0",
+ "symfony/cache": "^5.4|^6.0",
+ "symfony/dependency-injection": "^5.4|^6.0",
+ "symfony/expression-language": "^5.4|^6.0",
+ "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
+ "symfony/mime": "^5.4|^6.0",
+ "symfony/rate-limiter": "^5.2|^6.0"
+ },
+ "suggest": {
+ "symfony/mime": "To use the file extension guesser"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Defines an object-oriented layer for the HTTP specification",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/http-foundation/tree/v6.1.12"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-01-30T15:43:30+00:00"
+ },
+ {
+ "name": "symfony/mime",
+ "version": "v7.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/mime.git",
+ "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9",
+ "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-intl-idn": "^1.10",
+ "symfony/polyfill-mbstring": "^1.0"
+ },
+ "conflict": {
+ "egulias/email-validator": "~3.0.0",
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/mailer": "<6.4",
+ "symfony/serializer": "<6.4.3|>7.0,<7.0.3"
+ },
+ "require-dev": {
+ "egulias/email-validator": "^2.1.10|^3.1|^4",
+ "league/html-to-markdown": "^5.0",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/serializer": "^6.4.3|^7.0.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Mime\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Allows manipulating MIME messages",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "mime",
+ "mime-type"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/mime/tree/v7.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-02-19T08:51:26+00:00"
+ },
{
"name": "symfony/polyfill-ctype",
"version": "v1.28.0",
@@ -2638,6 +3242,89 @@
],
"time": "2023-01-26T09:26:14+00:00"
},
+ {
+ "name": "symfony/polyfill-intl-idn",
+ "version": "v1.32.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
+ "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+ "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "symfony/polyfill-intl-normalizer": "^1.10"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Trevor Rowbotham",
+ "email": "trevor.rowbotham@pm.me"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "idn",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-10T14:38:51+00:00"
+ },
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.28.0",
@@ -2875,6 +3562,165 @@
],
"time": "2023-01-26T09:26:14+00:00"
},
+ {
+ "name": "symfony/polyfill-php81",
+ "version": "v1.32.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php81.git",
+ "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
+ "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php81\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-09T11:45:10+00:00"
+ },
+ {
+ "name": "symfony/psr-http-message-bridge",
+ "version": "v6.4.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/psr-http-message-bridge.git",
+ "reference": "c9cf83326a1074f83a738fc5320945abf7fb7fec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/c9cf83326a1074f83a738fc5320945abf7fb7fec",
+ "reference": "c9cf83326a1074f83a738fc5320945abf7fb7fec",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/http-message": "^1.0|^2.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0"
+ },
+ "conflict": {
+ "php-http/discovery": "<1.15",
+ "symfony/http-kernel": "<6.2"
+ },
+ "require-dev": {
+ "nyholm/psr7": "^1.1",
+ "php-http/discovery": "^1.15",
+ "psr/log": "^1.1.4|^2|^3",
+ "symfony/browser-kit": "^5.4|^6.0|^7.0",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
+ "symfony/framework-bundle": "^6.2|^7.0",
+ "symfony/http-kernel": "^6.2|^7.0"
+ },
+ "type": "symfony-bridge",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\PsrHttpMessage\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "PSR HTTP message bridge",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr-17",
+ "psr-7"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/psr-http-message-bridge/tree/v6.4.13"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-25T14:18:03+00:00"
+ },
{
"name": "symfony/service-contracts",
"version": "v2.5.2",
@@ -3569,6 +4415,88 @@
],
"time": "2022-03-08T17:03:00+00:00"
},
+ {
+ "name": "w7corp/easywechat",
+ "version": "6.17.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/w7corp/easywechat.git",
+ "reference": "ea6460149b20a0a31d614d18c5c8cbe77414c4ca"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/w7corp/easywechat/zipball/ea6460149b20a0a31d614d18c5c8cbe77414c4ca",
+ "reference": "ea6460149b20a0a31d614d18c5c8cbe77414c4ca",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-fileinfo": "*",
+ "ext-libxml": "*",
+ "ext-openssl": "*",
+ "ext-simplexml": "*",
+ "nyholm/psr7": "^1.5",
+ "nyholm/psr7-server": "^1.0",
+ "overtrue/socialite": "^3.5.4|^4.0.1",
+ "php": ">=8.0.2",
+ "psr/http-client": "^1.0",
+ "psr/simple-cache": "^1.0|^2.0|^3.0",
+ "symfony/cache": "^5.4|^6.0|^7.0",
+ "symfony/http-client": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0",
+ "symfony/mime": "^5.4|^6.0|^7.0",
+ "symfony/polyfill-php81": "^1.25",
+ "symfony/psr-http-message-bridge": "^2.1.2|^6.4.0|^7.1",
+ "thenorthmemory/xml": "^1.0"
+ },
+ "conflict": {
+ "overtrue/wechat": "*"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "^1.0",
+ "laravel/pint": "^1.2",
+ "mikey179/vfsstream": "^1.6",
+ "mockery/mockery": "^1.4.4",
+ "phpstan/phpstan": "^1.0 | ^2",
+ "phpunit/phpunit": "^9.5",
+ "symfony/var-dumper": "^5.2|^6|^7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "EasyWeChat\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "overtrue",
+ "email": "anzhengchao@gmail.com"
+ }
+ ],
+ "description": "微信SDK",
+ "keywords": [
+ "easywechat",
+ "sdk",
+ "wechat",
+ "weixin",
+ "weixin-sdk"
+ ],
+ "support": {
+ "issues": "https://github.com/w7corp/easywechat/issues",
+ "source": "https://github.com/w7corp/easywechat/tree/6.17.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/overtrue",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-19T00:52:30+00:00"
+ },
{
"name": "webman/console",
"version": "v1.2.38",
@@ -3795,7 +4723,7 @@
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
diff --git a/config/middleware.php b/config/middleware.php
index 78cbaee..364a9f6 100644
--- a/config/middleware.php
+++ b/config/middleware.php
@@ -22,5 +22,6 @@ return [
app\admin\middleware\LoginMiddleware::class,
// 权限认证
app\admin\middleware\AuthMiddleware::class,
- ]
-];
\ No newline at end of file
+ ],
+ 'api' => [\app\api\middleware\AuthMiddleware::class],
+];
diff --git a/config/plugin/tinywan/jwt/app.php b/config/plugin/tinywan/jwt/app.php
new file mode 100644
index 0000000..735b24d
--- /dev/null
+++ b/config/plugin/tinywan/jwt/app.php
@@ -0,0 +1,83 @@
+ true,
+ 'jwt' => [
+ /** 算法类型 HS256、HS384、HS512、RS256、RS384、RS512、ES256、ES384、ES512、PS256、PS384、PS512 */
+ 'algorithms' => 'HS256',
+
+ /** access令牌秘钥 */
+ 'access_secret_key' => '2022d3d3LmJq',
+
+ /** access令牌过期时间,单位:秒。默认 2 小时 */
+ 'access_exp' => 86400 * 3,
+
+ /** refresh令牌秘钥 */
+ 'refresh_secret_key' => '2022KTxigxc9o50c',
+
+ /** refresh令牌过期时间,单位:秒。默认 7 天 */
+ 'refresh_exp' => 604800,
+
+ /** refresh 令牌是否禁用,默认不禁用 false */
+ 'refresh_disable' => false,
+
+ /** 令牌签发者 */
+ 'iss' => 'webman.tinywan.cn',
+
+ /** 某个时间点后才能访问,单位秒。(如:30 表示当前时间30秒后才能使用) */
+ 'nbf' => 0,
+
+ /** 时钟偏差冗余时间,单位秒。建议这个余地应该不大于几分钟 */
+ 'leeway' => 60,
+
+ /** 是否允许单设备登录,默认不允许 false */
+ 'is_single_device' => false,
+
+ /** 缓存令牌时间,单位:秒。默认 7 天 */
+ 'cache_token_ttl' => 604800,
+
+ /** 缓存令牌前缀,默认 JWT:TOKEN: */
+ 'cache_token_pre' => 'JWT:TOKEN:',
+
+ /** 缓存刷新令牌前缀,默认 JWT:REFRESH_TOKEN: */
+ 'cache_refresh_token_pre' => 'JWT:REFRESH_TOKEN:',
+
+ /** 用户信息模型 */
+ 'user_model' => function ($uid) {
+ return [];
+ },
+
+ /** 是否支持 get 请求获取令牌 */
+ 'is_support_get_token' => false,
+ /** GET 请求获取令牌请求key */
+ 'is_support_get_token_key' => 'authorization',
+
+ /** access令牌私钥 */
+ 'access_private_key' => << << << <<get('page', 1);
+ return intval($page);
+ }
+
+ public function limit()
+ {
+ $limit = $this->get('limit', 10);
+ return intval(min($limit, 50));
+ }
+
+}
diff --git a/support/auth/Weixin.php b/support/auth/Weixin.php
new file mode 100644
index 0000000..0de54d6
--- /dev/null
+++ b/support/auth/Weixin.php
@@ -0,0 +1,63 @@
+config = [
+ 'app_id' => '',
+ 'secret' => '',
+ 'response_type' => 'array',
+ 'log' => [
+ 'level' => 'debug',
+ 'file' => __DIR__ . '/wechat.log',
+ ],
+ ];
+ $this->app = new Application($this->config);
+ }
+
+ public function appId()
+ {
+ return $this->config['app_id'];
+ }
+
+ public function nickname()
+ {
+ return '微信用户' . time() . rand(1, 100);
+ }
+
+ public function avatar()
+ {
+ return '/image/avatar.jpg';
+ }
+
+ public function login($code)
+ {
+ $result = $this->app->getUtils()->codeToSession($code);
+ if (isset($result['openid'])) {
+ return $result;
+ }
+ throw new BusinessException('登录失败', 500);
+ }
+
+ public function getPhoneNumber($code, $iv, $encryptedData)
+ {
+ $utils = $this->app->getUtils();
+ $response = $utils->codeToSession($code);
+ $session = $utils->decryptSession($response['session_key'], $iv, $encryptedData);
+ if (empty($session['phoneNumber'])) {
+ throw new BusinessException('获取手机号失败', 500);
+ }
+ return $session['phoneNumber'];
+ }
+
+}