|
|
@@ -0,0 +1,780 @@
|
|
|
+<?php
|
|
|
+/**
|
|
|
+ * 套餐管理控制器
|
|
|
+ */
|
|
|
+
|
|
|
+namespace app\admin\controller\package;
|
|
|
+
|
|
|
+use app\common\controller\Backend;
|
|
|
+use think\facade\Db;
|
|
|
+use think\facade\Validate;
|
|
|
+
|
|
|
+class Package extends Backend
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 套餐列表
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function index()
|
|
|
+ {
|
|
|
+ $where = [];
|
|
|
+
|
|
|
+ // 套餐名称搜索
|
|
|
+ if (!empty($this->request->get('name'))) {
|
|
|
+ $name = $this->request->get('name');
|
|
|
+ $where[] = ['p.name', 'like', '%' . $name . '%'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 套餐类型筛选
|
|
|
+ if (!empty($this->request->get('type'))) {
|
|
|
+ $type = $this->request->get('type');
|
|
|
+ $where['p.type'] = $type;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 状态筛选
|
|
|
+ if (!empty($this->request->get('status'))) {
|
|
|
+ $status = $this->request->get('status');
|
|
|
+ $where['p.status'] = $status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序
|
|
|
+ $order = [];
|
|
|
+ if (!empty($this->request->get('order'))) {
|
|
|
+ $order_a = $this->request->get('order');
|
|
|
+ $order_a = explode(',', $order_a);
|
|
|
+ $order[$order_a[0]] = $order_a[1];
|
|
|
+ } else {
|
|
|
+ $order['p.sort'] = 'asc';
|
|
|
+ $order['p.id'] = 'desc';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 分页
|
|
|
+ $page = $this->request->get('page', 1);
|
|
|
+ $limit = $this->request->get('limit', 20);
|
|
|
+
|
|
|
+ // 查询数据(统计规格数量和已售总数)
|
|
|
+ $specCountSubQuery = Db::name('package_price')
|
|
|
+ ->field('package_id, COUNT(*) as spec_count, SUM(sold_count) as total_sold')
|
|
|
+ ->where('status', 1)
|
|
|
+ ->group('package_id')
|
|
|
+ ->buildSql();
|
|
|
+
|
|
|
+ $packageList = Db::name('package')
|
|
|
+ ->alias('p')
|
|
|
+ ->leftJoin([$specCountSubQuery => 'sc'], 'p.id = sc.package_id')
|
|
|
+ ->field('p.*, IFNULL(sc.spec_count, 0) as spec_count, IFNULL(sc.total_sold, 0) as total_sold')
|
|
|
+ ->where($where)
|
|
|
+ ->order($order)
|
|
|
+ ->paginate([
|
|
|
+ 'list_rows' => $limit,
|
|
|
+ 'page' => $page
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 转换功能特性字段
|
|
|
+ $list = $packageList->items();
|
|
|
+ foreach ($list as &$item) {
|
|
|
+ if (!empty($item['features'])) {
|
|
|
+ $item['features'] = json_decode($item['features'], true);
|
|
|
+ } else {
|
|
|
+ $item['features'] = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->success('查询成功', [
|
|
|
+ 'list' => $list,
|
|
|
+ 'total' => $packageList->total()
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增/编辑套餐
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function edit()
|
|
|
+ {
|
|
|
+ $id = $this->request->post('id');
|
|
|
+ $name = $this->request->post('name');
|
|
|
+ $type = $this->request->post('type', 1);
|
|
|
+ $description = $this->request->post('description', '');
|
|
|
+ $features = $this->request->post('features', []);
|
|
|
+ $sort = $this->request->post('sort', 0);
|
|
|
+ $status = $this->request->post('status', 1);
|
|
|
+
|
|
|
+ if (empty($name)) {
|
|
|
+ $this->error(__('套餐名称不能为空'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证套餐名称是否已存在(编辑时排除自己)
|
|
|
+ $checkName = Db::name('package')
|
|
|
+ ->where('name', $name);
|
|
|
+
|
|
|
+ if (!empty($id)) {
|
|
|
+ $checkName->where('id', '<>', $id);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($checkName->find()) {
|
|
|
+ $this->error(__('套餐名称已存在'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理功能特性字段
|
|
|
+ if (!is_array($features)) {
|
|
|
+ $features = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ $data = [
|
|
|
+ 'name' => $name,
|
|
|
+ 'type' => $type,
|
|
|
+ 'description' => $description,
|
|
|
+ 'features' => json_encode($features, JSON_UNESCAPED_UNICODE),
|
|
|
+ 'sort' => $sort,
|
|
|
+ 'status' => $status,
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
+ ];
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!empty($id)) {
|
|
|
+ // 编辑
|
|
|
+ $packageInfo = Db::name('package')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->find();
|
|
|
+
|
|
|
+ if (!$packageInfo) {
|
|
|
+ $this->error(__('套餐不存在'));
|
|
|
+ }
|
|
|
+
|
|
|
+ $result = Db::name('package')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->update($data);
|
|
|
+ $message = '编辑成功';
|
|
|
+ } else {
|
|
|
+ // 新增
|
|
|
+ $data['create_time'] = date('Y-m-d H:i:s');
|
|
|
+ $result = Db::name('package')
|
|
|
+ ->insert($data);
|
|
|
+ $id = Db::name('package')->getLastInsID();
|
|
|
+ $message = '新增成功';
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $this->success($message, ['id' => $id]);
|
|
|
+ } else {
|
|
|
+ $this->error(__('操作失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->error('操作失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除套餐
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function delete()
|
|
|
+ {
|
|
|
+ $id = $this->request->post('id');
|
|
|
+
|
|
|
+ if (empty($id)) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有规格存在
|
|
|
+ $hasSpec = Db::name('package_price')
|
|
|
+ ->where('package_id', $id)
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ if ($hasSpec > 0) {
|
|
|
+ $this->error(__('该套餐下有关联的规格,请先删除规格'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有用户购买记录(如果user_package表存在)
|
|
|
+ try {
|
|
|
+ $hasUserPackage = Db::name('user_package')
|
|
|
+ ->where('package_id', $id)
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ if ($hasUserPackage > 0) {
|
|
|
+ $this->error(__('该套餐已有用户购买记录,不能删除'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 表不存在,跳过检查
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有企业购买记录(如果company_package表存在)
|
|
|
+ try {
|
|
|
+ $hasCompanyPackage = Db::name('company_package')
|
|
|
+ ->where('package_id', $id)
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ if ($hasCompanyPackage > 0) {
|
|
|
+ $this->error(__('该套餐已有企业购买记录,不能删除'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 表不存在,跳过检查
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $result = Db::name('package')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->delete();
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $this->success('删除成功');
|
|
|
+ } else {
|
|
|
+ $this->error(__('删除失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->error('删除失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 套餐详情
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function detail()
|
|
|
+ {
|
|
|
+ $id = $this->request->get('id');
|
|
|
+
|
|
|
+ if (empty($id)) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取套餐基础信息
|
|
|
+ $packageInfo = Db::name('package')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->find();
|
|
|
+
|
|
|
+ if (!$packageInfo) {
|
|
|
+ $this->error(__('套餐不存在'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理功能特性字段
|
|
|
+ if (!empty($packageInfo['features'])) {
|
|
|
+ $packageInfo['features'] = json_decode($packageInfo['features'], true);
|
|
|
+ } else {
|
|
|
+ $packageInfo['features'] = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取套餐规格列表
|
|
|
+ $specList = Db::name('package_price')
|
|
|
+ ->where('package_id', $id)
|
|
|
+ ->order('sort', 'asc')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ // 统计库存和销售情况
|
|
|
+ $totalStock = 0;
|
|
|
+ $totalSold = 0;
|
|
|
+ foreach ($specList as $spec) {
|
|
|
+ $totalStock += $spec['stock'];
|
|
|
+ $totalSold += $spec['sold_count'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 统计用户购买数量(如果user_package表存在)
|
|
|
+ $userPurchaseCount = 0;
|
|
|
+ try {
|
|
|
+ $userPurchaseCount = Db::name('user_package')
|
|
|
+ ->where('package_id', $id)
|
|
|
+ ->count();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 表不存在,设为0
|
|
|
+ }
|
|
|
+
|
|
|
+ // 统计企业购买数量(如果company_package表存在)
|
|
|
+ $companyPurchaseCount = 0;
|
|
|
+ try {
|
|
|
+ $companyPurchaseCount = Db::name('company_package')
|
|
|
+ ->where('package_id', $id)
|
|
|
+ ->count();
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 表不存在,设为0
|
|
|
+ }
|
|
|
+
|
|
|
+ $result = [
|
|
|
+ 'package_info' => $packageInfo,
|
|
|
+ 'spec_list' => $specList,
|
|
|
+ 'statistics' => [
|
|
|
+ 'spec_count' => count($specList),
|
|
|
+ 'total_stock' => $totalStock,
|
|
|
+ 'total_sold' => $totalSold,
|
|
|
+ 'user_purchase_count' => $userPurchaseCount,
|
|
|
+ 'company_purchase_count' => $companyPurchaseCount
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->success('查询成功', $result);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加/编辑套餐规格
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function editSpec()
|
|
|
+ {
|
|
|
+ $id = $this->request->post('id');
|
|
|
+ $packageId = $this->request->post('package_id');
|
|
|
+ $specName = $this->request->post('spec_name');
|
|
|
+ $price = $this->request->post('price', 0);
|
|
|
+ $originalPrice = $this->request->post('original_price', 0);
|
|
|
+ $stock = $this->request->post('stock', 0);
|
|
|
+ $unitValue = $this->request->post('unit_value', '');
|
|
|
+ $description = $this->request->post('description', '');
|
|
|
+ $sort = $this->request->post('sort', 0);
|
|
|
+
|
|
|
+ if (empty($packageId) || empty($specName)) {
|
|
|
+ $this->error(__('参数不完整'));
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($price <= 0) {
|
|
|
+ $this->error(__('价格必须大于0'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查套餐是否存在
|
|
|
+ $packageInfo = Db::name('package')
|
|
|
+ ->where('id', $packageId)
|
|
|
+ ->find();
|
|
|
+
|
|
|
+ if (!$packageInfo) {
|
|
|
+ $this->error(__('套餐不存在'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证规格名称是否已存在(同一套餐下不能重复)
|
|
|
+ $checkSpec = Db::name('package_price')
|
|
|
+ ->where('package_id', $packageId)
|
|
|
+ ->where('spec_name', $specName);
|
|
|
+
|
|
|
+ if (!empty($id)) {
|
|
|
+ $checkSpec->where('id', '<>', $id);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($checkSpec->find()) {
|
|
|
+ $this->error(__('同一套餐下规格名称不能重复'));
|
|
|
+ }
|
|
|
+
|
|
|
+ $data = [
|
|
|
+ 'package_id' => $packageId,
|
|
|
+ 'spec_name' => $specName,
|
|
|
+ 'price' => $price,
|
|
|
+ 'original_price' => $originalPrice,
|
|
|
+ 'stock' => $stock,
|
|
|
+ 'unit_value' => $unitValue,
|
|
|
+ 'description' => $description,
|
|
|
+ 'sort' => $sort,
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
+ ];
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!empty($id)) {
|
|
|
+ // 编辑
|
|
|
+ $result = Db::name('package_price')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->update($data);
|
|
|
+ $message = '编辑成功';
|
|
|
+ } else {
|
|
|
+ // 新增
|
|
|
+ $data['create_time'] = date('Y-m-d H:i:s');
|
|
|
+ $result = Db::name('package_price')
|
|
|
+ ->insert($data);
|
|
|
+ $id = Db::name('package_price')->getLastInsID();
|
|
|
+ $message = '新增成功';
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $this->success($message, ['id' => $id]);
|
|
|
+ } else {
|
|
|
+ $this->error(__('操作失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->error('操作失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除套餐规格
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function deleteSpec()
|
|
|
+ {
|
|
|
+ $id = $this->request->post('id');
|
|
|
+
|
|
|
+ if (empty($id)) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有用户购买记录
|
|
|
+ try {
|
|
|
+ $hasPurchase = Db::name('user_package')
|
|
|
+ ->where('package_price_id', $id)
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ if ($hasPurchase > 0) {
|
|
|
+ $this->error(__('该规格已有用户购买记录,不能删除'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 表不存在,跳过检查
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否有企业购买记录
|
|
|
+ try {
|
|
|
+ $hasPurchase = Db::name('company_package')
|
|
|
+ ->where('package_price_id', $id)
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ if ($hasPurchase > 0) {
|
|
|
+ $this->error(__('该规格已有企业购买记录,不能删除'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 表不存在,跳过检查
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $result = Db::name('package_price')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->delete();
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $this->success('删除成功');
|
|
|
+ } else {
|
|
|
+ $this->error(__('删除失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->error('删除失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取套餐规格列表
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function specList()
|
|
|
+ {
|
|
|
+ $packageId = $this->request->get('package_id');
|
|
|
+
|
|
|
+ if (empty($packageId)) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ $specList = Db::name('package_price')
|
|
|
+ ->where('package_id', $packageId)
|
|
|
+ ->order('sort', 'asc')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ $this->success('查询成功', $specList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新套餐状态
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function batchStatus()
|
|
|
+ {
|
|
|
+ $ids = $this->request->post('ids');
|
|
|
+ $status = $this->request->post('status');
|
|
|
+
|
|
|
+ if (empty($ids) || empty($status)) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!is_array($ids)) {
|
|
|
+ $ids = explode(',', $ids);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $result = Db::name('package')
|
|
|
+ ->whereIn('id', $ids)
|
|
|
+ ->update([
|
|
|
+ 'status' => $status,
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
+ ]);
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $statusText = $status == 1 ? '启用' : '禁用';
|
|
|
+ $this->success("成功{$statusText}{$result}个套餐");
|
|
|
+ } else {
|
|
|
+ $this->error(__('操作失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->error('操作失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新规格库存
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function batchUpdateStock()
|
|
|
+ {
|
|
|
+ $ids = $this->request->post('ids');
|
|
|
+ $stock = $this->request->post('stock');
|
|
|
+
|
|
|
+ if (empty($ids) || $stock === null) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!is_array($ids)) {
|
|
|
+ $ids = explode(',', $ids);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $result = Db::name('package_price')
|
|
|
+ ->whereIn('id', $ids)
|
|
|
+ ->update([
|
|
|
+ 'stock' => $stock,
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
+ ]);
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $this->success("成功更新{$result}个规格的库存");
|
|
|
+ } else {
|
|
|
+ $this->error(__('操作失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ $this->error('操作失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取套餐类型选项
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function typeOptions()
|
|
|
+ {
|
|
|
+ $options = [
|
|
|
+ ['value' => 1, 'label' => '个人套餐'],
|
|
|
+ ['value' => 2, 'label' => '团队套餐'],
|
|
|
+ ['value' => 3, 'label' => '企业套餐']
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->success('获取成功', $options);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取套餐状态选项
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function statusOptions()
|
|
|
+ {
|
|
|
+ $options = [
|
|
|
+ ['value' => 1, 'label' => '启用'],
|
|
|
+ ['value' => 2, 'label' => '禁用']
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->success('获取成功', $options);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取规格状态选项
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function specStatusOptions()
|
|
|
+ {
|
|
|
+ $options = [
|
|
|
+ ['value' => 1, 'label' => '正常'],
|
|
|
+ ['value' => 2, 'label' => '售罄']
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->success('获取成功', $options);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 套餐统计信息
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function statistics()
|
|
|
+ {
|
|
|
+ // 套餐总数
|
|
|
+ $totalPackage = Db::name('package')->count();
|
|
|
+
|
|
|
+ // 启用套餐数
|
|
|
+ $activePackage = Db::name('package')
|
|
|
+ ->where('status', 1)
|
|
|
+ ->count();
|
|
|
+
|
|
|
+ // 规格总数
|
|
|
+ $totalSpec = Db::name('package_price')->count();
|
|
|
+
|
|
|
+ // 总库存
|
|
|
+ $totalStock = Db::name('package_price')
|
|
|
+ ->sum('stock');
|
|
|
+
|
|
|
+ // 总已售
|
|
|
+ $totalSold = Db::name('package_price')
|
|
|
+ ->sum('sold_count');
|
|
|
+
|
|
|
+ // 按类型统计
|
|
|
+ $typeStats = Db::name('package')
|
|
|
+ ->field('type, COUNT(*) as count')
|
|
|
+ ->where('status', 1)
|
|
|
+ ->group('type')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ $stats = [
|
|
|
+ 'total_package' => $totalPackage,
|
|
|
+ 'active_package' => $activePackage,
|
|
|
+ 'total_spec' => $totalSpec,
|
|
|
+ 'total_stock' => $totalStock,
|
|
|
+ 'total_sold' => $totalSold,
|
|
|
+ 'type_stats' => $typeStats
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->success('获取成功', $stats);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出套餐数据
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function export()
|
|
|
+ {
|
|
|
+ $where = [];
|
|
|
+
|
|
|
+ // 根据筛选条件构建查询条件
|
|
|
+ if (!empty($this->request->get('name'))) {
|
|
|
+ $name = $this->request->get('name');
|
|
|
+ $where[] = ['name', 'like', '%' . $name . '%'];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!empty($this->request->get('status'))) {
|
|
|
+ $status = $this->request->get('status');
|
|
|
+ $where['status'] = $status;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询数据
|
|
|
+ $packageList = Db::name('package')
|
|
|
+ ->where($where)
|
|
|
+ ->order('sort', 'asc')
|
|
|
+ ->order('id', 'desc')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ // 状态映射
|
|
|
+ $typeMap = [1 => '个人套餐', 2 => '团队套餐', 3 => '企业套餐'];
|
|
|
+ $statusMap = [1 => '启用', 2 => '禁用'];
|
|
|
+
|
|
|
+ foreach ($packageList as &$item) {
|
|
|
+ $item['type'] = $typeMap[$item['type']] ?? '未知';
|
|
|
+ $item['status'] = $statusMap[$item['status']] ?? '未知';
|
|
|
+
|
|
|
+ // 获取规格信息
|
|
|
+ $specs = Db::name('package_price')
|
|
|
+ ->where('package_id', $item['id'])
|
|
|
+ ->order('sort', 'asc')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ $specInfo = [];
|
|
|
+ foreach ($specs as $spec) {
|
|
|
+ $specInfo[] = "{$spec['spec_name']} - ¥{$spec['price']} (库存:{$spec['stock']})";
|
|
|
+ }
|
|
|
+
|
|
|
+ $item['spec_info'] = implode('; ', $specInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->success('查询成功', $packageList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所有套餐选项(用于下拉选择)
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function selectOptions()
|
|
|
+ {
|
|
|
+ $packageList = Db::name('package')
|
|
|
+ ->where('status', 1)
|
|
|
+ ->field('id as value, name as label, type')
|
|
|
+ ->order('sort', 'asc')
|
|
|
+ ->order('id', 'asc')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ $this->success('获取成功', $packageList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取套餐规格选项(用于购买时选择)
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function specOptions()
|
|
|
+ {
|
|
|
+ $packageId = $this->request->get('package_id');
|
|
|
+
|
|
|
+ if (empty($packageId)) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ $specList = Db::name('package_price')
|
|
|
+ ->where('package_id', $packageId)
|
|
|
+ ->where('status', 1)
|
|
|
+ ->where('stock', '>', 0) // 只显示有库存的规格
|
|
|
+ ->field('id as value, spec_name as label, price, stock, unit_value, description')
|
|
|
+ ->order('sort', 'asc')
|
|
|
+ ->select()
|
|
|
+ ->toArray();
|
|
|
+
|
|
|
+ $this->success('获取成功', $specList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新规格销售数量(模拟用户购买)
|
|
|
+ * @return void
|
|
|
+ */
|
|
|
+ public function updateSoldCount()
|
|
|
+ {
|
|
|
+ $id = $this->request->post('id');
|
|
|
+ $quantity = $this->request->post('quantity', 1);
|
|
|
+
|
|
|
+ if (empty($id) || $quantity <= 0) {
|
|
|
+ $this->error(__('参数错误'));
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ Db::startTrans();
|
|
|
+
|
|
|
+ // 获取当前规格信息
|
|
|
+ $specInfo = Db::name('package_price')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->lock(true)
|
|
|
+ ->find();
|
|
|
+
|
|
|
+ if (!$specInfo) {
|
|
|
+ throw new \Exception('规格不存在');
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($specInfo['stock'] < $quantity) {
|
|
|
+ throw new \Exception('库存不足');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新库存和销售数量
|
|
|
+ $result = Db::name('package_price')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->update([
|
|
|
+ 'stock' => Db::raw('stock - ' . $quantity),
|
|
|
+ 'sold_count' => Db::raw('sold_count + ' . $quantity),
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 如果库存为0,自动标记为售罄
|
|
|
+ if ($specInfo['stock'] - $quantity <= 0) {
|
|
|
+ Db::name('package_price')
|
|
|
+ ->where('id', $id)
|
|
|
+ ->update([
|
|
|
+ 'status' => 2, // 售罄
|
|
|
+ 'update_time' => date('Y-m-d H:i:s')
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ Db::commit();
|
|
|
+
|
|
|
+ if ($result) {
|
|
|
+ $this->success('更新成功');
|
|
|
+ } else {
|
|
|
+ $this->error(__('更新失败'));
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Db::rollback();
|
|
|
+ $this->error('操作失败: ' . $e->getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|