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" /}
+
+{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" /}
+
+
+
+{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" /}
+
+
+
+
+
+
+{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' => '商品列表',
+ ],
],
],
[