浏览代码

添加功能

PC-7\Administrator 10 月之前
父节点
当前提交
c62a5550cc

+ 441 - 0
app/admin/controller/distribution/Distribution.php

@@ -0,0 +1,441 @@
+<?php
+/**
+ * 分销管理控制器
+ */
+
+namespace app\admin\controller\distribution;
+
+use app\common\controller\Backend;
+use think\facade\Db;
+
+class Distribution extends Backend
+{
+    protected array $noNeedLogin = ['*'];
+
+    /**
+     * 分销订单列表
+     * @return void
+     */
+    public function index(): void
+    {
+        $where = [];
+
+        // 分佣产品搜索
+        if (!empty($this->request->get('product_name'))) {
+            $productName = $this->request->get('product_name');
+            $where[] = ['p.name', 'like', '%' . $productName . '%'];
+        }
+
+        // 分佣人搜索
+        if (!empty($this->request->get('distributor_name'))) {
+            $distributorName = $this->request->get('distributor_name');
+            $where[] = ['du.name', 'like', '%' . $distributorName . '%'];
+        }
+
+        // 购买人搜索
+        if (!empty($this->request->get('buyer_name'))) {
+            $buyerName = $this->request->get('buyer_name');
+            $where[] = ['bu.name', 'like', '%' . $buyerName . '%'];
+        }
+
+        // 关联订单号搜索
+        if (!empty($this->request->get('order_no'))) {
+            $orderNo = $this->request->get('order_no');
+            $where[] = ['o.order_no', 'like', '%' . $orderNo . '%'];
+        }
+
+        // 状态筛选
+        if (!empty($this->request->get('status'))) {
+            $status = $this->request->get('status');
+            $where['dr.status'] = $status;
+        }
+
+        // 创建时间范围筛选
+        if (!empty($this->request->get('create_time_range'))) {
+            $timeRange = $this->request->get('create_time_range');
+            $timeArr = explode(' - ', $timeRange);
+            if (count($timeArr) == 2) {
+                $startTime = $timeArr[0];
+                $endTime = $timeArr[1];
+                $where[] = ['dr.create_time', '>=', $startTime . ' 00:00:00'];
+                $where[] = ['dr.create_time', '<=', $endTime . ' 23:59:59'];
+            }
+        }
+
+        // 排序
+        $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['dr.create_time'] = 'desc';
+        }
+
+        // 分页
+        $page = $this->request->get('page', 1);
+        $limit = $this->request->get('limit', 20);
+
+        // 查询分销记录
+        $distributionList = Db::name('distribution_record')
+            ->alias('dr')
+            ->leftJoin('order o', 'dr.order_id = o.id')
+            ->leftJoin('product p', 'dr.product_id = p.id')
+            ->leftJoin('user bu', 'dr.buyer_id = bu.id')
+            ->leftJoin('user du', 'dr.distributor_id = du.id')
+            ->field('
+                dr.id as 编号,
+                o.order_no as 关联订单号,
+                p.name as 分佣产品,
+                bu.name as 购买人,
+                du.name as 分佣人,
+                dr.commission_amount as 分佣金额,
+                dr.create_time as 创建时间,
+                dr.status,
+                dr.commission_rate
+            ')
+            ->where($where)
+            ->order($order)
+            ->paginate([
+                'list_rows' => $limit,
+                'page' => $page
+            ]);
+
+        // 状态转换
+        $list = $distributionList->items();
+        foreach ($list as &$item) {
+            $statusMap = [
+                1 => '待结算',
+                2 => '已结算',
+                3 => '已取消'
+            ];
+            $item['status_text'] = $statusMap[$item['status']] ?? '未知';
+        }
+
+        $this->success('查询成功', [
+            'list' => $list,
+            'total' => $distributionList->total()
+        ]);
+    }
+
+    /**
+     * 获取分销设置
+     * @return void
+     */
+    public function getSetting(): void
+    {
+        $setting = Db::name('distribution_setting')
+            ->order('id', 'desc')
+            ->find();
+
+        if (!$setting) {
+            // 如果不存在,创建默认设置
+            $defaultSetting = [
+                'default_rate' => 15.00,
+                'min_withdrawal' => 20.00,
+                'max_withdrawal' => 50000.00,
+                'withdrawal_fee_rate' => 0.00,
+                'update_time' => date('Y-m-d H:i:s')
+            ];
+
+            Db::name('distribution_setting')->insert($defaultSetting);
+            $setting = $defaultSetting;
+        }
+
+        $this->success('获取成功', $setting);
+    }
+
+    /**
+     * 更新分销设置
+     * @return void
+     */
+    public function updateSetting(): void
+    {
+        $defaultRate = $this->request->post('default_rate', 15.00);
+        $minWithdrawal = $this->request->post('min_withdrawal', 20.00);
+        $maxWithdrawal = $this->request->post('max_withdrawal', 50000.00);
+        $withdrawalFeeRate = $this->request->post('withdrawal_fee_rate', 0.00);
+
+        if ($defaultRate <= 0 || $defaultRate > 100) {
+            $this->error(__('分销佣金比例必须在0-100之间'));
+        }
+
+        if ($minWithdrawal <= 0) {
+            $this->error(__('最低提现金额必须大于0'));
+        }
+
+        if ($maxWithdrawal <= $minWithdrawal) {
+            $this->error(__('最高提现金额必须大于最低提现金额'));
+        }
+
+        $data = [
+            'default_rate' => $defaultRate,
+            'min_withdrawal' => $minWithdrawal,
+            'max_withdrawal' => $maxWithdrawal,
+            'withdrawal_fee_rate' => $withdrawalFeeRate,
+            'update_time' => date('Y-m-d H:i:s')
+        ];
+
+        try {
+            // 检查是否已有设置
+            $existingSetting = Db::name('distribution_setting')->find();
+
+            if ($existingSetting) {
+                // 更新
+                $result = Db::name('distribution_setting')
+                    ->where('id', $existingSetting['id'])
+                    ->update($data);
+            } else {
+                // 新增
+                $result = Db::name('distribution_setting')
+                    ->insert($data);
+            }
+
+            if ($result) {
+                $this->success('更新成功');
+            } else {
+                $this->error(__('更新失败'));
+            }
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 手动结算分销佣金
+     * @return void
+     */
+    public function settleCommission(): void
+    {
+        $id = $this->request->post('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        try {
+            Db::startTrans();
+
+            // 获取分销记录
+            $distributionRecord = Db::name('distribution_record')
+                ->where('id', $id)
+                ->lock(true)
+                ->find();
+
+            if (!$distributionRecord) {
+                throw new \Exception('分销记录不存在');
+            }
+
+            if ($distributionRecord['status'] != 1) {
+                throw new \Exception('只有待结算的记录才能结算');
+            }
+
+            // 更新分销记录状态
+            $updateResult = Db::name('distribution_record')
+                ->where('id', $id)
+                ->update([
+                    'status' => 2,
+                    'settle_time' => date('Y-m-d H:i:s')
+                ]);
+
+            if (!$updateResult) {
+                throw new \Exception('更新分销记录失败');
+            }
+
+            // 更新用户佣金
+            $userCommission = Db::name('user_commission')
+                ->where('user_id', $distributionRecord['distributor_id'])
+                ->lock(true)
+                ->find();
+
+            if ($userCommission) {
+                // 更新现有记录
+                $commissionResult = Db::name('user_commission')
+                    ->where('user_id', $distributionRecord['distributor_id'])
+                    ->update([
+                        'total_commission' => Db::raw('total_commission + ' . $distributionRecord['commission_amount']),
+                        'current_commission' => Db::raw('current_commission + ' . $distributionRecord['commission_amount']),
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+            } else {
+                // 创建新记录
+                $commissionResult = Db::name('user_commission')
+                    ->insert([
+                        'user_id' => $distributionRecord['distributor_id'],
+                        'total_commission' => $distributionRecord['commission_amount'],
+                        'current_commission' => $distributionRecord['commission_amount'],
+                        'promotion_link' => 'xxxx.com?from=' . $distributionRecord['distributor_id'],
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+            }
+
+            if (!$commissionResult) {
+                throw new \Exception('更新用户佣金失败');
+            }
+
+            Db::commit();
+            $this->success('结算成功');
+
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error('结算失败: ' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 批量结算分销佣金
+     * @return void
+     */
+    public function batchSettle(): void
+    {
+        $ids = $this->request->post('ids');
+
+        if (empty($ids)) {
+            $this->error(__('参数错误'));
+        }
+
+        if (!is_array($ids)) {
+            $ids = explode(',', $ids);
+        }
+
+        $successCount = 0;
+        $failCount = 0;
+        $messages = [];
+
+        foreach ($ids as $id) {
+            try {
+                Db::startTrans();
+
+                $distributionRecord = Db::name('distribution_record')
+                    ->where('id', $id)
+                    ->lock(true)
+                    ->find();
+
+                if (!$distributionRecord) {
+                    throw new \Exception('分销记录不存在');
+                }
+
+                if ($distributionRecord['status'] != 1) {
+                    throw new \Exception('只有待结算的记录才能结算');
+                }
+
+                // 更新分销记录状态
+                Db::name('distribution_record')
+                    ->where('id', $id)
+                    ->update([
+                        'status' => 2,
+                        'settle_time' => date('Y-m-d H:i:s')
+                    ]);
+
+                // 更新用户佣金
+                $userCommission = Db::name('user_commission')
+                    ->where('user_id', $distributionRecord['distributor_id'])
+                    ->lock(true)
+                    ->find();
+
+                if ($userCommission) {
+                    Db::name('user_commission')
+                        ->where('user_id', $distributionRecord['distributor_id'])
+                        ->update([
+                            'total_commission' => Db::raw('total_commission + ' . $distributionRecord['commission_amount']),
+                            'current_commission' => Db::raw('current_commission + ' . $distributionRecord['commission_amount']),
+                            'update_time' => date('Y-m-d H:i:s')
+                        ]);
+                } else {
+                    Db::name('user_commission')
+                        ->insert([
+                            'user_id' => $distributionRecord['distributor_id'],
+                            'total_commission' => $distributionRecord['commission_amount'],
+                            'current_commission' => $distributionRecord['commission_amount'],
+                            'promotion_link' => 'xxxx.com?from=' . $distributionRecord['distributor_id'],
+                            'update_time' => date('Y-m-d H:i:s')
+                        ]);
+                }
+
+                Db::commit();
+                $successCount++;
+
+            } catch (\Exception $e) {
+                Db::rollback();
+                $failCount++;
+                $messages[] = "记录ID {$id}: " . $e->getMessage();
+            }
+        }
+
+        $message = "结算完成,成功: {$successCount}条,失败: {$failCount}条";
+        if (!empty($messages)) {
+            $message .= "。失败原因:" . implode('; ', $messages);
+        }
+
+        $this->success($message);
+    }
+
+    /**
+     * 分销统计
+     * @return void
+     */
+    public function statistics(): void
+    {
+        // 总分销记录数
+        $totalCount = Db::name('distribution_record')->count();
+
+        // 待结算记录数
+        $pendingCount = Db::name('distribution_record')
+            ->where('status', 1)
+            ->count();
+
+        // 已结算记录数
+        $settledCount = Db::name('distribution_record')
+            ->where('status', 2)
+            ->count();
+
+        // 总分销金额
+        $totalCommission = Db::name('distribution_record')
+            ->where('status', 2)
+            ->sum('commission_amount');
+
+        // 今日分销统计
+        $todayStart = date('Y-m-d 00:00:00');
+        $todayEnd = date('Y-m-d 23:59:59');
+        $todayCount = Db::name('distribution_record')
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->count();
+
+        $todayCommission = Db::name('distribution_record')
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->sum('commission_amount');
+
+        // 分销人数统计
+        $distributorCount = Db::name('distribution_record')
+            ->distinct(true)
+            ->field('distributor_id')
+            ->count();
+
+        $stats = [
+            'total_count' => $totalCount,
+            'pending_count' => $pendingCount,
+            'settled_count' => $settledCount,
+            'total_commission' => $totalCommission ?? 0,
+            'today_count' => $todayCount,
+            'today_commission' => $todayCommission ?? 0,
+            'distributor_count' => $distributorCount
+        ];
+
+        $this->success('获取成功', $stats);
+    }
+
+    /**
+     * 获取分销状态选项
+     * @return void
+     */
+    public function statusOptions(): void
+    {
+        $options = [
+            ['value' => 1, 'label' => '待结算'],
+            ['value' => 2, 'label' => '已结算'],
+            ['value' => 3, 'label' => '已取消']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+}

+ 441 - 0
app/admin/controller/order/Distribution.php

@@ -0,0 +1,441 @@
+<?php
+/**
+ * 分销管理控制器
+ */
+
+namespace app\admin\controller\order;
+
+use app\common\controller\Backend;
+use think\facade\Db;
+
+class Distribution extends Backend
+{
+    protected array $noNeedLogin = ['*'];
+
+    /**
+     * 分销订单列表
+     * @return void
+     */
+    public function index(): void
+    {
+        $where = [];
+
+        // 分佣产品搜索
+        if (!empty($this->request->get('product_name'))) {
+            $productName = $this->request->get('product_name');
+            $where[] = ['p.name', 'like', '%' . $productName . '%'];
+        }
+
+        // 分佣人搜索
+        if (!empty($this->request->get('distributor_name'))) {
+            $distributorName = $this->request->get('distributor_name');
+            $where[] = ['du.name', 'like', '%' . $distributorName . '%'];
+        }
+
+        // 购买人搜索
+        if (!empty($this->request->get('buyer_name'))) {
+            $buyerName = $this->request->get('buyer_name');
+            $where[] = ['bu.name', 'like', '%' . $buyerName . '%'];
+        }
+
+        // 关联订单号搜索
+        if (!empty($this->request->get('order_no'))) {
+            $orderNo = $this->request->get('order_no');
+            $where[] = ['o.order_no', 'like', '%' . $orderNo . '%'];
+        }
+
+        // 状态筛选
+        if (!empty($this->request->get('status'))) {
+            $status = $this->request->get('status');
+            $where['dr.status'] = $status;
+        }
+
+        // 创建时间范围筛选
+        if (!empty($this->request->get('create_time_range'))) {
+            $timeRange = $this->request->get('create_time_range');
+            $timeArr = explode(' - ', $timeRange);
+            if (count($timeArr) == 2) {
+                $startTime = $timeArr[0];
+                $endTime = $timeArr[1];
+                $where[] = ['dr.create_time', '>=', $startTime . ' 00:00:00'];
+                $where[] = ['dr.create_time', '<=', $endTime . ' 23:59:59'];
+            }
+        }
+
+        // 排序
+        $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['dr.create_time'] = 'desc';
+        }
+
+        // 分页
+        $page = $this->request->get('page', 1);
+        $limit = $this->request->get('limit', 20);
+
+        // 查询分销记录
+        $distributionList = Db::name('distribution_record')
+            ->alias('dr')
+            ->leftJoin('order o', 'dr.order_id = o.id')
+            ->leftJoin('product p', 'dr.product_id = p.id')
+            ->leftJoin('user_on bu', 'dr.buyer_id = bu.id')
+            ->leftJoin('user_on du', 'dr.distributor_id = du.id')
+            ->field('
+                dr.id,
+                o.order_no,
+                p.name as commission_product,
+                bu.name as g_name,
+                du.name as f_name,
+                dr.commission_amount,
+                dr.create_time,
+                dr.status,
+                dr.commission_rate
+            ')
+            ->where($where)
+            ->order($order)
+            ->paginate([
+                'list_rows' => $limit,
+                'page' => $page
+            ]);
+
+        // 状态转换
+        $list = $distributionList->items();
+        foreach ($list as &$item) {
+            $statusMap = [
+                1 => '待结算',
+                2 => '已结算',
+                3 => '已取消'
+            ];
+            $item['status_text'] = $statusMap[$item['status']] ?? '未知';
+        }
+
+        $this->success('查询成功', [
+            'list' => $list,
+            'total' => $distributionList->total()
+        ]);
+    }
+
+    /**
+     * 获取分销设置
+     * @return void
+     */
+    public function getSetting(): void
+    {
+        $setting = Db::name('distribution_setting')
+            ->order('id', 'desc')
+            ->find();
+
+        if (!$setting) {
+            // 如果不存在,创建默认设置
+            $defaultSetting = [
+                'default_rate' => 15.00,
+                'min_withdrawal' => 20.00,
+                'max_withdrawal' => 50000.00,
+                'withdrawal_fee_rate' => 0.00,
+                'update_time' => date('Y-m-d H:i:s')
+            ];
+
+            Db::name('distribution_setting')->insert($defaultSetting);
+            $setting = $defaultSetting;
+        }
+
+        $this->success('获取成功', $setting);
+    }
+
+    /**
+     * 更新分销设置
+     * @return void
+     */
+    public function updateSetting(): void
+    {
+        $defaultRate = $this->request->post('default_rate', 15.00);
+        $minWithdrawal = $this->request->post('min_withdrawal', 20.00);
+        $maxWithdrawal = $this->request->post('max_withdrawal', 50000.00);
+        $withdrawalFeeRate = $this->request->post('withdrawal_fee_rate', 0.00);
+
+        if ($defaultRate <= 0 || $defaultRate > 100) {
+            $this->error(__('分销佣金比例必须在0-100之间'));
+        }
+
+        if ($minWithdrawal <= 0) {
+            $this->error(__('最低提现金额必须大于0'));
+        }
+
+        if ($maxWithdrawal <= $minWithdrawal) {
+            $this->error(__('最高提现金额必须大于最低提现金额'));
+        }
+
+        $data = [
+            'default_rate' => $defaultRate,
+            'min_withdrawal' => $minWithdrawal,
+            'max_withdrawal' => $maxWithdrawal,
+            'withdrawal_fee_rate' => $withdrawalFeeRate,
+            'update_time' => date('Y-m-d H:i:s')
+        ];
+
+        try {
+            // 检查是否已有设置
+            $existingSetting = Db::name('distribution_setting')->value('id');
+            if ($existingSetting) {
+                // 更新
+                $result = Db::name('distribution_setting')
+                    ->where('id', $existingSetting)
+                    ->update($data);
+            } else {
+                // 新增
+                $result = Db::name('distribution_setting')
+                    ->insert($data);
+            }
+
+
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+        if ($result) {
+            $this->success('更新成功');
+        } else {
+            $this->error(__('更新失败'));
+        }
+    }
+
+    /**
+     * 手动结算分销佣金
+     * @return void
+     */
+    public function settleCommission(): void
+    {
+        $id = $this->request->post('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        try {
+            Db::startTrans();
+
+            // 获取分销记录
+            $distributionRecord = Db::name('distribution_record')
+                ->where('id', $id)
+                ->lock(true)
+                ->find();
+
+            if (!$distributionRecord) {
+                throw new \Exception('分销记录不存在');
+            }
+
+            if ($distributionRecord['status'] != 1) {
+                throw new \Exception('只有待结算的记录才能结算');
+            }
+
+            // 更新分销记录状态
+            $updateResult = Db::name('distribution_record')
+                ->where('id', $id)
+                ->update([
+                    'status' => 2,
+                    'settle_time' => date('Y-m-d H:i:s')
+                ]);
+
+            if (!$updateResult) {
+                throw new \Exception('更新分销记录失败');
+            }
+
+            // 更新用户佣金
+            $userCommission = Db::name('user_commission')
+                ->where('user_id', $distributionRecord['distributor_id'])
+                ->lock(true)
+                ->find();
+
+            if ($userCommission) {
+                // 更新现有记录
+                $commissionResult = Db::name('user_commission')
+                    ->where('user_id', $distributionRecord['distributor_id'])
+                    ->update([
+                        'total_commission' => Db::raw('total_commission + ' . $distributionRecord['commission_amount']),
+                        'current_commission' => Db::raw('current_commission + ' . $distributionRecord['commission_amount']),
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+            } else {
+                // 创建新记录
+                $commissionResult = Db::name('user_commission')
+                    ->insert([
+                        'user_id' => $distributionRecord['distributor_id'],
+                        'total_commission' => $distributionRecord['commission_amount'],
+                        'current_commission' => $distributionRecord['commission_amount'],
+                        'promotion_link' => 'xxxx.com?from=' . $distributionRecord['distributor_id'],
+                        'update_time' => date('Y-m-d H:i:s')
+                    ]);
+            }
+
+            if (!$commissionResult) {
+                throw new \Exception('更新用户佣金失败');
+            }
+
+            Db::commit();
+            $this->success('结算成功');
+
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error('结算失败: ' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 批量结算分销佣金
+     * @return void
+     */
+    public function batchSettle(): void
+    {
+        $ids = $this->request->post('ids');
+
+        if (empty($ids)) {
+            $this->error(__('参数错误'));
+        }
+
+        if (!is_array($ids)) {
+            $ids = explode(',', $ids);
+        }
+
+        $successCount = 0;
+        $failCount = 0;
+        $messages = [];
+
+        foreach ($ids as $id) {
+            try {
+                Db::startTrans();
+
+                $distributionRecord = Db::name('distribution_record')
+                    ->where('id', $id)
+                    ->lock(true)
+                    ->find();
+
+                if (!$distributionRecord) {
+                    throw new \Exception('分销记录不存在');
+                }
+
+                if ($distributionRecord['status'] != 1) {
+                    throw new \Exception('只有待结算的记录才能结算');
+                }
+
+                // 更新分销记录状态
+                Db::name('distribution_record')
+                    ->where('id', $id)
+                    ->update([
+                        'status' => 2,
+                        'settle_time' => date('Y-m-d H:i:s')
+                    ]);
+
+                // 更新用户佣金
+                $userCommission = Db::name('user_commission')
+                    ->where('user_id', $distributionRecord['distributor_id'])
+                    ->lock(true)
+                    ->find();
+
+                if ($userCommission) {
+                    Db::name('user_commission')
+                        ->where('user_id', $distributionRecord['distributor_id'])
+                        ->update([
+                            'total_commission' => Db::raw('total_commission + ' . $distributionRecord['commission_amount']),
+                            'current_commission' => Db::raw('current_commission + ' . $distributionRecord['commission_amount']),
+                            'update_time' => date('Y-m-d H:i:s')
+                        ]);
+                } else {
+                    Db::name('user_commission')
+                        ->insert([
+                            'user_id' => $distributionRecord['distributor_id'],
+                            'total_commission' => $distributionRecord['commission_amount'],
+                            'current_commission' => $distributionRecord['commission_amount'],
+                            'promotion_link' => 'xxxx.com?from=' . $distributionRecord['distributor_id'],
+                            'update_time' => date('Y-m-d H:i:s')
+                        ]);
+                }
+
+                Db::commit();
+                $successCount++;
+
+            } catch (\Exception $e) {
+                Db::rollback();
+                $failCount++;
+                $messages[] = "记录ID {$id}: " . $e->getMessage();
+            }
+        }
+
+        $message = "结算完成,成功: {$successCount}条,失败: {$failCount}条";
+        if (!empty($messages)) {
+            $message .= "。失败原因:" . implode('; ', $messages);
+        }
+
+        $this->success($message);
+    }
+
+    /**
+     * 分销统计
+     * @return void
+     */
+    public function statistics(): void
+    {
+        // 总分销记录数
+        $totalCount = Db::name('distribution_record')->count();
+
+        // 待结算记录数
+        $pendingCount = Db::name('distribution_record')
+            ->where('status', 1)
+            ->count();
+
+        // 已结算记录数
+        $settledCount = Db::name('distribution_record')
+            ->where('status', 2)
+            ->count();
+
+        // 总分销金额
+        $totalCommission = Db::name('distribution_record')
+            ->where('status', 2)
+            ->sum('commission_amount');
+
+        // 今日分销统计
+        $todayStart = date('Y-m-d 00:00:00');
+        $todayEnd = date('Y-m-d 23:59:59');
+        $todayCount = Db::name('distribution_record')
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->count();
+
+        $todayCommission = Db::name('distribution_record')
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->sum('commission_amount');
+
+        // 分销人数统计
+        $distributorCount = Db::name('distribution_record')
+            ->distinct(true)
+            ->field('distributor_id')
+            ->count();
+
+        $stats = [
+            'total_count' => $totalCount,
+            'pending_count' => $pendingCount,
+            'settled_count' => $settledCount,
+            'total_commission' => $totalCommission ?? 0,
+            'today_count' => $todayCount,
+            'today_commission' => $todayCommission ?? 0,
+            'distributor_count' => $distributorCount
+        ];
+
+        $this->success('获取成功', $stats);
+    }
+
+    /**
+     * 获取分销状态选项
+     * @return void
+     */
+    public function statusOptions(): void
+    {
+        $options = [
+            ['value' => 1, 'label' => '待结算'],
+            ['value' => 2, 'label' => '已结算'],
+            ['value' => 3, 'label' => '已取消']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+}

+ 426 - 0
app/admin/controller/order/Order.php

@@ -0,0 +1,426 @@
+<?php
+/**
+ * 订单管理控制器
+ */
+
+namespace app\admin\controller\order;
+
+use app\common\controller\Backend;
+use think\facade\Db;
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+use PhpOffice\PhpSpreadsheet\Cell\DataType;
+
+class Order extends Backend
+{
+    protected array $noNeedLogin = ['*'];
+
+    /**
+     * 订单列表
+     * @return void
+     */
+    public function index(): void
+    {
+        $where = [];
+
+        // 订单编号搜索
+        if (!empty($this->request->get('order_no'))) {
+            $orderNo = $this->request->get('order_no');
+            $where[] = ['o.order_no', 'like', '%' . $orderNo . '%'];
+        }
+
+        // 商品名称搜索
+        if (!empty($this->request->get('product_name'))) {
+            $productName = $this->request->get('product_name');
+            $where[] = ['oi.item_name', 'like', '%' . $productName . '%'];
+        }
+
+        // 会员名称搜索
+        if (!empty($this->request->get('user_name'))) {
+            $userName = $this->request->get('user_name');
+            $where[] = ['u.name', 'like', '%' . $userName . '%'];
+        }
+
+        // 分佣人搜索
+        if (!empty($this->request->get('distributor_name'))) {
+            $distributorName = $this->request->get('distributor_name');
+            $where[] = ['du.name', 'like', '%' . $distributorName . '%'];
+        }
+
+        // 支付状态筛选
+        if (!empty($this->request->get('pay_status'))) {
+            $payStatus = $this->request->get('pay_status');
+            $where['o.pay_status'] = $payStatus;
+        }
+
+        // 支付方式筛选
+        if (!empty($this->request->get('pay_method'))) {
+            $payMethod = $this->request->get('pay_method');
+            $where['o.pay_method'] = $payMethod;
+        }
+
+        // 日期范围筛选
+        if (!empty($this->request->get('date_range'))) {
+            $dateRange = $this->request->get('date_range');
+            $dateArr = explode(' - ', $dateRange);
+            if (count($dateArr) == 2) {
+                $startDate = $dateArr[0];
+                $endDate = $dateArr[1];
+                $where[] = ['o.order_time', '>=', $startDate . ' 00:00:00'];
+                $where[] = ['o.order_time', '<=', $endDate . ' 23:59:59'];
+            }
+        }
+
+        // 排序
+        $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['o.order_time'] = 'desc';
+        }
+
+        // 分页
+        $page = $this->request->get('page', 1);
+        $limit = $this->request->get('limit', 20);
+
+        // 查询数据(使用订单商品表作为主表,一个订单可能对应多个商品)
+        $orderList = Db::name('order_item')
+            ->alias('oi')
+            ->leftJoin('order o', 'oi.order_id = o.id')
+            ->leftJoin('user_on u', 'o.user_id = u.id')
+            ->leftJoin('user_on du', 'o.distributor_id = du.id')
+            ->field('
+                o.order_time,
+                o.order_no,
+                oi.item_name,
+                oi.quantity,
+                oi.unit_price,
+                u.name,
+                o.pay_amount,
+                o.pay_method,
+                o.pay_status,
+                o.commission_amount,
+                du.name,
+                o.order_time,
+                o.pay_time,
+                oi.id,
+                o.id as order_id
+            ')
+            ->where($where)
+            ->order($order)
+            ->paginate([
+                'list_rows' => $limit,
+                'page' => $page
+            ]);
+
+        // 转换字段格式
+        $list = $orderList->items();
+        foreach ($list as &$item) {
+            // 支付方式转换
+            $payMethodMap = [
+                'wechat' => '微信',
+                'alipay' => '支付宝',
+                'bank' => '银行卡',
+                'balance' => '余额'
+            ];
+            $item['pay_method'] = $payMethodMap[$item['pay_method']] ?? $item['pay_method'];
+
+            // 支付状态转换
+            $payStatusMap = [
+                0 => '待支付',
+                1 => '已支付',
+                2 => '支付失败',
+                3 => '已取消'
+            ];
+            $item['pay_status_text'] = $payStatusMap[$item['pay_status']] ?? $item['pay_status'];
+
+            // 格式化日期
+            if (!empty($item['order_time'])) {
+                $item['order_time'] = date('Y-m-d', strtotime($item['order_time']));
+            }
+        }
+
+        $this->success('查询成功', [
+            'list' => $list,
+            'total' => $orderList->total()
+        ]);
+    }
+
+
+    /**
+     * 构建查询条件
+     * @return array
+     */
+    private function buildWhere(): array
+    {
+        $where = [];
+
+        if (!empty($this->request->get('order_no'))) {
+            $where[] = ['o.order_no', 'like', '%' . $this->request->get('order_no') . '%'];
+        }
+
+        if (!empty($this->request->get('item_name'))) {
+            $where[] = ['oi.item_name', 'like', '%' . $this->request->get('item_name') . '%'];
+        }
+
+        if (!empty($this->request->get('user_name'))) {
+            $where[] = ['u.name', 'like', '%' . $this->request->get('user_name') . '%'];
+        }
+
+        if (!empty($this->request->get('distributor_name'))) {
+            $where[] = ['du.name', 'like', '%' . $this->request->get('distributor_name') . '%'];
+        }
+
+        if ($this->request->get('pay_status') !== '' && $this->request->get('pay_status') !== null) {
+            $where['o.pay_status'] = $this->request->get('pay_status');
+        }
+
+        if (!empty($this->request->get('pay_method'))) {
+            $where['o.pay_method'] = $this->request->get('pay_method');
+        }
+
+        if (!empty($this->request->get('date_range'))) {
+            $dateRange = $this->request->get('date_range');
+            $dateArr = explode(' - ', $dateRange);
+            if (count($dateArr) == 2) {
+                $startDate = $dateArr[0];
+                $endDate = $dateArr[1];
+                $where[] = ['o.order_time', '>=', $startDate . ' 00:00:00'];
+                $where[] = ['o.order_time', '<=', $endDate . ' 23:59:59'];
+            }
+        }
+
+        return $where;
+    }
+
+    /**
+     * 构建排序
+     * @return array
+     */
+    private function buildOrder(): array
+    {
+        $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['o.order_time'] = 'desc';
+        }
+        return $order;
+    }
+
+    /**
+     * 使用PhpSpreadsheet导出Excel文件
+     * @return void
+     */
+    public function export(): void
+    {
+        // 获取查询条件
+        $where = $this->buildWhere();
+        $order = $this->buildOrder();
+
+        // 查询所有数据
+        $data = Db::name('order_item')
+            ->alias('oi')
+            ->leftJoin('order o', 'oi.order_id = o.id')
+            ->leftJoin('user_on u', 'o.user_id = u.id')
+            ->leftJoin('user_on du', 'o.distributor_id = du.id')
+            ->field('
+            o.order_no as 订单编号,
+            DATE(o.order_time) as 日期,
+            oi.item_name as 商品名称,
+            oi.quantity as 购买数量,
+            oi.unit_price as 商品单价,
+            u.name as 会员名称,
+            o.pay_amount as 支付金额,
+            o.pay_method as 支付方式,
+            o.pay_status as 支付状态,
+            o.commission_amount as 最后佣金,
+            du.name as 分佣人名称,
+            o.order_time as 下单时间,
+            o.pay_time as 支付时间
+        ')
+            ->where($where)
+            ->order($order)
+            ->select()
+            ->toArray();
+
+        if (empty($data)) {
+            $this->error(__('没有找到符合条件的数据'));
+        }
+
+        // 转换字段格式
+        foreach ($data as &$item) {
+            // 支付方式转换
+            $payMethodMap = [
+                'wechat' => '微信支付',
+                'alipay' => '支付宝',
+                'bank' => '银行卡',
+                'balance' => '余额支付'
+            ];
+            $item['支付方式'] = $payMethodMap[$item['支付方式']] ?? $item['支付方式'];
+
+            // 支付状态转换
+            $payStatusMap = [
+                0 => '待支付',
+                1 => '已支付',
+                2 => '支付失败',
+                3 => '已取消'
+            ];
+            $item['支付状态'] = $payStatusMap[$item['支付状态']] ?? $item['支付状态'];
+
+            // 格式化金额(PhpSpreadsheet会自动处理数字格式)
+            $item['商品单价'] = (float)$item['商品单价'];
+            $item['支付金额'] = (float)$item['支付金额'];
+            $item['最后佣金'] = (float)$item['最后佣金'];
+
+            // 格式化时间
+            if ($item['下单时间']) {
+                $item['下单时间'] = date('Y-m-d H:i:s', strtotime($item['下单时间']));
+            }
+            if ($item['支付时间']) {
+                $item['支付时间'] = date('Y-m-d H:i:s', strtotime($item['支付时间']));
+            }
+        }
+
+        try {
+            $spreadsheet = new Spreadsheet();
+            $sheet = $spreadsheet->getActiveSheet();
+
+            // 定义表头
+            $headers = [
+                '订单编号', '日期', '商品名称', '购买数量', '商品单价',
+                '会员名称', '支付金额', '支付方式', '支付状态',
+                '最后佣金', '分佣人名称', '下单时间', '支付时间'
+            ];
+
+            // 设置表头
+            $col = 'A';
+            foreach ($headers as $header) {
+                $sheet->setCellValue($col . '1', $header);
+
+                // 设置表头加粗和背景色
+                $sheet->getStyle($col . '1')->getFont()->setBold(true);
+                $sheet->getStyle($col . '1')->getFill()
+                    ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
+                    ->getStartColor()->setRGB('D9D9D9');
+
+                $col++;
+            }
+
+            // 填充数据
+            $row = 2;
+            foreach ($data as $item) {
+                $col = 'A';
+                foreach ($item as $value) {
+                    $cellAddress = $col . $row;
+
+                    // 特殊处理订单编号(防止科学计数法)
+                    if ($col === 'A') {
+                        $sheet->setCellValueExplicit($cellAddress, $value, DataType::TYPE_STRING);
+                        $sheet->getStyle($cellAddress)->getNumberFormat()->setFormatCode('@');
+                    } else {
+                        $sheet->setCellValue($cellAddress, $value);
+                    }
+                    $col++;
+                }
+                $row++;
+            }
+
+            // 设置列宽自适应
+            $lastColumn = $sheet->getHighestColumn();
+            for ($col = 'A'; $col <= $lastColumn; $col++) {
+                $sheet->getColumnDimension($col)->setAutoSize(true);
+            }
+
+            // 生成文件名
+            $fileName = '订单数据_' . date('YmdHis') . '.xlsx';
+
+            // 清除输出缓冲区
+            ob_clean();
+
+            // 设置HTTP头
+            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
+            header('Content-Disposition: attachment;filename="' . $fileName . '"');
+            header('Cache-Control: max-age=0');
+
+            // 输出到浏览器
+            $writer = new Xlsx($spreadsheet);
+            $writer->save('php://output');
+
+            exit;
+
+        } catch (\Exception $e) {
+            $this->error('导出失败:' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 获取订单状态选项
+     * @return void
+     */
+    public function statusOptions(): void
+    {
+        $options = [
+            ['value' => 0, 'label' => '待支付'],
+            ['value' => 1, 'label' => '已支付'],
+            ['value' => 2, 'label' => '支付失败'],
+            ['value' => 3, 'label' => '已取消']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 获取支付方式选项
+     * @return void
+     */
+    public function payMethodOptions(): void
+    {
+        $options = [
+            ['value' => 'wechat', 'label' => '微信'],
+            ['value' => 'alipay', 'label' => '支付宝'],
+            ['value' => 'bank', 'label' => '银行卡'],
+            ['value' => 'balance', 'label' => '余额']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+
+    /**
+     * 获取支付方式文本
+     * @param string $method
+     * @return string
+     */
+    private function getPayMethodText(string $method): string
+    {
+        $map = [
+            'wechat' => '微信支付',
+            'alipay' => '支付宝',
+            'bank' => '银行卡',
+            'balance' => '余额支付'
+        ];
+        return $map[$method] ?? $method;
+    }
+
+    /**
+     * 获取支付状态文本
+     * @param int $status
+     * @return string
+     */
+    private function getPayStatusText(int $status): string
+    {
+        $map = [
+            0 => '待支付',
+            1 => '已支付',
+            2 => '支付失败',
+            3 => '已取消'
+        ];
+        return $map[$status] ?? '未知';
+    }
+
+}

+ 353 - 0
app/admin/controller/order/Withdrawal.php

@@ -0,0 +1,353 @@
+<?php
+
+namespace app\admin\controller\order;
+
+use app\common\controller\Backend;
+use think\facade\Db;
+
+class Withdrawal extends Backend
+{
+    protected array $noNeedLogin = ['*'];
+
+    /**
+     * 提现申请列表
+     * @return void
+     */
+    public function index(): void
+    {
+        $where = [];
+
+        // 申请人搜索
+        if (!empty($this->request->get('applicant_name'))) {
+            $applicantName = $this->request->get('applicant_name');
+            $where[] = ['u.name', 'like', '%' . $applicantName . '%'];
+        }
+
+        // 状态筛选
+        if ($this->request->get('status') !== '' && $this->request->get('status') !== null) {
+            $where['wr.status'] = $this->request->get('status');
+        }
+
+        // 提现方式筛选
+        if (!empty($this->request->get('withdrawal_method'))) {
+            $where['wr.withdrawal_method'] = $this->request->get('withdrawal_method');
+        }
+
+        //查询时间范围
+        $star_time = $this->request->get('star_time');
+        $end_time = $this->request->get('end_time');
+        if (!empty($star_time) && !empty($end_time)) {
+        $where[] = ['wr.create_time', 'between', [$star_time, $end_time], 'AND'];
+        }
+
+
+        // 排序
+        $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['wr.create_time'] = 'desc';
+        }
+
+        // 分页
+        $page = $this->request->get('page', 1);
+        $limit = $this->request->get('limit', 20);
+
+        // 查询数据
+        $withdrawalList = Db::name('withdrawal_record')
+            ->alias('wr')
+            ->leftJoin('user_on u', 'wr.user_id = u.id')
+            ->field('
+                wr.id,
+                u.name,
+                wr.amount,
+                wr.current_balance,
+                wr.withdrawal_method,
+                wr.status,
+                wr.create_time,
+                wr.audit_time,
+                wr.audit_remark,
+                wr.user_id,
+                wr.withdrawal_no
+            ')
+            ->where($where)
+            ->order($order)
+            ->paginate([
+                'list_rows' => $limit,
+                'page' => $page
+            ]);
+
+        // 转换字段格式
+        $list = $withdrawalList->items();
+        foreach ($list as &$item) {
+            // 提现方式转换
+            $item['withdrawal_method'] = $this->getWithdrawalMethodText($item['withdrawal_method']);
+
+            // 状态转换
+            $item['status_text'] = $this->getStatusText($item['status']);
+
+            // 格式化金额
+            $item['amount'] = number_format($item['amount'], 2);
+            $item['current_balance'] = number_format($item['current_balance'], 2);
+
+            // 格式化时间
+            if ($item['create_time']) {
+                $item['create_time'] = date('Y-m-d H:i:s', strtotime($item['create_time']));
+            }
+            if ($item['audit_time']) {
+                $item['audit_time'] = date('Y-m-d H:i:s', strtotime($item['audit_time']));
+            }
+        }
+
+        $this->success('查询成功', [
+            'list' => $list,
+            'total' => $withdrawalList->total()
+        ]);
+    }
+
+    /**
+     * 审核通过
+     * @return void
+     */
+    public function approve(): void
+    {
+        $id = $this->request->post('id');
+        $auditRemark = $this->request->post('audit_remark', '');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        try {
+            Db::startTrans();
+
+            // 获取提现记录
+            $withdrawalRecord = Db::name('withdrawal_record')
+                ->where('id', $id)
+                ->lock(true)
+                ->find();
+
+            if (!$withdrawalRecord) {
+                throw new \Exception('提现记录不存在');
+            }
+
+            if ($withdrawalRecord['status'] != 0) {
+                throw new \Exception('只有待审核的记录才能审核');
+            }
+
+            // 检查用户佣金是否足够
+            $userCommission = Db::name('user_commission')
+                ->where('user_id', $withdrawalRecord['user_id'])
+                ->lock(true)
+                ->find();
+            if (!$userCommission || $userCommission['current_commission'] < $withdrawalRecord['amount']) {
+                throw new \Exception('用户佣金不足');
+            }
+
+            // 更新提现记录状态
+            $updateData = [
+                'status' => 1, // 审核通过
+                'auditor_id' => $this->auth->id ?? 0,
+                'audit_time' => date('Y-m-d H:i:s'),
+                'audit_remark' => $auditRemark,
+                'balance_after' => Db::raw('current_balance - ' . $withdrawalRecord['amount']),
+                'update_time' => date('Y-m-d H:i:s')
+            ];
+
+            $result = Db::name('withdrawal_record')
+                ->where('id', $id)
+                ->update($updateData);
+
+            if (!$result) {
+                throw new \Exception('更新提现记录失败');
+            }
+
+            // 更新用户佣金(扣除已提现金额)
+            Db::name('user_commission')
+                ->where('user_id', $withdrawalRecord['user_id'])
+                ->update([
+                    'current_commission' => Db::raw('current_commission - ' . $withdrawalRecord['amount']),
+                    'update_time' => date('Y-m-d H:i:s')
+                ]);
+
+            Db::commit();
+
+
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error('审核失败: ' . $e->getMessage());
+        }
+
+        $this->success('审核通过');
+    }
+
+    /**
+     * 审核拒绝
+     * @return void
+     */
+    public function reject(): void
+    {
+        $id = $this->request->post('id');
+        $auditRemark = $this->request->post('audit_remark', '');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        if (empty($auditRemark)) {
+            $this->error(__('请填写拒绝原因'));
+        }
+
+        try {
+            // 获取提现记录
+            $withdrawalRecord = Db::name('withdrawal_record')
+                ->where('id', $id)
+                ->find();
+            if (!$withdrawalRecord) {
+                throw new \Exception ('提现记录不存在');
+            }
+
+            if ($withdrawalRecord['status'] != 0) {
+                throw new \Exception ('只有待审核的记录才能审核');
+            }
+            // 更新提现记录状态
+            $result = Db::name('withdrawal_record')
+                ->where('id', $id)
+                ->update([
+                    'status' => 2, // 审核拒绝
+                    'auditor_id' => $this->auth->id ?? 0,
+                    'audit_time' => date('Y-m-d H:i:s'),
+                    'audit_remark' => $auditRemark,
+                    'update_time' => date('Y-m-d H:i:s')
+                ]);
+
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+        if ($result) {
+            $this->success('审核拒绝成功');
+        } else {
+            $this->error(__('审核拒绝失败'));
+        }
+    }
+
+    /**
+     * 获取提现方式文本
+     * @param string $method
+     * @return string
+     */
+    private function getWithdrawalMethodText(string $method): string
+    {
+        $map = [
+            'wechat' => '微信',
+            'alipay' => '支付宝',
+            'bank' => '银行卡'
+        ];
+        return $map[$method] ?? $method;
+    }
+
+    /**
+     * 获取状态文本
+     * @param int $status
+     * @return string
+     */
+    private function getStatusText(int $status): string
+    {
+        $map = [
+            0 => '待审核',
+            1 => '审核通过',
+            2 => '审核拒绝',
+            3 => '已打款',
+            4 => '打款失败'
+        ];
+        return $map[$status] ?? '未知';
+    }
+
+    /**
+     * 获取提现状态选项
+     * @return void
+     */
+    public function statusOptions(): void
+    {
+        $options = [
+            ['value' => 0, 'label' => '待审核'],
+            ['value' => 1, 'label' => '审核通过'],
+            ['value' => 2, 'label' => '审核拒绝'],
+            ['value' => 3, 'label' => '已打款'],
+            ['value' => 4, 'label' => '打款失败']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 获取提现方式选项
+     * @return void
+     */
+    public function methodOptions(): void
+    {
+        $options = [
+            ['value' => 'wechat', 'label' => '微信'],
+            ['value' => 'alipay', 'label' => '支付宝'],
+            ['value' => 'bank', 'label' => '银行卡']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 提现统计
+     * @return void
+     */
+    public function statistics(): void
+    {
+        // 总提现申请数
+        $totalCount = Db::name('withdrawal_record')->count();
+
+        // 待审核数
+        $pendingCount = Db::name('withdrawal_record')
+            ->where('status', 0)
+            ->count();
+
+        // 已通过数
+        $approvedCount = Db::name('withdrawal_record')
+            ->where('status', 1)
+            ->count();
+
+        // 已拒绝数
+        $rejectedCount = Db::name('withdrawal_record')
+            ->where('status', 2)
+            ->count();
+
+        // 总提现金额
+        $totalAmount = Db::name('withdrawal_record')
+            ->where('status', 1) // 只计算审核通过的
+            ->sum('amount');
+
+        // 今日提现统计
+        $todayStart = date('Y-m-d 00:00:00');
+        $todayEnd = date('Y-m-d 23:59:59');
+        $todayCount = Db::name('withdrawal_record')
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->count();
+
+        $todayAmount = Db::name('withdrawal_record')
+            ->whereBetween('create_time', [$todayStart, $todayEnd])
+            ->where('status', 1)
+            ->sum('amount');
+
+        $stats = [
+            'total_count' => $totalCount,
+            'pending_count' => $pendingCount,
+            'approved_count' => $approvedCount,
+            'rejected_count' => $rejectedCount,
+            'total_amount' => number_format($totalAmount ?? 0, 2),
+            'today_count' => $todayCount,
+            'today_amount' => number_format($todayAmount ?? 0, 2)
+        ];
+
+        $this->success('获取成功', $stats);
+    }
+}

+ 101 - 135
app/admin/controller/package/Package.php

@@ -44,25 +44,17 @@ class Package extends Backend
             $order_a = explode(',', $order_a);
             $order[$order_a[0]] = $order_a[1];
         } else {
-            $order['p.sort'] = 'asc';
-            $order['p.id'] = 'desc';
+            $order['sort'] = 'asc';
+            $order['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([
@@ -70,14 +62,35 @@ class Package extends Backend
                 'page' => $page
             ]);
 
-        // 转换功能特性字段
+        // 为每个套餐计算库存状态
         $list = $packageList->items();
-        foreach ($list as &$item) {
-            if (!empty($item['features'])) {
-                $item['features'] = json_decode($item['features'], true);
+        foreach ($list as &$package) {
+            // 获取该套餐的所有规格
+            $specs = Db::name('package_price')
+                ->where('package_id', $package['id'])
+                ->select()
+                ->toArray();
+
+            // 计算总库存和总已售
+            $totalStock = 0;
+            $totalSold = 0;
+            foreach ($specs as $spec) {
+                $totalStock += $spec['stock'];
+                $totalSold += $spec['sold_count'];
+            }
+
+            // 根据库存设置库存状态
+            if ($totalStock == 0) {
+                $package['stock_status'] = '售罄';
+            } elseif ($totalStock <= 10) {
+                $package['stock_status'] = '即将售罄';
             } else {
-                $item['features'] = [];
+                $package['stock_status'] = '充足';
             }
+
+            $package['remaining_stock'] = $totalStock;
+            $package['sold_count'] = $totalSold;
+            $package['spec_count'] = count($specs);
         }
 
         $this->success('查询成功', [
@@ -94,9 +107,7 @@ class Package extends Backend
     {
         $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);
 
@@ -116,16 +127,9 @@ class Package extends Backend
             $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')
@@ -250,13 +254,6 @@ class Package extends Backend
             $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)
@@ -264,43 +261,58 @@ class Package extends Backend
             ->select()
             ->toArray();
 
-        // 统计库存和销售情况
+        // 计算规格库存状态和汇总数据
         $totalStock = 0;
         $totalSold = 0;
-        foreach ($specList as $spec) {
-            $totalStock += $spec['stock'];
-            $totalSold += $spec['sold_count'];
-        }
+        $cardTypeMap = [
+            1 => '次卡',
+            2 => '按积分',
+            3 => '日卡',
+            4 => '周卡',
+            5 => '季卡',
+            6 => '月卡',
+            7 => '年卡'
+        ];
 
-        // 统计用户购买数量(如果user_package表存在)
-        $userPurchaseCount = 0;
-        try {
-            $userPurchaseCount = Db::name('user_package')
-                ->where('package_id', $id)
-                ->count();
-        } catch (\Exception $e) {
-            // 表不存在,设为0
-        }
+        $typeMap = [
+            1 => '个人套餐',
+            2 => '团队套餐',
+        ];
 
-        // 统计企业购买数量(如果company_package表存在)
-        $companyPurchaseCount = 0;
-        try {
-            $companyPurchaseCount = Db::name('company_package')
-                ->where('package_id', $id)
-                ->count();
-        } catch (\Exception $e) {
-            // 表不存在,设为0
+        foreach ($specList as &$spec) {
+            // 计算库存状态
+            if ($spec['stock'] == 0) {
+                $spec['stock_status'] = '售罄';
+            } elseif ($spec['stock'] <= 10) {
+                $spec['stock_status'] = '即将售罄';
+            } else {
+                $spec['stock_status'] = '充足';
+            }
+
+            // 翻译类型和卡类型
+            $spec['type_text'] = $typeMap[$spec['type']] ?? '未知';
+            $spec['card_type_text'] = $cardTypeMap[$spec['card_type']] ?? '未知';
+
+            // 格式化收费方式显示
+            if ($spec['card_type'] == 1 && $spec['unit_value'] > 0) {
+                $spec['charge_text'] = '按次数:' . $spec['unit_value'] . '次';
+            } elseif ($spec['card_type'] == 2 && $spec['points_value'] > 0) {
+                $spec['charge_text'] = '按积分:' . $spec['points_value'] . '积分';
+            } else {
+                $spec['charge_text'] = $spec['card_type_text'];
+            }
+
+            $totalStock += $spec['stock'];
+            $totalSold += $spec['sold_count'];
         }
 
         $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
+                'spec_count' => count($specList)
             ]
         ];
 
@@ -317,9 +329,11 @@ class Package extends Backend
         $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', '');
+        $type = $this->request->post('type', 1);
+        $cardType = $this->request->post('card_type', 1);
+        $unitValue = $this->request->post('unit_value', 0);
+        $pointsValue = $this->request->post('points_value', 0);
         $description = $this->request->post('description', '');
         $sort = $this->request->post('sort', 0);
 
@@ -331,6 +345,15 @@ class Package extends Backend
             $this->error(__('价格必须大于0'));
         }
 
+        // 验证条件
+        if ($cardType == 1 && $unitValue <= 0) {
+            $this->error(__('次卡类型必须填写有效次数'));
+        }
+
+        if ($cardType == 2 && $pointsValue <= 0) {
+            $this->error(__('积分类型必须填写有效积分数量'));
+        }
+
         // 检查套餐是否存在
         $packageInfo = Db::name('package')
             ->where('id', $packageId)
@@ -357,9 +380,11 @@ class Package extends Backend
             'package_id' => $packageId,
             'spec_name' => $specName,
             'price' => $price,
-            'original_price' => $originalPrice,
             'stock' => $stock,
+            'type' => $type,
+            'card_type' => $cardType,
             'unit_value' => $unitValue,
+            'points_value' => $pointsValue,
             'description' => $description,
             'sort' => $sort,
             'update_time' => date('Y-m-d H:i:s')
@@ -381,10 +406,10 @@ class Package extends Backend
                 $message = '新增成功';
             }
 
-
         } catch (\Exception $e) {
             $this->error('操作失败: ' . $e->getMessage());
         }
+
         if ($result) {
             $this->success($message, ['id' => $id]);
         } else {
@@ -435,10 +460,10 @@ class Package extends Backend
                 ->where('id', $id)
                 ->delete();
 
-
         } catch (\Exception $e) {
             $this->error('删除失败: ' . $e->getMessage());
         }
+
         if ($result) {
             $this->success('删除成功');
         } else {
@@ -492,10 +517,10 @@ class Package extends Backend
                     'update_time' => date('Y-m-d H:i:s')
                 ]);
 
-
         } catch (\Exception $e) {
             $this->error('操作失败: ' . $e->getMessage());
         }
+
         if ($result) {
             $statusText = $status == 1 ? '启用' : '禁用';
             $this->success("成功{$statusText}{$result}个套餐");
@@ -529,10 +554,10 @@ class Package extends Backend
                     'update_time' => date('Y-m-d H:i:s')
                 ]);
 
-
         } catch (\Exception $e) {
             $this->error('操作失败: ' . $e->getMessage());
         }
+
         if ($result) {
             $this->success("成功更新{$result}个规格的库存");
         } else {
@@ -570,14 +595,19 @@ class Package extends Backend
     }
 
     /**
-     * 获取规格状态选项
+     * 获取卡类型选项
      * @return void
      */
-    public function specStatusOptions():void
+    public function cardTypeOptions():void
     {
         $options = [
-            ['value' => 1, 'label' => '正常'],
-            ['value' => 2, 'label' => '售罄']
+            ['value' => 1, 'label' => '次卡'],
+            ['value' => 2, 'label' => '按积分'],
+            ['value' => 3, 'label' => '日卡'],
+            ['value' => 4, 'label' => '周卡'],
+            ['value' => 5, 'label' => '季卡'],
+            ['value' => 6, 'label' => '月卡'],
+            ['value' => 7, 'label' => '年卡']
         ];
 
         $this->success('获取成功', $options);
@@ -608,79 +638,17 @@ class Package extends Backend
         $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
+            'total_sold' => $totalSold
         ];
 
         $this->success('获取成功', $stats);
     }
 
-    /**
-     * 导出套餐数据
-     * @return void
-     */
-    public function export():void
-    {
-        $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
@@ -689,7 +657,7 @@ class Package extends Backend
     {
         $packageList = Db::name('package')
             ->where('status', 1)
-            ->field('id as value, name as label, type')
+            ->field('id as value, name as label')
             ->order('sort', 'asc')
             ->order('id', 'asc')
             ->select()
@@ -712,16 +680,14 @@ class Package extends Backend
 
         $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')
+            ->field('id as value, spec_name as label, price, stock, type, card_type, unit_value, points_value, description')
             ->order('sort', 'asc')
             ->select()
             ->toArray();
 
         $this->success('获取成功', $specList);
     }
-
     /**
      * 更新规格销售数量(模拟用户购买)
      * @return void

+ 51 - 85
app/admin/controller/package/Product.php

@@ -6,6 +6,7 @@
 namespace app\admin\controller\package;
 
 use app\common\controller\Backend;
+use ba\Filesystem;
 use think\facade\Db;
 
 class Product extends Backend
@@ -31,6 +32,11 @@ class Product extends Backend
             $code = $this->request->get('code');
             $where[] = ['p.code', 'like', '%' . $code . '%'];
         }
+        // 产品类型筛选
+        if (!empty($this->request->get('type'))) {
+            $type = $this->request->get('type');
+            $where['p.type'] = $type;
+        }
 
         // 分类筛选
         if (!empty($this->request->get('category_id'))) {
@@ -60,38 +66,35 @@ class Product extends Backend
             $order['p.sort'] = 'asc';
             $order['p.id'] = 'desc';
         }
-
         // 分页
-        $page = $this->request->get('page', 1);
-        $limit = $this->request->get('limit', 20);
-
+        $page = $this->request->param('page', 1);
+        $limit = $this->request->param('limit', 20);
         // 查询数据
         $productList = Db::name('product')
             ->alias('p')
-            ->leftJoin('product_category pc', 'p.category_id = pc.id')
-            ->field('p.*, pc.name as category_name')
+            ->leftJoin('package pk', 'p.package_id = pk.id')
+            ->field('p.*, pk.name as package_name')
             ->where($where)
             ->order($order)
             ->paginate([
                 'list_rows' => $limit,
                 'page' => $page
             ]);
-
         // 转换图片字段
         $list = $productList->items();
-        foreach ($list as &$item) {
-            if (!empty($item['image'])) {
-                $item['image'] = json_decode($item['image'], true);
-            } else {
-                $item['image'] = [];
-            }
-
-            if (!empty($item['key_attributes'])) {
-                $item['key_attributes'] = json_decode($item['key_attributes'], true);
-            } else {
-                $item['key_attributes'] = [];
-            }
-        }
+//        foreach ($list as &$item) {
+//            if (!empty($item['image'])) {
+//                $item['image'] = json_decode($item['image'], true);
+//            } else {
+//                $item['image'] = [];
+//            }
+//
+//            if (!empty($item['key_attributes'])) {
+//                $item['key_attributes'] = json_decode($item['key_attributes'], true);
+//            } else {
+//                $item['key_attributes'] = [];
+//            }
+//        }
 
         $this->success('查询成功', [
             'list' => $list,
@@ -107,8 +110,8 @@ class Product extends Backend
     {
         $id = $this->request->post('id');
         $name = $this->request->post('name');
-        $code = $this->request->post('code');
-        $categoryId = $this->request->post('category_id');
+//        $code = $this->request->post('code');
+        $packageId = $this->request->post('package_id');
         $description = $this->request->post('description', '');
         $detail = $this->request->post('detail', '');
         $keyAttributes = $this->request->post('key_attributes', []);
@@ -116,27 +119,28 @@ class Product extends Backend
         $stockStatus = $this->request->post('stock_status', 1);
         $status = $this->request->post('status', 1);
         $sort = $this->request->post('sort', 0);
+        $type = $this->request->post('type', 0);
+        $link = $this->request->post('link', 0);
 
         if (empty($name)) {
             $this->error(__('产品名称不能为空'));
         }
 
-        if (empty($code)) {
-            $this->error(__('产品编码不能为空'));
+        if (empty($link)) {
+            $this->error(__('产品链接不能为空'));
         }
-
-        // 验证产品编码是否已存在(编辑时排除自己)
-        $checkCode = Db::name('product')
-            ->where('code', $code);
-
-        if (!empty($id)) {
-            $checkCode->where('id', '<>', $id);
+        if (empty($packageId)) {
+            $this->error(__('请选择套餐'));
         }
 
-        if ($checkCode->find()) {
-            $this->error(__('产品编码已存在'));
-        }
+        // 验证套餐是否存在
+        $packageInfo = Db::name('package')
+            ->where('id', $packageId)
+            ->find();
 
+        if (!$packageInfo) {
+            $this->error(__('选择的套餐不存在'));
+        }
         // 处理图片和属性字段
         if (empty($image)) {
             $image = "";
@@ -148,8 +152,8 @@ class Product extends Backend
 
         $data = [
             'name' => $name,
-            'code' => $code,
-            'category_id' => $categoryId ?: null,
+//            'code' => $code,
+            'package_id' => $packageId ?: null,
             'description' => $description,
             'detail' => $detail,
             'key_attributes' => json_encode($keyAttributes, JSON_UNESCAPED_UNICODE),
@@ -157,6 +161,8 @@ class Product extends Backend
             'stock_status' => $stockStatus,
             'status' => $status,
             'sort' => $sort,
+            'type' => $type,
+            'link' =>$link,
             'update_time' => date('Y-m-d H:i:s')
         ];
         try {
@@ -205,15 +211,6 @@ class Product extends Backend
             $this->error(__('参数错误'));
         }
 
-        // 检查是否有套餐关联
-        $hasPackage = Db::name('package')
-            ->where('product_id', $id)
-            ->count();
-
-        if ($hasPackage > 0) {
-            $this->error(__('该产品下有关联的套餐,请先删除套餐'));
-        }
-
         // 检查是否有订单关联
         $hasOrder = Db::name('order_item')
             ->where('product_id', $id)
@@ -224,24 +221,14 @@ class Product extends Backend
         }
 
         try {
-            Db::startTrans();
-
-            // 删除产品
             $result = Db::name('product')
                 ->where('id', $id)
                 ->delete();
 
-            // 删除产品规格
-            Db::name('product_spec')
-                ->where('product_id', $id)
-                ->delete();
-
-            Db::commit();
-
         } catch (\Exception $e) {
-            Db::rollback();
             $this->error('删除失败: ' . $e->getMessage());
         }
+
         if ($result) {
             $this->success('删除成功');
         } else {
@@ -264,45 +251,25 @@ class Product extends Backend
         // 获取产品基础信息
         $productInfo = Db::name('product')
             ->alias('p')
-            ->leftJoin('product_category pc', 'p.category_id = pc.id')
+            ->leftJoin('package pk', 'p.package_id = pk.id')
             ->where('p.id', $id)
-            ->field('p.*, pc.name as category_name')
+            ->field('p.*, pk.name as package_name, pk.type as package_type')
             ->find();
 
         if (!$productInfo) {
             $this->error(__('产品不存在'));
         }
 
-        if (empty($productInfo['image'])) {
-            $productInfo['image'] = [];
-        }
 
-        if (!empty($productInfo['key_attributes'])) {
-            $productInfo['key_attributes'] = json_decode($productInfo['key_attributes'], true);
-        } else {
-            $productInfo['key_attributes'] = [];
-        }
-
-        // 获取产品规格
-        $specList = Db::name('product_spec')
-            ->where('product_id', $id)
+        // 获取所属套餐下的其他产品
+        $samePackageProducts = Db::name('product')
+            ->where('package_id', $productInfo['package_id'])
+            ->where('id', '<>', $id)
+            ->field('id, name, code')
             ->order('sort', 'asc')
             ->select()
             ->toArray();
 
-        foreach ($specList as &$spec) {
-            if (!empty($spec['value'])) {
-                $spec['value'] = json_decode($spec['value'], true);
-            } else {
-                $spec['value'] = [];
-            }
-        }
-
-        // 获取关联套餐数量
-        $packageCount = Db::name('package')
-            ->where('product_id', $id)
-            ->count();
-
         // 获取订单数量
         $orderCount = Db::name('order_item')
             ->where('product_id', $id)
@@ -310,8 +277,7 @@ class Product extends Backend
 
         $result = [
             'product_info' => $productInfo,
-            'spec_list' => $specList,
-            'package_count' => $packageCount,
+            'same_package_products' => $samePackageProducts,
             'order_count' => $orderCount
         ];
 

+ 539 - 0
app/admin/controller/pay/AccountConfig.php

@@ -0,0 +1,539 @@
+<?php
+/**
+ * 提现账户配置控制器(客户银行卡配置)
+ */
+namespace app\admin\controller\pay;
+
+use app\common\controller\Backend;
+use think\facade\Db;
+
+class AccountConfig extends Backend
+{
+    protected array $noNeedLogin = ['*'];
+
+    /**
+     * 提现账户列表
+     * @return void
+     */
+    public function index(): void
+    {
+        $where = [];
+
+        // 用户ID搜索
+        if (!empty($this->request->get('user_id'))) {
+            $where['wac.user_id'] = $this->request->get('user_id');
+        }
+
+        // 账户类型筛选
+        if (!empty($this->request->get('account_type'))) {
+            $where['wac.account_type'] = $this->request->get('account_type');
+        }
+
+        // 银行名称搜索
+        if (!empty($this->request->get('bank_name'))) {
+            $where[] = ['wac.bank_name', 'like', '%' . $this->request->get('bank_name') . '%'];
+        }
+
+        // 账户姓名搜索
+        if (!empty($this->request->get('account_name'))) {
+            $where[] = ['wac.account_name', 'like', '%' . $this->request->get('account_name') . '%'];
+        }
+
+        // 状态筛选
+        if ($this->request->get('status') !== '' && $this->request->get('status') !== null) {
+            $where['wac.status'] = $this->request->get('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['wac.create_time'] = 'desc';
+        }
+
+        // 分页
+        $page = $this->request->get('page', 1);
+        $limit = $this->request->get('limit', 20);
+
+        // 查询数据
+        $accountList = Db::name('withdrawal_account_config')
+            ->alias('wac')
+            ->leftJoin('user_on u', 'wac.user_id = u.id')
+            ->field('
+                wac.id,
+                wac.user_id,
+                u.name as user_name,
+                wac.account_type,
+                wac.account_name,
+                wac.bank_name,
+                wac.bank_branch,
+                wac.bank_province,
+                wac.bank_city,
+                wac.card_number,
+                wac.alipay_account,
+                wac.wechat_account,
+                wac.is_default,
+                wac.status,
+                wac.remark,
+                wac.create_time,
+                wac.update_time
+            ')
+            ->where($where)
+            ->order($order)
+            ->paginate([
+                'list_rows' => $limit,
+                'page' => $page
+            ]);
+
+        $list = $accountList->items();
+        foreach ($list as &$item) {
+            // 添加账户类型文本
+            $item['account_type_text'] = $this->getAccountTypeText($item['account_type']);
+
+            // 添加状态文本
+            $item['status_text'] = $item['status'] ? '启用' : '禁用';
+
+            // 添加默认账户文本
+            $item['is_default_text'] = $item['is_default'] ? '是' : '否';
+
+            // 部分掩码显示(保护隐私)
+            if ($item['card_number']) {
+                $item['card_number_masked'] = substr($item['card_number'], 0, 4) . '****' . substr($item['card_number'], -4);
+            }
+            if ($item['alipay_account']) {
+                // 支付宝邮箱掩码
+                if (strpos($item['alipay_account'], '@') !== false) {
+                    list($prefix, $domain) = explode('@', $item['alipay_account']);
+                    if (strlen($prefix) > 3) {
+                        $item['alipay_account_masked'] = substr($prefix, 0, 3) . '***@' . $domain;
+                    } else {
+                        $item['alipay_account_masked'] = $prefix . '***@' . $domain;
+                    }
+                } else {
+                    $item['alipay_account_masked'] = substr($item['alipay_account'], 0, 3) . '***';
+                }
+            }
+        }
+
+        $this->success('查询成功', [
+            'list' => $list,
+            'total' => $accountList->total()
+        ]);
+    }
+
+    /**
+     * 获取账户详情
+     * @return void
+     */
+    public function detail(): void
+    {
+        $id = $this->request->get('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        $account = Db::name('withdrawal_account_config')
+            ->alias('wac')
+            ->leftJoin('user_on u', 'wac.user_id = u.id')
+            ->where('wac.id', $id)
+            ->field('wac.*, u.name as user_name')
+            ->find();
+
+        if (!$account) {
+            $this->error(__('账户不存在'));
+        }
+
+        // 添加账户类型文本
+        $account['account_type_text'] = $this->getAccountTypeText($account['account_type']);
+
+        $this->success('查询成功', $account);
+    }
+
+    /**
+     * 新增/编辑提现账户
+     * @return void
+     */
+    public function edit(): void
+    {
+        $id = $this->request->post('id');
+        $userId = $this->request->post('user_id');
+        $accountType = $this->request->post('account_type');
+        $accountName = $this->request->post('account_name');
+        $isDefault = $this->request->post('is_default', 0);
+        $status = $this->request->post('status', 1);
+        $remark = $this->request->post('remark', '');
+
+        // 根据账户类型接收不同的字段
+        $bankName = $this->request->post('bank_name', '');
+        $bankBranch = $this->request->post('bank_branch', '');
+        $bankProvince = $this->request->post('bank_province', '');
+        $bankCity = $this->request->post('bank_city', '');
+        $cardNumber = $this->request->post('card_number', '');
+        $alipayAccount = $this->request->post('alipay_account', '');
+        $wechatAccount = $this->request->post('wechat_account', '');
+
+        if (empty($userId)) {
+            $this->error(__('用户ID不能为空'));
+        }
+
+        if (empty($accountType)) {
+            $this->error(__('请选择账户类型'));
+        }
+
+        if (empty($accountName)) {
+            $this->error(__('账户姓名不能为空'));
+        }
+
+        // 验证用户是否存在
+        $userInfo = Db::name('user')
+            ->where('id', $userId)
+            ->find();
+
+        if (!$userInfo) {
+            $this->error(__('用户不存在'));
+        }
+
+        // 验证账户类型对应的必填字段
+        $validationResult = $this->validateAccountFields($accountType, [
+            'bank_name' => $bankName,
+            'card_number' => $cardNumber,
+            'alipay_account' => $alipayAccount,
+            'wechat_account' => $wechatAccount
+        ]);
+
+        if ($validationResult !== true) {
+            $this->error($validationResult);
+        }
+
+        // 验证银行卡号格式(如果是银行卡)
+        if ($accountType == 'bank' && !empty($cardNumber)) {
+            if (!preg_match('/^[0-9]{16,19}$/', $cardNumber)) {
+                $this->error(__('银行卡号格式不正确,应为16-19位数字'));
+            }
+        }
+
+        // 验证支付宝账号格式
+        if ($accountType == 'alipay' && !empty($alipayAccount)) {
+            if (!filter_var($alipayAccount, FILTER_VALIDATE_EMAIL) && !preg_match('/^1[3-9]\d{9}$/', $alipayAccount)) {
+                $this->error(__('支付宝账号应为邮箱或手机号格式'));
+            }
+        }
+
+        $data = [
+            'user_id' => $userId,
+            'account_type' => $accountType,
+            'account_name' => $accountName,
+            'bank_name' => $accountType == 'bank' ? $bankName : '',
+            'bank_branch' => $accountType == 'bank' ? $bankBranch : '',
+            'bank_province' => $accountType == 'bank' ? $bankProvince : '',
+            'bank_city' => $accountType == 'bank' ? $bankCity : '',
+            'card_number' => $accountType == 'bank' ? $cardNumber : '',
+            'alipay_account' => $accountType == 'alipay' ? $alipayAccount : '',
+            'wechat_account' => $accountType == 'wechat' ? $wechatAccount : '',
+            'is_default' => $isDefault,
+            'status' => $status,
+            'remark' => $remark,
+            'update_time' => date('Y-m-d H:i:s')
+        ];
+
+        try {
+            if (!empty($id)) {
+                // 编辑
+                $accountInfo = Db::name('withdrawal_account_config')
+                    ->where('id', $id)
+                    ->find();
+
+                if (!$accountInfo) {
+                    $this->error(__('账户不存在'));
+                }
+
+                // 如果设置为默认账户,需要取消该用户的其他默认账户
+                if ($isDefault == 1) {
+                    Db::name('withdrawal_account_config')
+                        ->where('user_id', $userId)
+                        ->where('id', '<>', $id)
+                        ->where('account_type', $accountType)
+                        ->update(['is_default' => 0]);
+                }
+
+                $result = Db::name('withdrawal_account_config')
+                    ->where('id', $id)
+                    ->update($data);
+                $message = '编辑成功';
+            } else {
+                // 新增
+                $data['create_time'] = date('Y-m-d H:i:s');
+
+                // 检查是否已存在相同账户
+                $existCheck = Db::name('withdrawal_account_config')
+                    ->where('user_id', $userId)
+                    ->where('account_type', $accountType);
+
+                if ($accountType == 'bank') {
+                    $existCheck->where('card_number', $cardNumber);
+                } elseif ($accountType == 'alipay') {
+                    $existCheck->where('alipay_account', $alipayAccount);
+                } elseif ($accountType == 'wechat') {
+                    $existCheck->where('wechat_account', $wechatAccount);
+                }
+
+                if ($existCheck->find()) {
+                    throw new \Exception('该账户已存在');
+                }
+
+                // 如果设置为默认账户,需要取消该用户的其他默认账户
+                if ($isDefault == 1) {
+                    Db::name('withdrawal_account_config')
+                        ->where('user_id', $userId)
+                        ->where('account_type', $accountType)
+                        ->update(['is_default' => 0]);
+                }
+
+                $result = Db::name('withdrawal_account_config')
+                    ->insert($data);
+                $id = Db::name('withdrawal_account_config')->getLastInsID();
+                $message = '新增成功';
+            }
+
+
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+
+
+        if ($result) {
+            $this->success($message, ['id' => $id]);
+        } else {
+            $this->error(__('操作失败'));
+        }
+    }
+
+    /**
+     * 删除提现账户
+     * @return void
+     */
+    public function delete(): void
+    {
+        $id = $this->request->post('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        $accountInfo = Db::name('withdrawal_account_config')
+            ->where('id', $id)
+            ->find();
+
+        if (!$accountInfo) {
+            $this->error(__('账户不存在'));
+        }
+
+        // 检查是否正在使用(如果有提现记录)
+        $hasWithdrawal = Db::name('withdrawal_record')
+            ->where('account_info', 'like', '%' . $accountInfo['card_number'] . '%')
+//            ->whereOr('account_info', 'like', '%' . $accountInfo['alipay_account'] . '%')
+//            ->whereOr('account_info', 'like', '%' . $accountInfo['wechat_account'] . '%')
+            ->find();
+        if ($hasWithdrawal) {
+            $this->error(__('该账户已有提现记录,不能删除'));
+        }
+
+        $result = Db::name('withdrawal_account_config')
+            ->where('id', $id)
+            ->delete();
+
+        if ($result) {
+            $this->success('删除成功');
+        } else {
+            $this->error(__('删除失败'));
+        }
+    }
+
+    /**
+     * 设置默认账户
+     * @return void
+     */
+    public function setDefault(): void
+    {
+        $id = $this->request->post('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        $accountInfo = Db::name('withdrawal_account_config')
+            ->where('id', $id)
+            ->find();
+
+        if (!$accountInfo) {
+            $this->error(__('账户不存在'));
+        }
+
+        try {
+            // 取消该用户同类型账户的其他默认设置
+            Db::name('withdrawal_account_config')
+                ->where('user_id', $accountInfo['user_id'])
+                ->where('account_type', $accountInfo['account_type'])
+                ->where('id', '<>', $id)
+                ->update(['is_default' => 0]);
+
+            // 设置当前账户为默认
+            $result = Db::name('withdrawal_account_config')
+                ->where('id', $id)
+                ->update([
+                    'is_default' => 1,
+                    'update_time' => date('Y-m-d H:i:s')
+                ]);
+
+            if ($result) {
+                $this->success('设置默认成功');
+            } else {
+                $this->error(__('设置失败'));
+            }
+
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+    }
+
+    /**
+     * 获取用户的提现账户列表
+     * @return void
+     */
+    public function getUserAccounts(): void
+    {
+        $userId = $this->request->get('user_id');
+
+        if (empty($userId)) {
+            $this->error(__('用户ID不能为空'));
+        }
+
+        $accounts = Db::name('withdrawal_account_config')
+            ->where('user_id', $userId)
+            ->where('status', 1)
+            ->order('is_default', 'desc')
+            ->order('create_time', 'desc')
+            ->select()
+            ->toArray();
+
+        foreach ($accounts as &$account) {
+            // 添加账户类型文本
+            $account['account_type_text'] = $this->getAccountTypeText($account['account_type']);
+
+            // 部分掩码显示
+            if ($account['card_number']) {
+                $account['card_number_masked'] = substr($account['card_number'], 0, 4) . '****' . substr($account['card_number'], -4);
+            }
+        }
+
+        $this->success('查询成功', $accounts);
+    }
+
+    /**
+     * 验证账户字段
+     * @param string $accountType 账户类型
+     * @param array $fields 字段值
+     * @return bool|string
+     */
+    private function validateAccountFields(string $accountType, array $fields): bool|string
+    {
+        if ($accountType == 'bank') {
+            if (empty($fields['bank_name'])) {
+                return '银行名称不能为空';
+            }
+            if (empty($fields['card_number'])) {
+                return '银行卡号不能为空';
+            }
+        } elseif ($accountType == 'alipay') {
+            if (empty($fields['alipay_account'])) {
+                return '支付宝账号不能为空';
+            }
+        } elseif ($accountType == 'wechat') {
+            if (empty($fields['wechat_account'])) {
+                return '微信账号不能为空';
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * 获取账户类型文本
+     * @param string $type
+     * @return string
+     */
+    private function getAccountTypeText(string $type): string
+    {
+        $map = [
+            'bank' => '银行卡',
+            'alipay' => '支付宝',
+            'wechat' => '微信'
+        ];
+        return $map[$type] ?? '未知类型';
+    }
+
+    /**
+     * 获取账户类型选项
+     * @return void
+     */
+    public function accountTypeOptions(): void
+    {
+        $options = [
+            ['value' => 'bank', 'label' => '银行卡'],
+            ['value' => 'alipay', 'label' => '支付宝'],
+            ['value' => 'wechat', 'label' => '微信']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 获取状态选项
+     * @return void
+     */
+    public function statusOptions(): void
+    {
+        $options = [
+            ['value' => 0, 'label' => '禁用'],
+            ['value' => 1, 'label' => '启用']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 获取银行列表(常见银行)
+     * @return void
+     */
+    public function bankList(): void
+    {
+        $banks = [
+            '中国工商银行',
+            '中国农业银行',
+            '中国银行',
+            '中国建设银行',
+            '交通银行',
+            '招商银行',
+            '中信银行',
+            '中国民生银行',
+            '中国光大银行',
+            '华夏银行',
+            '兴业银行',
+            '浦发银行',
+            '平安银行',
+            '广发银行',
+            '邮政储蓄银行'
+        ];
+
+        $options = [];
+        foreach ($banks as $bank) {
+            $options[] = ['value' => $bank, 'label' => $bank];
+        }
+
+        $this->success('获取成功', $options);
+    }
+}

+ 455 - 0
app/admin/controller/pay/Config.php

@@ -0,0 +1,455 @@
+<?php
+/**
+ * 支付配置控制器 - 字段单独存储版
+ */
+
+namespace app\admin\controller\pay;
+
+use app\common\controller\Backend;
+use think\facade\Db;
+
+class Config extends Backend
+{
+    protected array $noNeedLogin = ['*'];
+
+    /**
+     * 支付配置列表
+     * @return void
+     */
+    public function index(): void
+    {
+        $where = [];
+
+        // 配置名称搜索
+        if (!empty($this->request->get('name'))) {
+            $where[] = ['name', 'like', '%' . $this->request->get('name') . '%'];
+        }
+
+        // 支付类型筛选
+        if (!empty($this->request->get('type'))) {
+            $where['type'] = $this->request->get('type');
+        }
+
+        // 状态筛选
+        if ($this->request->get('status') !== '' && $this->request->get('status') !== null) {
+            $where['status'] = $this->request->get('status');
+        }
+
+        // 排序
+        $order = ['id' => 'desc'];
+
+        // 分页
+        $page = $this->request->get('page', 1);
+        $limit = $this->request->get('limit', 20);
+
+        $configList = Db::name('pay_config')
+            ->where($where)
+            ->order($order)
+            ->paginate([
+                'list_rows' => $limit,
+                'page' => $page
+            ]);
+
+        $list = $configList->items();
+        foreach ($list as &$item) {
+            // 添加类型文本
+            $item['type_text'] = $this->getTypeText($item['type']);
+            $item['status_text'] = $item['status'] ? '启用' : '禁用';
+        }
+
+        $this->success('查询成功', [
+            'list' => $list,
+            'total' => $configList->total()
+        ]);
+    }
+
+    /**
+     * 获取支付配置详情
+     * @return void
+     */
+    public function detail(): void
+    {
+        $id = $this->request->get('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        $config = Db::name('pay_config')
+            ->where('id', $id)
+            ->find();
+
+        if (!$config) {
+            $this->error(__('配置不存在'));
+        }
+
+        // 添加类型文本
+        $config['type_text'] = $this->getTypeText($config['type']);
+
+        $this->success('查询成功', $config);
+    }
+
+    /**
+     * 新增/编辑支付配置
+     * @return void
+     */
+    public function edit(): void
+    {
+        $id = $this->request->post('id');
+        $name = $this->request->post('name');
+        $type = $this->request->post('type', 1);
+        $status = $this->request->post('status', 0);
+
+        // 通用字段
+        $appId = $this->request->post('app_id', '');
+        $mchId = $this->request->post('mch_id', '');
+        $key = $this->request->post('key', '');
+        $notifyUrl = $this->request->post('notify_url', '');
+        $h5NotifyUrl = $this->request->post('h5_notify_url', '');
+
+        // 支付宝专用字段
+        $publicKeyPath = $this->request->post('public_key_path', '');
+        $privateKeyPath = $this->request->post('private_key_path', '');
+
+        if (empty($name)) {
+            $this->error(__('配置名称不能为空'));
+        }
+
+        if (empty($type)) {
+            $this->error(__('请选择支付类型'));
+        }
+
+        // 验证配置名称是否已存在(编辑时排除自己)
+        $checkName = Db::name('pay_config')
+            ->where('name', $name);
+
+        if (!empty($id)) {
+            $checkName->where('id', '<>', $id);
+        }
+
+        if ($checkName->find()) {
+            $this->error(__('配置名称已存在'));
+        }
+
+        // 验证必填字段
+        $validationResult = $this->validateFields($type, [
+            'app_id' => $appId,
+            'mch_id' => $mchId,
+            'key' => $key,
+            'notify_url' => $notifyUrl,
+            'h5_notify_url' => $h5NotifyUrl,
+            'public_key_path' => $publicKeyPath,
+            'private_key_path' => $privateKeyPath
+        ]);
+
+        if ($validationResult !== true) {
+            $this->error($validationResult);
+        }
+
+        $data = [
+            'name' => $name,
+            'type' => $type,
+            'app_id' => $appId,
+            'mch_id' => $mchId,
+            'key' => $key,
+            'notify_url' => $notifyUrl,
+            'h5_notify_url' => $h5NotifyUrl,
+            'public_key_path' => $type == 2 ? $publicKeyPath : '',
+            'private_key_path' => $type == 2 ? $privateKeyPath : '',
+            'status' => $status,
+            'update_time' => date('Y-m-d H:i:s')
+        ];
+
+        try {
+            if (!empty($id)) {
+                // 编辑
+                $configInfo = Db::name('pay_config')
+                    ->where('id', $id)
+                    ->find();
+
+                if (!$configInfo) {
+                    $this->error(__('配置不存在'));
+                }
+
+                // 如果启用此配置,需要禁用同类型的其他配置
+                if ($status == 1 && $configInfo['status'] == 0) {
+                    Db::name('pay_config')
+                        ->where('type', $type)
+                        ->where('id', '<>', $id)
+                        ->update(['status' => 0]);
+                }
+
+                $result = Db::name('pay_config')
+                    ->where('id', $id)
+                    ->update($data);
+                $message = '编辑成功';
+            } else {
+                // 新增
+                $data['create_time'] = date('Y-m-d H:i:s');
+
+                // 如果启用此配置,需要禁用同类型的其他配置
+                if ($status == 1) {
+                    Db::name('pay_config')
+                        ->where('type', $type)
+                        ->update(['status' => 0]);
+                }
+
+                $result = Db::name('pay_config')
+                    ->insert($data);
+                $id = Db::name('pay_config')->getLastInsID();
+                $message = '新增成功';
+            }
+
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+        if ($result) {
+            $this->success($message, ['id' => $id]);
+        } else {
+            $this->error(__('操作失败'));
+        }
+    }
+
+    /**
+     * 验证字段
+     * @param int $type 支付类型
+     * @param array $fields 字段值
+     * @return bool|string
+     */
+    private function validateFields(int $type, array $fields)
+    {
+        // 通用验证
+        if (empty($fields['app_id'])) {
+            return '应用ID不能为空';
+        }
+
+        if (empty($fields['mch_id'])) {
+            return '商户ID不能为空';
+        }
+
+        if (empty($fields['key'])) {
+            return 'API密钥不能为空';
+        }
+
+        // 类型特定验证
+        if ($type == 1) { // 微信支付
+            if (strlen($fields['key']) < 32) {
+                return '微信支付API密钥长度必须至少32位';
+            }
+        } elseif ($type == 2) { // 支付宝
+            if (empty($fields['private_key_path'])) {
+                return '支付宝私钥地址不能为空';
+            }
+        }
+
+        // URL验证
+        if (!empty($fields['notify_url']) && !filter_var($fields['notify_url'], FILTER_VALIDATE_URL)) {
+            return '支付通知地址格式不正确';
+        }
+
+        if (!empty($fields['h5_notify_url']) && !filter_var($fields['h5_notify_url'], FILTER_VALIDATE_URL)) {
+            return 'H5支付通知地址格式不正确';
+        }
+
+        return true;
+    }
+
+    /**
+     * 删除支付配置
+     * @return void
+     */
+    public function delete(): void
+    {
+        $id = $this->request->post('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        $configInfo = Db::name('pay_config')
+            ->where('id', $id)
+            ->find();
+
+        if (!$configInfo) {
+            $this->error(__('配置不存在'));
+        }
+
+        if ($configInfo['status'] == 1) {
+            $this->error(__('当前配置已启用,请先禁用后再删除'));
+        }
+
+        $result = Db::name('pay_config')
+            ->where('id', $id)
+            ->delete();
+
+        if ($result) {
+            $this->success('删除成功');
+        } else {
+            $this->error(__('删除失败'));
+        }
+    }
+
+    /**
+     * 启用/禁用配置
+     * @return void
+     */
+    public function toggleStatus(): void
+    {
+        $id = $this->request->post('id');
+
+        if (empty($id)) {
+            $this->error(__('参数错误'));
+        }
+
+        $configInfo = Db::name('pay_config')
+            ->where('id', $id)
+            ->find();
+
+        if (!$configInfo) {
+            $this->error(__('配置不存在'));
+        }
+
+        $newStatus = $configInfo['status'] == 1 ? 0 : 1;
+        $statusText = $newStatus ? '启用' : '禁用';
+
+        try {
+            // 如果启用此配置,需要禁用同类型的其他配置
+            if ($newStatus == 1) {
+                Db::name('pay_config')
+                    ->where('type', $configInfo['type'])
+                    ->where('id', '<>', $id)
+                    ->update(['status' => 0]);
+            }
+
+            $result = Db::name('pay_config')
+                ->where('id', $id)
+                ->update([
+                    'status' => $newStatus,
+                    'update_time' => date('Y-m-d H:i:s')
+                ]);
+
+
+        } catch (\Exception $e) {
+            $this->error('操作失败: ' . $e->getMessage());
+        }
+        if ($result) {
+            $this->success($statusText . '成功');
+        } else {
+            $this->error($statusText . '失败');
+        }
+    }
+
+    /**
+     * 获取支付类型文本
+     * @param int $type
+     * @return string
+     */
+    private function getTypeText(int $type): string
+    {
+        $map = [
+            1 => '微信支付',
+            2 => '支付宝支付'
+        ];
+        return $map[$type] ?? '未知类型';
+    }
+
+    /**
+     * 获取支付类型选项
+     * @return void
+     */
+    public function typeOptions(): void
+    {
+        $options = [
+            ['value' => 1, 'label' => '微信支付'],
+            ['value' => 2, 'label' => '支付宝支付']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 获取状态选项
+     * @return void
+     */
+    public function statusOptions(): void
+    {
+        $options = [
+            ['value' => 0, 'label' => '禁用'],
+            ['value' => 1, 'label' => '启用']
+        ];
+
+        $this->success('获取成功', $options);
+    }
+
+    /**
+     * 获取支付配置模板
+     * @return void
+     */
+    public function getTemplate(): void
+    {
+        $type = $this->request->get('type', 1);
+
+        if ($type == 1) { // 微信支付模板
+            $template = [
+                'name' => '微信支付配置',
+                'type' => 1,
+                'app_id' => 'wx1234567890abcdef',
+                'mch_id' => '1234567890',
+                'key' => 'your_wechat_api_key_32_characters_long',
+                'notify_url' => 'https://your-domain.com/api/pay/wechat/notify',
+                'h5_notify_url' => 'https://your-domain.com/api/pay/wechat/h5-notify',
+                'public_key_path' => '',
+                'private_key_path' => '',
+                'status' => 0
+            ];
+        } elseif ($type == 2) { // 支付宝模板
+            $template = [
+                'name' => '支付宝支付配置',
+                'type' => 2,
+                'app_id' => '2021000123456789',
+                'mch_id' => '2088101123456789',
+                'key' => 'your_alipay_api_key',
+                'notify_url' => 'https://your-domain.com/api/pay/alipay/notify',
+                'h5_notify_url' => 'https://your-domain.com/api/pay/alipay/h5-notify',
+                'public_key_path' => '/path/to/alipay/public_key.pem',
+                'private_key_path' => '/path/to/alipay/private_key.pem',
+                'status' => 0
+            ];
+        } else {
+            $template = [
+                'name' => '',
+                'type' => $type,
+                'app_id' => '',
+                'mch_id' => '',
+                'key' => '',
+                'notify_url' => '',
+                'h5_notify_url' => '',
+                'public_key_path' => '',
+                'private_key_path' => '',
+                'status' => 0
+            ];
+        }
+
+        $this->success('获取成功', $template);
+    }
+
+    /**
+     * 获取当前启用的配置
+     * @return void
+     */
+    public function getActiveConfig(): void
+    {
+        $type = $this->request->get('type', 1);
+
+        $config = Db::name('pay_config')
+            ->where('type', $type)
+            ->where('status', 1)
+            ->find();
+
+        if (!$config) {
+            $this->error('未找到启用的支付配置');
+        }
+
+        $this->success('获取成功', $config);
+    }
+}

+ 20 - 0
app/admin/controller/userCenter/Index.php

@@ -94,6 +94,9 @@ class Index extends  Backend
                 $result = Db::name('company')
                     ->where('id', $id)
                     ->update($data);
+                Db::name('user_on')
+                    ->where('company_id', $id)
+                    ->update(['company'=>$name]);
                 $message = '编辑成功';
             } else {
                 // 新增
@@ -143,6 +146,23 @@ class Index extends  Backend
         }
     }
 
+
+    /**
+     * 获取启用企业选项(用于下拉选择)
+     * @return void
+     */
+    public function selectOptions():void
+    {
+        $packageList = Db::name('company')
+            ->where('status', 1)
+            ->field('id,name')
+            ->select()
+            ->toArray();
+
+        $this->success('获取成功', $packageList);
+    }
+
+
     /**
      * 禁用/启用企业
      * @return void

+ 13 - 6
app/admin/controller/userCenter/User.php

@@ -21,25 +21,25 @@ class User extends Backend
         // 姓名搜索
         if (!empty($this->request->get('name'))) {
             $name = $this->request->get('name');
-            $where[] = ['name', 'like', '%' . $name . '%'];
+            $where[] = ['wac.name', 'like', '%' . $name . '%'];
         }
 
         // 邮箱搜索
         if (!empty($this->request->get('email'))) {
             $email = $this->request->get('email');
-            $where[] = ['email', 'like', '%' . $email . '%'];
+            $where[] = ['wac.email', 'like', '%' . $email . '%'];
         }
 
         // 企业搜索
         if (!empty($this->request->get('company'))) {
             $company = $this->request->get('company');
-            $where[] = ['company', 'like', '%' . $company . '%'];
+            $where[] = ['wac.company', 'like', '%' . $company . '%'];
         }
 
         // 状态筛选
         if (!empty($this->request->get('status'))) {
             $status = $this->request->get('status');
-            $where['status'] = $status;
+            $where['wac.status'] = $status;
         }
 
         // 排序
@@ -49,7 +49,7 @@ class User extends Backend
             $order_a = explode(',', $order_a);
             $order[$order_a[0]] = $order_a[1];
         } else {
-            $order['id'] = 'desc';
+            $order['wac.id'] = 'desc';
         }
 
         // 分页
@@ -57,7 +57,10 @@ class User extends Backend
         $limit = $this->request->get('limit', 20);
 
         $userList = Db::name('user_on')
+            ->alias('wac')
+            ->leftJoin('company u', 'wac.company_id = u.id')
             ->where($where)
+            ->field('wac.*, u.name as company_name')
             ->order($order)
             ->paginate([
                 'list_rows' => $limit,
@@ -70,6 +73,8 @@ class User extends Backend
         ]);
     }
 
+
+
     /**
      * 新增/编辑用户
      * @return void
@@ -81,6 +86,7 @@ class User extends Backend
         $email = $this->request->post('email');
         $password = $this->request->post('password');
         $company = $this->request->post('company');
+        $company_id = $this->request->post('company_id');
         $status = $this->request->post('status', 1);
 
         if (empty($name) || empty($email)) {
@@ -107,7 +113,8 @@ class User extends Backend
         $data = [
             'name' => $name,
             'email' => $email,
-            'company' => $company ?: null,
+            'company' => $company?: null,
+            'company_id' => $company_id?: null,
             'status' => $status,
             'update_time' => date('Y-m-d H:i:s')
         ];

+ 2 - 1
composer.json

@@ -29,7 +29,8 @@
         "ext-bcmath": "*",
         "ext-iconv": "*",
         "ext-json": "*",
-        "ext-gd": "*"
+        "ext-gd": "*",
+        "phpoffice/phpspreadsheet": "^2.1"
     },
     "require-dev": {
         "symfony/var-dumper": "^5.4",