From 7809448c371891082171dccb5720a341fe6ba750 Mon Sep 17 00:00:00 2001 From: youda Date: Wed, 25 Jun 2025 18:26:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FFCategoriesController.php | 179 +++++ app/admin/controller/FFProductsController.php | 250 +++++++ app/admin/controller/Upload.php | 2 +- app/admin/route/app.php | 17 + app/admin/view/FFCategories/add.html | 78 ++ app/admin/view/FFCategories/edit.html | 85 +++ app/admin/view/FFCategories/index.html | 179 +++++ app/admin/view/FFProducts/add.html | 438 +++++++++++ app/admin/view/FFProducts/edit.html | 448 +++++++++++ app/admin/view/FFProducts/index.html | 308 ++++++++ app/api/controller/FFOrdersController.php | 707 ++++++++++++++++++ app/api/controller/FFProductsController.php | 260 +++++++ app/api/controller/User.php | 29 + app/api/route/app.php | 27 +- app/common/model/FFCategories.php | 104 +++ app/common/model/FFFavorites.php | 145 ++++ app/common/model/FFOrders.php | 150 ++++ app/common/model/FFProducts.php | 170 +++++ app/common/server/platform/AppPlatform.php | 11 +- .../server/platform/PlatformFactory.php | 2 +- config/menu.php | 8 + 21 files changed, 3592 insertions(+), 5 deletions(-) create mode 100644 app/admin/controller/FFCategoriesController.php create mode 100644 app/admin/controller/FFProductsController.php create mode 100644 app/admin/view/FFCategories/add.html create mode 100644 app/admin/view/FFCategories/edit.html create mode 100644 app/admin/view/FFCategories/index.html create mode 100644 app/admin/view/FFProducts/add.html create mode 100644 app/admin/view/FFProducts/edit.html create mode 100644 app/admin/view/FFProducts/index.html create mode 100644 app/api/controller/FFOrdersController.php create mode 100644 app/api/controller/FFProductsController.php create mode 100644 app/common/model/FFCategories.php create mode 100644 app/common/model/FFFavorites.php create mode 100644 app/common/model/FFOrders.php create mode 100644 app/common/model/FFProducts.php diff --git a/app/admin/controller/FFCategoriesController.php b/app/admin/controller/FFCategoriesController.php new file mode 100644 index 0000000..7f56027 --- /dev/null +++ b/app/admin/controller/FFCategoriesController.php @@ -0,0 +1,179 @@ +isAjax()) { + $limit = input('param.limit', 15); + $page = input('param.page', 1); + $offset = ($page - 1) * $limit; + $category_name = input('param.category_name', ''); + $status = input('param.status', ''); + + $where = []; + if ($category_name) { + $where[] = ['category_name', 'like', "%{$category_name}%"]; + } + if ($status !== '') { + $where[] = ['status', '=', $status]; + } + + $res = FFCategories::where($where) + ->order(['sort_order' => 'asc', 'id' => 'desc']) + ->limit($offset, $limit) + ->select(); + + $total = FFCategories::where($where)->count(); + + return $this->renderTable('获取成功', $total, $res, 0); + } + + return View::fetch('FFCategories/index'); + } + + /** + * 添加商品分类 + */ + public function add() + { + if (request()->isPost()) { + $param = input('post.'); + $validate = $this->validate($param, [ + 'category_name' => 'require', + ]); + + if (true !== $validate) { + return $this->renderError($validate); + } + + // 默认值设置 + if (!isset($param['parent_id'])) { + $param['parent_id'] = 0; + $param['category_level'] = 1; + } else if ($param['parent_id'] > 0) { + // 查询父级分类的等级,并设置当前分类的等级为父级+1 + $parent = FFCategories::where('id', $param['parent_id'])->find(); + if (!$parent) { + return $this->renderError('父级分类不存在'); + } + $param['category_level'] = $parent['category_level'] + 1; + // 分类最多支持3级 + if ($param['category_level'] > 3) { + return $this->renderError('分类最多支持3级'); + } + } + + if (!isset($param['sort_order'])) { + $param['sort_order'] = 0; + } + if (!isset($param['status'])) { + $param['status'] = 1; + } + + $res = FFCategories::create($param); + if ($res) { + return $this->renderSuccess('添加成功', ['url' => (string) url('ff_products')]); + } else { + return $this->renderError('添加失败'); + } + } + + // 获取父级分类列表 + $parentList = FFCategories::where([ + ['category_level', '<', 3], // 只查询1级和2级分类作为父级 + ['status', '=', 1] + ]) + ->order('sort_order', 'asc') + ->select(); + View::assign('parentList', $parentList); + + return View::fetch('FFCategories/add'); + } + + /** + * 编辑商品分类 + */ + public function edit() + { + $id = input('param.id', 0); + $info = FFCategories::where('id', $id)->find(); + if (empty($info)) { + return $this->renderError('数据不存在'); + } + + if (request()->isPost()) { + $param = input('post.'); + $validate = $this->validate($param, [ + 'category_name' => 'require', + ]); + + if (true !== $validate) { + return $this->renderError($validate); + } + + // 不允许修改分类级别和父级分类,因为会影响分类结构 + unset($param['parent_id']); + unset($param['category_level']); + + $res = FFCategories::update($param, ['id' => $id]); + if ($res) { + return $this->renderSuccess('编辑成功', ['url' => (string) url('ff_products')]); + } else { + return $this->renderError('编辑失败'); + } + } + + View::assign('info', $info); + return View::fetch('FFCategories/edit'); + } + + /** + * 修改分类状态 + */ + public function status() + { + $id = input('param.id', 0); + $status = input('param.status', 0); + + $res = FFCategories::update(['status' => $status], ['id' => $id]); + if ($res) { + return $this->renderSuccess('操作成功'); + } else { + return $this->renderError('操作失败'); + } + } + + /** + * 删除分类 + */ + public function del() + { + $id = input('param.id', 0); + + // 检查是否有子分类 + $hasChildren = FFCategories::where('parent_id', $id)->count(); + if ($hasChildren > 0) { + return $this->renderError('该分类下有子分类,无法删除'); + } + + $res = FFCategories::destroy($id); + if ($res) { + return $this->renderSuccess('删除成功'); + } else { + return $this->renderError('删除失败'); + } + } + + + +} \ No newline at end of file diff --git a/app/admin/controller/FFProductsController.php b/app/admin/controller/FFProductsController.php new file mode 100644 index 0000000..8d18802 --- /dev/null +++ b/app/admin/controller/FFProductsController.php @@ -0,0 +1,250 @@ +isAjax()) { + $limit = input('param.limit', 15); + $page = input('param.page', 1); + $offset = ($page - 1) * $limit; + $product_name = input('param.product_name', ''); + $status = input('param.status', ''); + $is_hot = input('param.is_hot', ''); + $is_new = input('param.is_new', ''); + $is_recommend = input('param.is_recommend', ''); + $category_name = input('param.category_name', ''); + + $where = []; + if ($product_name) { + $where[] = ['product_name', 'like', "%{$product_name}%"]; + } + if ($status !== '') { + $where[] = ['status', '=', $status]; + } + if ($is_hot !== '') { + $where[] = ['is_hot', '=', $is_hot]; + } + if ($is_new !== '') { + $where[] = ['is_new', '=', $is_new]; + } + if ($is_recommend !== '') { + $where[] = ['is_recommend', '=', $is_recommend]; + } + if ($category_name) { + $where[] = ['category_name', 'like', "%{$category_name}%"]; + } + + $res = FFProducts::where($where) + ->order('id', 'desc') + ->limit($offset, $limit) + ->select(); + + $total = FFProducts::where($where)->count(); + + return $this->renderTable('获取成功', $total, $res, 0); + } + + return View::fetch('FFProducts/index'); + } + + /** + * 添加商品 + */ + public function add() + { + if (request()->isPost()) { + $param = input('post.'); + $validate = $this->validate($param, [ + 'product_name' => 'require', + 'price' => 'require|float', + 'stock' => 'require|number', + ]); + + if (true !== $validate) { + return $this->renderError($validate); + } + + // 处理多选的分类,转换为逗号分隔的字符串 + if (isset($param['categories']) && is_array($param['categories'])) { + $param['category_name'] = implode(',', $param['categories']); + unset($param['categories']); + } + + // 设置默认值 + if (!isset($param['status'])) { + $param['status'] = 1; + } + if (!isset($param['sales'])) { + $param['sales'] = 0; + } + if (!isset($param['is_hot'])) { + $param['is_hot'] = 0; + } + if (!isset($param['is_new'])) { + $param['is_new'] = 0; + } + if (!isset($param['is_recommend'])) { + $param['is_recommend'] = 0; + } + + $res = FFProducts::create($param); + if ($res) { + return $this->renderSuccess('添加成功', ['url' => (string) url('ff_products')]); + } else { + return $this->renderError('添加失败'); + } + } + + // 获取分类列表 + $categories = FFCategories::where('status', 1) + ->order('sort_order', 'asc') + ->select(); + View::assign('categories', $categories); + + return View::fetch('FFProducts/add'); + } + + /** + * 编辑商品 + */ + public function edit() + { + $id = input('param.id', 0); + $info = FFProducts::where('id', $id)->find(); + if (empty($info)) { + return $this->renderError('数据不存在'); + } + + if (request()->isPost()) { + $param = input('post.'); + $validate = $this->validate($param, [ + 'product_name' => 'require', + 'price' => 'require|float', + 'stock' => 'require|number', + ]); + + if (true !== $validate) { + return $this->renderError($validate); + } + + // 处理多选的分类,转换为逗号分隔的字符串 + if (isset($param['categories']) && is_array($param['categories'])) { + $param['category_name'] = implode(',', $param['categories']); + unset($param['categories']); + } + + $res = FFProducts::update($param, ['id' => $id]); + if ($res) { + return $this->renderSuccess('编辑成功', ['url' => (string) url('ff_products')]); + } else { + return $this->renderError('编辑失败'); + } + } + + // 获取分类列表 + $categories = FFCategories::where('status', 1) + ->order('sort_order', 'asc') + ->select()->toArray(); + + // 将已有的分类名称转为数组 + $selectedCategories = []; + if ($info['category_name']) { + $selectedCategories = explode(',', $info['category_name']); + } + + View::assign('categories', $categories); + View::assign('selectedCategories', $selectedCategories); + View::assign('info', $info); + + return View::fetch('FFProducts/edit'); + } + + /** + * 修改商品状态(上架/下架) + */ + public function status() + { + $id = input('param.id', 0); + $status = input('param.status', 0); + + $res = FFProducts::update(['status' => $status], ['id' => $id]); + if ($res) { + return $this->renderSuccess('操作成功'); + } else { + return $this->renderError('操作失败'); + } + } + + /** + * 修改热销状态 + */ + public function hot() + { + $id = input('param.id', 0); + $is_hot = input('param.is_hot', 0); + + $res = FFProducts::update(['is_hot' => $is_hot], ['id' => $id]); + if ($res) { + return $this->renderSuccess('操作成功'); + } else { + return $this->renderError('操作失败'); + } + } + + /** + * 修改新品状态 + */ + public function new() + { + $id = input('param.id', 0); + $is_new = input('param.is_new', 0); + + $res = FFProducts::update(['is_new' => $is_new], ['id' => $id]); + if ($res) { + return $this->renderSuccess('操作成功'); + } else { + return $this->renderError('操作失败'); + } + } + + /** + * 修改推荐状态 + */ + public function recommend() + { + $id = input('param.id', 0); + $is_recommend = input('param.is_recommend', 0); + + $res = FFProducts::update(['is_recommend' => $is_recommend], ['id' => $id]); + if ($res) { + return $this->renderSuccess('操作成功'); + } else { + return $this->renderError('操作失败'); + } + } + + /** + * 删除商品 + */ + public function del() + { + $id = input('param.id', 0); + $res = FFProducts::destroy($id); + if ($res) { + return $this->renderSuccess('删除成功'); + } else { + return $this->renderError('删除失败'); + } + } +} \ No newline at end of file diff --git a/app/admin/controller/Upload.php b/app/admin/controller/Upload.php index 55c874a..7024819 100755 --- a/app/admin/controller/Upload.php +++ b/app/admin/controller/Upload.php @@ -37,7 +37,7 @@ class Upload extends Base } // 文件格式校验 - $ext = ['jpg', 'png', 'jpeg', 'JPG', 'PNG', 'JPEG', 'gif', 'apk', 'mp3','webp']; + $ext = ['jpg', 'png', 'jpeg', 'JPG', 'PNG', 'JPEG', 'gif', 'apk', 'mp3','webp','avif']; $type = substr($_FILES['file']['name'], strrpos($_FILES['file']['name'], '.') + 1); if (!in_array($type, $ext)) { return $this->renderError("文件格式错误"); diff --git a/app/admin/route/app.php b/app/admin/route/app.php index 6c7c298..2b24297 100755 --- a/app/admin/route/app.php +++ b/app/admin/route/app.php @@ -500,3 +500,20 @@ Route::rule('verification_code', 'VerificationCode/index', 'GET|POST'); #News.php 新闻管理 #============================ Route::rule('news', 'News/index', 'GET|POST'); + +#============================ +#FFProductsController.php商品分类管理 +#============================ +Route::rule('ff_categories', 'FFCategoriesController/index', 'GET|POST'); +Route::rule('ff_categories_add', 'FFCategoriesController/add', 'GET|POST'); +Route::rule('ff_categories_edit', 'FFCategoriesController/edit', 'GET|POST'); +Route::rule('ff_categories_del', 'FFCategoriesController/del', 'POST'); +Route::rule('ff_categories_status', 'FFCategoriesController/status', 'POST'); +Route::rule('ff_products', 'FFProductsController/index', 'GET|POST'); +Route::rule('ff_products_add', 'FFProductsController/add', 'GET|POST'); +Route::rule('ff_products_edit', 'FFProductsController/edit', 'GET|POST'); +Route::rule('ff_products_del', 'FFProductsController/del', 'POST'); +Route::rule('ff_products_status', 'FFProductsController/status', 'POST'); +Route::rule('ff_products_hot', 'FFProductsController/hot', 'POST'); +Route::rule('ff_products_new', 'FFProductsController/new', 'POST'); +Route::rule('ff_products_recommend', 'FFProductsController/recommend', 'POST'); diff --git a/app/admin/view/FFCategories/add.html b/app/admin/view/FFCategories/add.html new file mode 100644 index 0000000..30bc7b6 --- /dev/null +++ b/app/admin/view/FFCategories/add.html @@ -0,0 +1,78 @@ +{include file="Public/header3" /} +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
数值越小越靠前
+
+
+ +
+ +
+ + +
+
+ +
+
+ +
+
+
+{include file="Public/footer" /} + \ No newline at end of file diff --git a/app/admin/view/FFCategories/edit.html b/app/admin/view/FFCategories/edit.html new file mode 100644 index 0000000..25418a4 --- /dev/null +++ b/app/admin/view/FFCategories/edit.html @@ -0,0 +1,85 @@ +{include file="Public/header3" /} +
+ + +
+ +
+ +
+
+ +
+ +
+
{if $info.parent_id == 0}顶级分类{else}父级ID:{$info.parent_id}{/if}
+
为维护分类结构,不允许修改父级分类
+
+
+ +
+ +
+
+ {if $info.category_level == 1}一级分类{elseif $info.category_level == 2}二级分类{else}三级分类{/if} +
+
+
+ +
+ +
+ +
数值越小越靠前
+
+
+ +
+ +
+ + +
+
+ +
+
+ +
+
+
+{include file="Public/footer" /} + \ No newline at end of file diff --git a/app/admin/view/FFCategories/index.html b/app/admin/view/FFCategories/index.html new file mode 100644 index 0000000..3dd95da --- /dev/null +++ b/app/admin/view/FFCategories/index.html @@ -0,0 +1,179 @@ +{include file="Public:header3"/} +
+
+
商品分类管理
+
+
+
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
+
+ + + + + + + + + + +{include file="Public/footer3" /} + \ No newline at end of file diff --git a/app/admin/view/FFProducts/add.html b/app/admin/view/FFProducts/add.html new file mode 100644 index 0000000..416ed32 --- /dev/null +++ b/app/admin/view/FFProducts/add.html @@ -0,0 +1,438 @@ +{include file="Public/header3" /} + + +
+
+ +
+ +
+
+ +
+ +
+ {foreach $categories as $category} + + {/foreach} +
+
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+
+
+
+
+ +
+
+ +
+ + +
+
+
+ +
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+
+ +
+
+
+{include file="Public/footer" /} + + \ No newline at end of file diff --git a/app/admin/view/FFProducts/edit.html b/app/admin/view/FFProducts/edit.html new file mode 100644 index 0000000..d863b9c --- /dev/null +++ b/app/admin/view/FFProducts/edit.html @@ -0,0 +1,448 @@ +{include file="Public/header3" /} + + + + +
+ + +
+ +
+ +
+
+ +
+ +
+ {foreach $categories as $category} + + {/foreach} +
+
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+
+
+
+
+ +
+
+ +
+ + +
+
+
+ +
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +
+
+ +
+
+
+ +{include file="Public/footer" /} + + \ No newline at end of file diff --git a/app/admin/view/FFProducts/index.html b/app/admin/view/FFProducts/index.html new file mode 100644 index 0000000..7dd4822 --- /dev/null +++ b/app/admin/view/FFProducts/index.html @@ -0,0 +1,308 @@ +{include file="Public:header3"/} +
+
+
商品管理
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + +{include file="Public/footer3" /} + \ No newline at end of file diff --git a/app/api/controller/FFOrdersController.php b/app/api/controller/FFOrdersController.php new file mode 100644 index 0000000..9eaebd6 --- /dev/null +++ b/app/api/controller/FFOrdersController.php @@ -0,0 +1,707 @@ +getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + $product_id = $this->request->param('product_id', 0); + $address_id = $this->request->param('address_id', 0); + $coupon_id = $this->request->param('coupon_id', 0); + // $total_price = $this->request->param('total_price', 0); + if (empty($product_id) || empty($address_id)) { + return $this->renderError('缺少必要参数'); + } + $product = FFProducts::where('id', $product_id)->find(); + if (!$product) { + return $this->renderError('商品不存在'); + } + $address = UserAddress::where('id', $address_id)->find(); + if (!$address) { + return $this->renderError('地址不存在'); + } + $coupon = null; + if ($coupon_id > 0) { + $coupon = CouponReceive::where('id', $coupon_id)->find(); + if (!$coupon) { + return $this->renderError('优惠券不存在'); + } + } + //$user, $price, $title, $attach, $pre = "MH_", $pay_type = 1, $client = null + $total_price = $product['price']; + if ($coupon) { + $total_price = $total_price - $coupon['price']; + } + $user = $this->getUser(); + $payRes = PlatformFactory::createPay($user, $total_price, $product['product_name'], 'order_product', 'YS_', 1); + if ($payRes['status'] !== 1) { + return $this->renderError("购买失败,请稍后再试"); + } + //使用优惠卷 + if ($coupon) { + $coupon['status'] = 1; + $coupon->save(); + } + # 订单号 + $order_num = $payRes['data']['order_no']; + $receiver_name = $address['receiver_name']; + $receiver_phone = $address['receiver_phone']; + $receiver_address = $address['detailed_address']; + + # 保存到ff_orders 表 + $orderData = [ + 'order_no' => $order_num, + 'user_id' => $user_id, + 'product_id' => $product_id, + 'total_amount' => $product['price'], + 'payment_amount' => $total_price, + 'discount_amount' => $coupon ? $coupon['price'] : 0, + 'payment_type' => 1, // 假设这里是微信支付 + 'order_status' => 0, // 待支付 + 'pay_status' => 0, // 未支付 + 'shipping_status' => 0, // 未发货 + 'receiver_name' => $receiver_name, + 'receiver_phone' => $receiver_phone, + 'receiver_address' => $receiver_address, + 'source' => 2, // APP来源 + 'create_time' => date('Y-m-d H:i:s') + ]; + + // 将该用户的所有未支付订单状态变成已取消 + \app\common\model\FFOrders::where([ + 'user_id' => $user_id, + 'order_status' => 0, // 待支付 + 'pay_status' => 0 // 未支付 + ])->update([ + 'order_status' => 5, // 已取消 + 'cancel_time' => date('Y-m-d H:i:s') // 取消时间 + ]); + + // 创建订单 + $order = new \app\common\model\FFOrders(); + $result = $order->save($orderData); + + if (!$result) { + return $this->renderError('订单创建失败'); + } + + return $this->renderSuccess('订单创建成功', [ + 'order_no' => $order_num, + 'user_info' => ['is_test' => $user['istest']], + 'payment_data' => $payRes['data']['res'] + ]); + } + + public function orderPaySuccess() + { + $order_no = $this->request->param('order_no', ''); + if (empty($order_no)) { + return $this->renderError('订单号不能为空'); + } + + // 根据订单号查询订单 + $order = \app\common\model\FFOrders::where('order_no', $order_no)->find(); + if (!$order) { + return $this->renderError('订单不存在'); + } + + // 判断订单状态,避免重复处理 + if ($order['pay_status'] == 2) { + return $this->renderSuccess('订单已支付', ['order_no' => $order_no]); + } + + // 查询订单对应的商品信息 + $product_id = $order['product_id']; + $product = FFProducts::where('id', $product_id)->find(); + if (!$product) { + return $this->renderError('商品不存在'); + } + + // 开启事务 + \think\facade\Db::startTrans(); + try { + // 扣减库存 + if ($product['stock'] > 0) { + $product->sales = $product['sales'] - 1; // 增加销量 + $product->save(); + } else { + throw new \Exception('商品库存不足'); + } + + // 更新订单状态 + $order->order_status = 2; // 已支付待发货 + $order->pay_status = 2; // 已支付 + $order->shipping_status = 1; // 未发货 + $order->shipping_company = '京东快递'; // 快递公司 + $order->shipping_no = "TEST_" . time();//TEST_开头 + $order->shipping_time = date('Y-m-d H:i:s'); // 发货时间 + $order->payment_time = date('Y-m-d H:i:s'); // 支付时间 + $order->payment_no = $this->request->param('payment_no', ''); // 支付流水号 + + // 保存订单 + if (!$order->save()) { + throw new \Exception('订单状态更新失败'); + } + + // 提交事务 + \think\facade\Db::commit(); + + return $this->renderSuccess('购买成功', [ + 'order_no' => $order_no, + 'order_status' => $order->order_status, + 'pay_status' => $order->pay_status + ]); + + } catch (\Exception $e) { + // 回滚事务 + \think\facade\Db::rollback(); + return $this->renderError('支付处理失败:' . $e->getMessage()); + } + } + + /** + * 获取订单列表 + * @return \think\Response + */ + public function getOrderList() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收参数 + $status = $this->request->param('status', 0); // 订单状态,0表示全部 + $keyword = $this->request->param('keyword', ''); // 商品标题搜索关键词 + $page = (int) $this->request->param('page', 1); + $limit = (int) $this->request->param('limit', 10); + + // 构建查询条件 + $where = [ + 'user_id' => $user_id, + 'delete_status' => 0 + ]; + + // 初始化查询对象 + $query = \app\common\model\FFOrders::alias('o'); + + // 根据状态筛选 + if ($status > 0) { + if ($status == 4) { + // 当status为4时,查询状态为6和7的订单(申请售后和退款售后成功) + $query = $query->where($where) + ->where('o.order_status', 'in', [6, 7]); + } else { + // 其他状态正常查询 + $query = $query->where($where) + ->where('o.order_status', $status); + } + } else { + // status为0时查询所有订单 + $query = $query->where($where); + } + + // 如果有搜索关键词,则需要联表查询 + if (!empty($keyword)) { + // 通过product_id关联FFProducts表 + $query = $query->join('ff_products p', 'o.product_id = p.id') + ->where('p.product_name', 'like', "%{$keyword}%"); + } + + // 排序方式 - 最新订单在前 + $query = $query->order('o.create_time desc'); + + // 分页查询 + $count = $query->count(); + $list = $query->page($page, $limit)->select(); + + // 处理结果 + $result = []; + foreach ($list as $order) { + // 获取商品信息 + $product = \app\common\model\FFProducts::where('id', $order['product_id'])->find(); + + $item = [ + 'order_id' => $order['order_id'], + 'order_no' => $order['order_no'], + 'product_id' => $product ? $product['id'] : '', // + 'product_cover' => $product ? $product['cover_image'] : '', // 商品封面图 + 'product_title' => $product ? $product['product_name'] : '', // 商品标题 + 'payment_amount' => $order['payment_amount'], // 支付金额 + 'payment_time' => $order['payment_time'] ?: '', // 支付时间 + 'order_status' => $order['order_status'], // 订单状态 + 'order_status_text' => $this->getOrderStatusText($order['order_status']), // 订单状态文本 + 'create_time' => $order['create_time'], // 创建时间 + 'receive_time' => $order['receive_time'] ?: '', // 收货时间 + 'is_invoice' => $order['invoice_title'] == '' ? 0 : 1, // 是否开票 + ]; + + $result[] = $item; + } + + return $this->renderSuccess('获取成功', [ + 'total' => $count, + 'page' => $page, + 'limit' => $limit, + 'list' => $result + ]); + } + + /** + * 获取订单状态文本 + * @param int $status 订单状态 + * @return string 状态文本 + */ + private function getOrderStatusText($status) + { + $statusArr = [ + 0 => '待支付', + 1 => '已支付待发货', + 2 => '已发货', + 3 => '已完成', + 4 => '已关闭', + 5 => '已取消', + 6 => '申请售后', + 7 => '售后结束' + ]; + + return isset($statusArr[$status]) ? $statusArr[$status] : '未知状态'; + } + + /** + * 订单收货接口 + * @return \think\Response + */ + public function orderReceive() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收订单编号参数 + $order_no = $this->request->param('order_no', ''); + if (empty($order_no)) { + return $this->renderError('订单编号不能为空'); + } + + // 查询订单 + $order = \app\common\model\FFOrders::where([ + 'order_no' => $order_no, + 'user_id' => $user_id + ])->find(); + + if (!$order) { + return $this->renderError('订单不存在或不属于当前用户'); + } + + // 判断订单状态是否为已发货 + if ($order['order_status'] != 2) { + return $this->renderError('只有已发货的订单才能确认收货'); + } + + // 更新订单状态和收货时间 + $order->order_status = 3; // 已完成 + $order->receive_time = date('Y-m-d H:i:s'); // 收货时间 + + // 保存订单 + if ($order->save()) { + return $this->renderSuccess('确认收货成功', [ + 'order_no' => $order_no, + 'order_status' => $order->order_status, + 'order_status_text' => $this->getOrderStatusText($order->order_status), + 'receive_time' => $order->receive_time + ]); + } else { + return $this->renderError('确认收货失败'); + } + } + + /** + * 申请售后接口 + * @return \think\Response + */ + public function applyRefund() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收参数 + $order_no = $this->request->param('order_no', ''); + $extend_info = $this->request->param('extend_info', ''); + + if (empty($order_no)) { + return $this->renderError('订单编号不能为空'); + } + + // 查询订单 + $order = \app\common\model\FFOrders::where([ + 'order_no' => $order_no, + 'user_id' => $user_id + ])->find(); + + if (!$order) { + return $this->renderError('订单不存在或不属于当前用户'); + } + + // 判断订单状态是否可申请售后 + if ($order['order_status'] == 0 || $order['order_status'] == 4 || $order['order_status'] == 5 || $order['order_status'] == 6 || $order['order_status'] == 7) { + return $this->renderError('当前订单状态不可申请售后'); + } + + try { + // 将当前订单状态保存到扩展信息中 + $extendData = json_decode($extend_info, true) ?: []; + $extendData['original_status'] = $order['order_status']; + + // 更新订单状态和扩展信息 + $order->order_status = 6; // 申请退款 + $order->extend_info = json_encode($extendData); + + // 保存订单 + if ($order->save()) { + return $this->renderSuccess('申请售后成功', [ + 'order_no' => $order_no, + 'order_status' => $order->order_status, + 'order_status_text' => $this->getOrderStatusText($order->order_status) + ]); + } else { + return $this->renderError('申请售后失败'); + } + } catch (\Exception $e) { + return $this->renderError('申请售后失败:' . $e->getMessage()); + } + } + + /** + * 取消售后接口 + * @return \think\Response + */ + public function cancelRefund() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收参数 + $order_no = $this->request->param('order_no', ''); + + if (empty($order_no)) { + return $this->renderError('订单编号不能为空'); + } + + // 查询订单 + $order = \app\common\model\FFOrders::where([ + 'order_no' => $order_no, + 'user_id' => $user_id + ])->find(); + + if (!$order) { + return $this->renderError('订单不存在或不属于当前用户'); + } + + // 判断订单状态是否为申请退款 + if ($order['order_status'] != 6) { + return $this->renderError('只有申请退款状态的订单才能取消售后'); + } + + try { + // 从扩展信息中读取原始状态 + $extendInfo = $order['extend_info'] ? json_decode($order['extend_info'], true) : []; + $originalStatus = isset($extendInfo['original_status']) ? $extendInfo['original_status'] : 3; // 默认为已完成 + + // 移除原始状态信息 + if (isset($extendInfo['original_status'])) { + unset($extendInfo['original_status']); + } + + // 更新订单状态和扩展信息 + $order->order_status = $originalStatus; + $order->extend_info = !empty($extendInfo) ? json_encode($extendInfo) : ''; + + // 保存订单 + if ($order->save()) { + return $this->renderSuccess('取消售后成功', [ + 'order_no' => $order_no, + 'order_status' => $order->order_status, + 'order_status_text' => $this->getOrderStatusText($order->order_status) + ]); + } else { + return $this->renderError('取消售后失败'); + } + } catch (\Exception $e) { + return $this->renderError('取消售后失败:' . $e->getMessage()); + } + } + + /** + * 删除订单接口 + * @return \think\Response + */ + public function deleteOrder() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收订单编号参数 + $order_no = $this->request->param('order_no', ''); + + if (empty($order_no)) { + return $this->renderError('订单编号不能为空'); + } + + // 查询订单 + $order = \app\common\model\FFOrders::where([ + 'order_no' => $order_no, + 'user_id' => $user_id, + 'delete_status' => 0 // 未删除的订单 + ])->find(); + + if (!$order) { + return $this->renderError('订单不存在或不属于当前用户'); + } + + // 判断订单状态是否可删除 + // 通常只有已完成(3)、已关闭(4)、已取消(5)、退款成功(7)的订单可以删除 + $allowDeleteStatus = [3, 4, 5, 7]; + if (!in_array($order['order_status'], $allowDeleteStatus)) { + return $this->renderError('当前订单状态不允许删除'); + } + + try { + // 更新订单删除状态 + $order->delete_status = 1; // 标记为已删除 + + // 保存订单 + if ($order->save()) { + return $this->renderSuccess('订单删除成功'); + } else { + return $this->renderError('订单删除失败'); + } + } catch (\Exception $e) { + return $this->renderError('订单删除失败:' . $e->getMessage()); + } + } + + /** + * 获取订单详情接口 + * @return \think\Response + */ + public function getOrderDetail() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收订单编号参数 + $order_no = $this->request->param('order_no', ''); + + if (empty($order_no)) { + return $this->renderError('订单编号不能为空'); + } + + // 查询订单 + $order = \app\common\model\FFOrders::where([ + 'order_no' => $order_no, + 'user_id' => $user_id, + 'delete_status' => 0 // 未删除的订单 + ])->find(); + + if (!$order) { + return $this->renderError('订单不存在或不属于当前用户'); + } + + // 查询关联商品 + $product = \app\common\model\FFProducts::where('id', $order['product_id'])->find(); + + // 组装订单详情数据 + $orderDetail = [ + // 商品信息 + 'product_id' => $product ? $product['id'] : '', + 'product_cover' => $product ? $product['cover_image'] : '', + 'product_title' => $product ? $product['product_name'] : '', + 'product_price' => $product ? $product['price'] : 0.00, + + // 订单信息 + 'order_id' => $order['order_id'], + 'order_no' => $order['order_no'], + 'total_amount' => $order['total_amount'], // 订单总金额 + 'payment_amount' => $order['payment_amount'], // 实际支付金额 + 'discount_amount' => $order['discount_amount'], // 优惠金额 + 'shipping_fee' => $order['shipping_fee'], // 运费 + 'order_status' => $order['order_status'], + 'order_status_text' => $this->getOrderStatusText($order['order_status']), + 'pay_status' => $order['pay_status'], + 'payment_type' => $order['payment_type'], // 支付方式 + + // 物流信息 + 'shipping_company' => $order['shipping_company'] ?: '', + 'shipping_no' => $order['shipping_no'] ?: '', + 'create_time' => $order['create_time'], // 下单时间 + 'shipping_time' => $order['shipping_time'] ?: '', // 发货时间 + 'receive_time' => $order['receive_time'] ?: '', // 收货时间 + 'payment_time' => $order['payment_time'] ?: '', // 支付时间 + + // 收货人信息 + 'receiver_name' => $order['receiver_name'], + 'receiver_phone' => $order['receiver_phone'], + 'receiver_address' => $order['receiver_address'], + + // 发票信息 + 'invoice_title' => $order['invoice_title'] ?: '', + 'invoice_content' => $order['invoice_content'] ?: '', + 'invoice_type' => $order['invoice_type'], + 'invoice_type_text' => $order['invoice_type'] == 1 ? '个人' : ($order['invoice_type'] == 2 ? '企业' : ''), + + // 扩展信息 + 'extend_info' => $order['extend_info'] ? json_decode($order['extend_info'], true) : [] + ]; + + return $this->renderSuccess('获取成功', $orderDetail); + } + + /** + * 申请发票接口 + * @return \think\Response + */ + public function applyInvoice() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + // 接收参数 + $order_no = $this->request->param('order_no', ''); + $invoice_title = $this->request->param('invoice_title', ''); + $invoice_content = $this->request->param('invoice_content', ''); + $invoice_type = (int) $this->request->param('invoice_type', 1); // 默认个人 + $user_email = $this->request->param('user_email', ''); // 用户邮箱,不存储 + + // 参数验证 + if (empty($order_no)) { + return $this->renderError('订单编号不能为空'); + } + + if (empty($invoice_title)) { + return $this->renderError('发票抬头不能为空'); + } + + if (empty($invoice_content)) { + return $this->renderError('发票内容不能为空'); + } + + if (!in_array($invoice_type, [1, 2])) { + return $this->renderError('发票类型不正确'); + } + + if (empty($user_email)) { + return $this->renderError('用户邮箱不能为空'); + } + + // 邮箱格式验证 + if (!filter_var($user_email, FILTER_VALIDATE_EMAIL)) { + return $this->renderError('邮箱格式不正确'); + } + + // 查询订单 + $order = \app\common\model\FFOrders::where([ + 'order_no' => $order_no, + 'user_id' => $user_id, + 'delete_status' => 0 // 未删除的订单 + ])->find(); + + if (!$order) { + return $this->renderError('订单不存在或不属于当前用户'); + } + + // 验证订单状态,通常只有已支付的订单才能申请发票 + if ($order['pay_status'] != 2) { // 2表示已支付 + return $this->renderError('只有已支付的订单才能申请发票'); + } + + try { + // 更新订单发票信息 + $order->invoice_title = $invoice_title; + $order->invoice_content = $invoice_content; + $order->invoice_type = $invoice_type; + + // 保存订单 + if ($order->save()) { + return $this->renderSuccess('发票申请成功', true); + } else { + return $this->renderError('发票申请失败'); + } + } catch (\Exception $e) { + return $this->renderError('发票申请失败:' . $e->getMessage()); + } + } + + /** + * 获取用户订单统计数据 + * @return \think\Response + */ + public function getOrderStatistics() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + try { + // 查询条件 - 用户ID和未删除 + $where = [ + 'user_id' => $user_id, + 'delete_status' => 0 + ]; + + // 查询待发货订单数量 - 订单状态为1(已支付待发货) + $waitingShipCount = \app\common\model\FFOrders::where($where) + ->where('order_status', 1) + ->count(); + + // 查询待收货订单数量 - 订单状态为2(已发货) + $waitingReceiveCount = \app\common\model\FFOrders::where($where) + ->where('order_status', 2) + ->count(); + + // 查询已收货订单数量 - 订单状态为3(已完成) + $receivedCount = \app\common\model\FFOrders::where($where) + ->where('order_status', 3) + ->count(); + + // 查询申请售后订单数量 - 订单状态为6(申请售后)和7(售后结束) + $afterSalesCount = \app\common\model\FFOrders::where($where) + ->where('order_status', 'in', [6]) + ->count(); + + // 返回统计结果 + return $this->renderSuccess('获取成功', [ + 'waiting_ship_count' => $waitingShipCount, // 待发货数量 + 'waiting_receive_count' => $waitingReceiveCount, // 待收货数量 + 'received_count' => $receivedCount, // 已收货数量 + 'after_sales_count' => $afterSalesCount // 申请售后数量 + ]); + } catch (\Exception $e) { + return $this->renderError('获取订单统计数据失败:' . $e->getMessage()); + } + } +} diff --git a/app/api/controller/FFProductsController.php b/app/api/controller/FFProductsController.php new file mode 100644 index 0000000..14b63d9 --- /dev/null +++ b/app/api/controller/FFProductsController.php @@ -0,0 +1,260 @@ + + field('id,product_name as title,cover_image as image,price,stock,sales') + ->select()->toArray(); + return $this->renderSuccess('', $bannerList); + } + + public function getProductList() + { + $page = intval($this->request->param('page', 1)); + $limit = intval($this->request->param('limit', 10)); + $title = $this->request->param('title', ''); + $productData = FFProducts::where('is_hot', '=', 0); + if ($title) { + $productData->where('product_name', 'like', '%' . $title . '%'); + } + $list = $productData-> + field('id,product_name as title,cover_image as image,price,stock,sales') + ->order(['is_new' => 'desc', 'id' => 'desc']) + ->page($page, $limit) + ->select()->toArray(); + + return $this->renderSuccess('', $list); + } + + public function getProductDetail() + { + $id = $this->request->param('id', 0); + $productDetail = FFProducts::where('id', '=', $id) + ->field('id,product_name as title,cover_image as image,price,stock,sales,product_desc,detail_image1,detail_image2,detail_image3,detail_image4,detail_html,is_hot,is_new,is_recommend')->find(); + if (!$productDetail) { + return $this->renderError('商品不存在'); + } + $productDetail['detail_image'] = [ + $productDetail['detail_image1'], + $productDetail['detail_image2'], + $productDetail['detail_image3'], + $productDetail['detail_image4'] + ]; + $productDetail['detail_image'] = array_filter($productDetail['detail_image'], function ($value) { + return !empty($value); + }); + unset( + $productDetail['detail_image1'], + $productDetail['detail_image2'], + $productDetail['detail_image3'], + $productDetail['detail_image4'] + ); + if ($this->getUserId() > 0) { + $productDetail['is_favorite'] = FFFavorites::isFavorite($this->getUserId(), $id); + } + + return $this->renderSuccess('', $productDetail); + } + + public function PayByOrder() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + $productId = $this->request->param('product_id', 0); + $productDetail = FFProducts::where('id', '=', $productId)->find(); + if (!$productDetail) { + return $this->renderError('商品不存在'); + } + if ($productDetail['sales'] <= 0) { + return $this->renderError('库存不足'); + } + + // 查询默认地址 + $address = UserAddress::where('user_id', $user_id) + ->where('is_default', 1) + ->where('is_deleted', 0) + ->field('id,receiver_name,receiver_phone,detailed_address,is_default') + ->find(); + + if (!$address) { + // 如果没有默认地址,返回最新添加的一条 + $address = UserAddress::where('user_id', $user_id) + ->where('is_deleted', 0) + ->field('id,receiver_name,receiver_phone,detailed_address,is_default') + ->order('id', 'desc') + ->find(); + } + $whe = 'user_id=' . $user_id . ' and status=0 and man_price<=' . $productDetail['price']; + $coupon = CouponReceive::where($whe) + ->field('id,title,man_price,price,end_time,status') + ->select()->toArray(); + $order = [ + 'product_id' => $productId, + 'title' => $productDetail['product_name'], + 'image' => $productDetail['cover_image'], + 'price' => $productDetail['price'], + 'coupon' => $coupon, + 'default_address' => $address, + ]; + return $this->renderSuccess('', $order); + } + + /** + * 获取用户收藏商品列表 + * @return \think\Response + */ + public function getFavoriteList() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + $page = intval($this->request->param('page', 1)); + $limit = intval($this->request->param('limit', 10)); + + // 使用模型静态方法获取收藏列表 + $favoriteList = FFFavorites::getUserFavoriteList($user_id, $page, $limit); + + // 格式化数据 + $result = []; + foreach ($favoriteList as $item) { + if (isset($item['product']) && $item['product']) { + $result[] = [ + 'id' => $item['product']['id'], + 'title' => $item['product']['product_name'], + 'image' => $item['product']['cover_image'], + 'price' => $item['product']['price'], + 'stock' => $item['product']['stock'], + 'sales' => $item['product']['sales'], + 'favorite_time' => $item['create_time'] + ]; + } + } + + return $this->renderSuccess('', $result); + } + + /** + * 添加商品收藏 + * @return \think\Response + */ + public function addFavorite() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + $product_id = intval($this->request->param('product_id', 0)); + if (!$product_id) { + return $this->renderError('商品ID不能为空'); + } + + // 检查商品是否存在 + $product = FFProducts::where('id', $product_id)->find(); + if (!$product) { + return $this->renderError('商品不存在'); + } + + // 使用模型静态方法添加收藏 + $result = FFFavorites::addFavorite($user_id, $product_id); + + return $this->renderSuccess('收藏成功'); + } + + /** + * 取消商品收藏 + * @return \think\Response + */ + public function cancelFavorite() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + $product_id = intval($this->request->param('product_id', 0)); + if (!$product_id) { + return $this->renderError('商品ID不能为空'); + } + + // 使用模型静态方法取消收藏 + $result = FFFavorites::cancelFavorite($user_id, $product_id); + + if ($result) { + return $this->renderSuccess('取消收藏成功'); + } else { + return $this->renderError('取消收藏失败'); + } + } + + /** + * 批量取消收藏 + * @return \think\Response + */ + public function batchCancelFavorite() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + $product_ids = $this->request->param('product_ids'); + if (empty($product_ids)) { + return $this->renderError('商品ID不能为空'); + } + + // 转换为数组 + if (!is_array($product_ids)) { + $product_ids = explode(',', $product_ids); + } + + // 批量取消收藏 + $result = FFFavorites::batchCancelFavorite($user_id, $product_ids); + + if ($result) { + return $this->renderSuccess('批量取消收藏成功'); + } else { + return $this->renderError('批量取消收藏失败'); + } + } + + /** + * 检查商品是否已收藏 + * @return \think\Response + */ + public function checkIsFavorite() + { + $user_id = $this->getUserId(); + if (!$user_id) { + return $this->renderError('请先登录'); + } + + $product_id = intval($this->request->param('product_id', 0)); + if (!$product_id) { + return $this->renderError('商品ID不能为空'); + } + + // 检查是否已收藏 + $isFavorite = FFFavorites::isFavorite($user_id, $product_id); + + return $this->renderSuccess('', ['is_favorite' => $isFavorite ? true : false]); + } +} diff --git a/app/api/controller/User.php b/app/api/controller/User.php index 725b1ec..92dcd57 100755 --- a/app/api/controller/User.php +++ b/app/api/controller/User.php @@ -1294,6 +1294,35 @@ class User extends Base return $this->renderSuccess("请求成功", $userinfo); } + /** + * 我的 + */ + public function userInfo2(Request $request) + { + $user_id = $this->getuserid(); + if ($user_id == 0) { + return $this->renderError("未登录"); + } + $user = Usermodel::where('id', '=', $user_id)->find(); + if (!$user) { + return $this->renderError("用户不存在"); + } + $userinfo['id'] = $user['id']; + $userinfo['mobile_is'] = $user['mobile'] ? 1 : 0; + $userinfo['nickname'] = $user['nickname']; + $userinfo['userIcon'] = imageUrl($user['headimg']); + $userinfo['mobile'] = $user['mobile'] ? substr_replace($user['mobile'], '****', 3, 4) : ''; + $userinfo['money'] = $user['money'];//钻石 + $userinfo['money2'] = $user['money2'];//达达券 + $userinfo['integral'] = $user['integral'];//UU币 + $userinfo['uid'] = $user['uid'] ? $user['uid'] : $user['id']; + $day = floor(abs(time() - $user['addtime']) / 86400); + $userinfo['day'] = $day; + $userinfo['pid'] = $user['pid']; + return $this->renderSuccess("请求成功", $userinfo); + } + + /** * 绑定邀请码 */ diff --git a/app/api/route/app.php b/app/api/route/app.php index 0d1cb69..3893f89 100755 --- a/app/api/route/app.php +++ b/app/api/route/app.php @@ -35,7 +35,8 @@ Route::any('getAgreement', 'Index/getDanye'); #User.php个人中心 #============================ Route::any('user', 'User/user'); -Route::any('userInfo', 'User/userInfo'); +Route::any('userInfo', 'User/userInfo2'); +Route::any('get_userInfo', 'User/userInfo'); Route::any('update_userinfo', 'User/update_userinfo'); Route::any('vip_list', 'User/vip_list'); Route::any('profitIntegral', 'User/profitIntegral'); @@ -241,6 +242,30 @@ Route::any('get_follow_news_list', 'News/getFollowNewsList'); Route::any('user_favorite_news', 'News/addFavorite'); Route::any('user_cancel_favorite_news', 'News/cancelFavorite'); +#============================ +# 商品管理 +#============================ +Route::any('get_banner_list', 'FFProductsController/getBannerList'); +Route::any('get_product_list', 'FFProductsController/getProductList'); +Route::any('get_product_detail', 'FFProductsController/getProductDetail'); +Route::any('pay_by_order', 'FFProductsController/PayByOrder'); +Route::any('get_favorite_list', 'FFProductsController/getFavoriteList'); +Route::any('add_favorite', 'FFProductsController/addFavorite'); +Route::any('cancel_favorite', 'FFProductsController/cancelFavorite'); +Route::any('batch_cancel_favorite', 'FFProductsController/batchCancelFavorite'); +Route::any('check_is_favorite', 'FFProductsController/checkIsFavorite'); +Route::any('pay_by_create_order', 'FFOrdersController/createOrder'); +Route::any('order_pay_success', 'FFOrdersController/orderPaySuccess'); +Route::any('get_order_list', 'FFOrdersController/getOrderList'); +Route::any('order_receive', 'FFOrdersController/orderReceive'); +Route::any('apply_refund', 'FFOrdersController/applyRefund'); +Route::any('cancel_refund', 'FFOrdersController/cancelRefund'); +Route::any('delete_order', 'FFOrdersController/deleteOrder'); +Route::any('get_order_detail', 'FFOrdersController/getOrderDetail'); +Route::any('apply_invoice', 'FFOrdersController/applyInvoice'); +Route::any('get_order_statistics', 'FFOrdersController/getOrderStatistics'); + + #============================APP使用的路由 ============================# Route::any('V5Vx6qHOM5Ks9HqH', 'Login/login'); Route::any('jaqXJ27mqJMfwT7X', 'Login/mobileLogin'); diff --git a/app/common/model/FFCategories.php b/app/common/model/FFCategories.php new file mode 100644 index 0000000..9669414 --- /dev/null +++ b/app/common/model/FFCategories.php @@ -0,0 +1,104 @@ +field($field) + ->order($order) + ->paginate(['list_rows' => $pageSize, 'query' => request()->param()]); + $page = $list->render(); + $data['list'] = $list->toArray()['data']; + $data['count'] = $list->total(); + $data['page'] = $page; + return $data; + } + + /** + * 获取所有列表(不分页) + * @param array $where 查询条件 + * @param string $field 查询字段 + * @param string $order 排序规则 + * @param string $limit 限制条数 + * @return \think\Collection + */ + public static function getAllList($where = [], $field = '*', $order = 'sort_order asc', $limit = '0') + { + $data = self::where($where) + ->field($field) + ->order($order) + ->limit($limit) + ->select(); + return $data; + } + + /** + * 获取单条数据 + * @param array $where 查询条件 + * @param string $field 查询字段 + * @return array|Model|null + */ + public static function getInfo($where = [], $field = '*') + { + $data = self::where($where) + ->field($field) + ->find(); + return $data; + } + + /** + * 获取树形结构分类数据 + * @param int $parentId 父级ID + * @param array $where 额外查询条件 + * @return array + */ + public static function getTreeList($parentId = 0, $where = []) + { + $where[] = ['status', '=', 1]; + $allCategories = self::getAllList($where)->toArray(); + return self::buildTree($allCategories, $parentId); + } + + /** + * 构建树形结构 + * @param array $elements 所有元素 + * @param int $parentId 父级ID + * @return array + */ + protected static function buildTree(array $elements, $parentId = 0) + { + $branch = []; + foreach ($elements as $element) { + if ($element['parent_id'] == $parentId) { + $children = self::buildTree($elements, $element['id']); + if ($children) { + $element['children'] = $children; + } + $branch[] = $element; + } + } + return $branch; + } +} \ No newline at end of file diff --git a/app/common/model/FFFavorites.php b/app/common/model/FFFavorites.php new file mode 100644 index 0000000..399804d --- /dev/null +++ b/app/common/model/FFFavorites.php @@ -0,0 +1,145 @@ +belongsTo('FFProducts', 'product_id', 'id'); + } + + /** + * 查询用户是否收藏了指定商品 + * @param int $userId 用户ID + * @param int $productId 商品ID + * @return bool|array false表示未收藏,array表示收藏信息 + */ + public static function isFavorite($userId, $productId) + { + $where = [ + 'user_id' => $userId, + 'product_id' => $productId, + ]; + + $favorite = self::where($where)->find(); + + return $favorite ? $favorite->toArray() : false; + } + + /** + * 添加收藏 + * @param int $userId 用户ID + * @param int $productId 商品ID + * @return bool|array 收藏结果 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public static function addFavorite($userId, $productId) + { + // 检查是否已收藏 + $favorite = self::where([ + 'user_id' => $userId, + 'product_id' => $productId, + ])->find(); + + if ($favorite) { + // 已收藏,返回已存在 + return $favorite->toArray(); + } + + // 新增收藏 + $model = new self(); + $model->user_id = $userId; + $model->product_id = $productId; + $model->save(); + + return $model->toArray(); + } + + /** + * 取消收藏 + * @param int $userId 用户ID + * @param int $productId 商品ID + * @return bool 取消结果 + */ + public static function cancelFavorite($userId, $productId) + { + return self::where([ + 'user_id' => $userId, + 'product_id' => $productId, + ])->delete(); + } + + /** + * 获取用户收藏列表 + * @param int $userId 用户ID + * @param int $page 页码 + * @param int $limit 每页条数 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public static function getUserFavoriteList($userId, $page = 1, $limit = 10) + { + $list = self::where('user_id', $userId) + ->with(['product']) + ->page($page, $limit) + ->order('create_time', 'desc') + ->select(); + + return $list ? $list->toArray() : []; + } + + /** + * 获取商品收藏数量 + * @param int $productId 商品ID + * @return int 收藏数量 + */ + public static function getProductFavoriteCount($productId) + { + return self::where('product_id', $productId)->count(); + } + + /** + * 批量取消收藏 + * @param int $userId 用户ID + * @param array $productIds 商品ID数组 + * @return int 影响行数 + */ + public static function batchCancelFavorite($userId, $productIds) + { + return self::where('user_id', $userId) + ->whereIn('product_id', $productIds) + ->delete(); + } + + /** + * 关联用户表 + * @return \think\model\relation\HasOne + */ + public function user() + { + return $this->hasOne(User::class, 'id', 'user_id'); + } +} \ No newline at end of file diff --git a/app/common/model/FFOrders.php b/app/common/model/FFOrders.php new file mode 100644 index 0000000..415ac5c --- /dev/null +++ b/app/common/model/FFOrders.php @@ -0,0 +1,150 @@ +field($field) + ->order($order) + ->paginate(['list_rows' => $pageSize, 'query' => request()->param()]); + $page = $list->render(); + $data['list'] = $list->toArray()['data']; + $data['count'] = $list->total(); + $data['last_page'] = $list->toArray()['last_page']; + $data['page'] = $page; + return $data; + } + + /** + * 获取列表 不分页 + */ + public static function getAllList($where = [], $field = '*', $order = 'order_id desc', $limit = '0') + { + $data = self::where($where) + ->field($field) + ->order($order) + ->limit($limit) + ->select(); + return $data; + } + + /** + * 获取单条数据 + */ + public static function getInfo($where = [], $field = '*') + { + $data = self::where($where) + ->field($field) + ->find(); + return $data; + } + + /** + * 获取关联用户信息 + */ + public function getUserInfoAttr($value, $data) + { + $user_info = User::field('nickname,headimg,mobile')->where(['id' => $data['user_id']])->find(); + return $user_info; + } + + /** + * 订单状态获取器 + */ + public function getOrderStatusTextAttr($value, $data) + { + $status = [ + 0 => '待支付', + 1 => '已支付待发货', + 2 => '已发货', + 3 => '已完成', + 4 => '已关闭', + 5 => '已取消' + ]; + return isset($status[$data['order_status']]) ? $status[$data['order_status']] : '未知状态'; + } + + /** + * 支付状态获取器 + */ + public function getPayStatusTextAttr($value, $data) + { + $status = [ + 0 => '未支付', + 1 => '支付中', + 2 => '已支付' + ]; + return isset($status[$data['pay_status']]) ? $status[$data['pay_status']] : '未知状态'; + } + + /** + * 配送状态获取器 + */ + public function getShippingStatusTextAttr($value, $data) + { + $status = [ + 0 => '未发货', + 1 => '已发货', + 2 => '已收货' + ]; + return isset($status[$data['shipping_status']]) ? $status[$data['shipping_status']] : '未知状态'; + } + + /** + * 支付方式获取器 + */ + public function getPaymentTypeTextAttr($value, $data) + { + $types = [ + 1 => '支付宝', + 2 => '微信', + 3 => '银联' + ]; + return isset($types[$data['payment_type']]) ? $types[$data['payment_type']] : '未知方式'; + } + + /** + * 订单来源获取器 + */ + public function getSourceTextAttr($value, $data) + { + $sources = [ + 1 => 'PC', + 2 => 'APP', + 3 => '小程序', + 4 => 'H5' + ]; + return isset($sources[$data['source']]) ? $sources[$data['source']] : '未知来源'; + } + + /** + * 发票类型获取器 + */ + public function getInvoiceTypeTextAttr($value, $data) + { + if (empty($data['invoice_type'])) { + return ''; + } + $types = [ + 1 => '个人', + 2 => '企业' + ]; + return isset($types[$data['invoice_type']]) ? $types[$data['invoice_type']] : '未知类型'; + } +} \ No newline at end of file diff --git a/app/common/model/FFProducts.php b/app/common/model/FFProducts.php new file mode 100644 index 0000000..8c8559c --- /dev/null +++ b/app/common/model/FFProducts.php @@ -0,0 +1,170 @@ +field($field) + ->order($order) + ->paginate(['list_rows' => $pageSize, 'query' => request()->param()]); + $page = $list->render(); + $data['list'] = $list->toArray()['data']; + $data['count'] = $list->total(); + $data['page'] = $page; + return $data; + } + + /** + * 获取所有列表(不分页) + * @param array $where 查询条件 + * @param string $field 查询字段 + * @param string $order 排序规则 + * @param string $limit 限制条数 + * @return \think\Collection + */ + public static function getAllList($where = [], $field = '*', $order = 'create_time desc', $limit = '0') + { + $data = self::where($where) + ->field($field) + ->order($order) + ->limit($limit) + ->select(); + return $data; + } + + /** + * 获取单条数据 + * @param array $where 查询条件 + * @param string $field 查询字段 + * @return array|Model|null + */ + public static function getInfo($where = [], $field = '*') + { + $data = self::where($where) + ->field($field) + ->find(); + return $data; + } + + /** + * 获取热销商品 + */ + public static function getHotProducts($limit = 10, $field = '*') + { + return self::where('status', 1) + ->where('is_hot', 1) + ->field($field) + ->order('sales desc') + ->limit($limit) + ->select(); + } + + /** + * 获取新品商品 + */ + public static function getNewProducts($limit = 10, $field = '*') + { + return self::where('status', 1) + ->where('is_new', 1) + ->field($field) + ->order('create_time desc') + ->limit($limit) + ->select(); + } + + /** + * 获取推荐商品 + */ + public static function getRecommendProducts($limit = 10, $field = '*') + { + return self::where('status', 1) + ->where('is_recommend', 1) + ->field($field) + ->order('create_time desc') + ->limit($limit) + ->select(); + } + + /** + * 根据分类名称获取商品 + * @param string $categoryName 分类名称 + * @param int $limit 限制条数 + * @param string $field 查询字段 + * @return \think\Collection + */ + public static function getProductsByCategory($categoryName, $limit = 10, $field = '*') + { + return self::where('status', 1) + ->where('category_name', 'like', "%{$categoryName}%") + ->field($field) + ->order('create_time desc') + ->limit($limit) + ->select(); + } + + /** + * 搜索商品 + */ + public static function searchProducts($keyword, $field = '*', $pageSize = 15) + { + return self::where('status', 1) + ->where(function ($query) use ($keyword) { + $query->where('product_name', 'like', "%{$keyword}%") + ->whereOr('product_desc', 'like', "%{$keyword}%") + ->whereOr('category_name', 'like', "%{$keyword}%"); + }) + ->field($field) + ->order('create_time desc') + ->paginate(['list_rows' => $pageSize, 'query' => request()->param()]); + } + + /** + * 更新库存 + * @param int $id 商品ID + * @param int $num 减少的数量 + * @return bool + */ + public static function updateStock($id, $num) + { + return self::where('id', $id) + ->where('stock', '>=', $num) + ->dec('stock', $num) + ->inc('sales', $num) + ->update(); + } + + /** + * 根据条件获取商品列表并按价格排序 + * @param array $where 查询条件 + * @param string $order 排序规则 asc-升序 desc-降序 + * @param int $pageSize 每页数量 + * @return array + */ + public static function getListByPrice($where = [], $order = 'asc', $pageSize = 15) + { + $orderRule = $order == 'asc' ? 'price asc' : 'price desc'; + return self::getList($where, '*', $orderRule, $pageSize); + } +} \ No newline at end of file diff --git a/app/common/server/platform/AppPlatform.php b/app/common/server/platform/AppPlatform.php index f3f8df1..cc93c93 100644 --- a/app/common/server/platform/AppPlatform.php +++ b/app/common/server/platform/AppPlatform.php @@ -35,12 +35,19 @@ class AppPlatform extends BasePlatform $versionNumber = (int) preg_replace('/[^0-9]/', '', $version); $config = [ 'isWebPay' => false, - 'isCheck' => false, + 'buildVersion' => '106', 'version' => '1.0.0', + 'userAgreement' => "https://zfunbox.cn?_p=cb20xad0e35094521ae46a1d1fb0ddd1&time=" . time() ]; + $is_env_test = EnvHelper::getIsTest(); + if ($is_env_test) { + $config['userAgreement'] = "https://testweb.zfunbox.cn?_p=cb20xad0e35094521ae46a1d1fb0ddd1&time=" . time(); + } $configVersion = (int) preg_replace('/[^0-9]/', '', $config['version']); if ($versionNumber >= $configVersion) { - $config['isCheck'] = true; + $config['buildVersion'] = '105'; + // $config['isCheck'] = true; + $config['userAgreement'] = "https://zfunbox.cn/pages/guize/guize?type=4"; } return $config; } diff --git a/app/common/server/platform/PlatformFactory.php b/app/common/server/platform/PlatformFactory.php index d76475a..af4b894 100644 --- a/app/common/server/platform/PlatformFactory.php +++ b/app/common/server/platform/PlatformFactory.php @@ -25,7 +25,7 @@ class PlatformFactory if ($client == "WEB_APP") { return new H5Platform(); } - if ($client == "APP_ANDROID") { + if ($client == "APP_ANDROID" || $client == "WEB_APP_ANDROID") { return new AppPlatform(); } if ($client == "APP_IOS") { diff --git a/config/menu.php b/config/menu.php index 017d129..063fd99 100755 --- a/config/menu.php +++ b/config/menu.php @@ -224,6 +224,14 @@ return [ 'url' => '/admin/news', 'name' => '新闻列表', ], + [ + 'url' => '/admin/ff_categories', + 'name' => '商品分类管理', + ], + [ + 'url' => '/admin/ff_products', + 'name' => '商品列表', + ], ], ], [