WIN-2308041133\Administrator 1 month ago
parent
commit
030a1b4727

+ 105 - 0
app/admin/controller/store/DeviceRepair.php

@@ -0,0 +1,105 @@
+<?php
+
+namespace app\admin\controller\store;
+
+use app\admin\controller\AuthController;
+use think\Request;
+use think\facade\Route as Url;
+use app\admin\model\store\DeviceRepair as DeviceRepairModel; // 设备报修模型
+use crmeb\services\{JsonService as Json, UtilService as Util};
+
+/**
+ * 设备报修管理控制器
+ * Class DeviceRepair
+ * @package app\admin\controller\repair
+ */
+class DeviceRepair extends AuthController
+{
+    /**
+     * 显示报修列表页面
+     * @return \think\Response
+     */
+    public function index()
+    {
+        // 页面仅展示列表,无搜索框
+        return $this->fetch();
+    }
+
+    /**
+     * 异步获取报修列表(用于表格渲染)
+     * @return json
+     */
+    public function repair_list()
+    {
+        $where = Util::getMore([
+            ['handle_status', ''], // 处理状态筛选(空=全部,0=未处理,1=已处理)
+            ['page', 1],
+            ['limit', 20],
+            ['order', 'create_time DESC'] // 默认按提交时间倒序
+        ]);
+        // 调用模型获取列表(带分页)
+        return Json::successlayui(DeviceRepairModel::getAdminRepairList($where));
+    }
+
+    /**
+     * 核心处理功能:标记报修单为“已处理”/“未处理”
+     * @param int $handle_status 处理状态(1=已处理,0=未处理)
+     * @param int $id 报修单ID
+     * @return json
+     */
+    public function set_handle($handle_status = '', $id = '')
+    {
+        // 参数验证
+        if ($handle_status === '' || $id === '') {
+            return Json::fail('缺少参数:状态或ID不能为空');
+        }
+        // 验证状态值合法性
+        if (!in_array((int)$handle_status, [0, 1])) {
+            return Json::fail('状态值错误:仅支持0(未处理)或1(已处理)');
+        }
+        // 调用模型处理状态更新(传入当前管理员ID)
+        $adminId = $this->adminId; // 从AuthController继承的管理员ID
+        $result = DeviceRepairModel::markStatus($id, (int)$handle_status, $adminId);
+        if ($result) {
+            return Json::successful($handle_status == 1 ? '标记为已处理成功' : '标记为未处理成功');
+        } else {
+            return Json::fail(DeviceRepairModel::getError() ?: ($handle_status == 1 ? '标记已处理失败' : '标记未处理失败'));
+        }
+    }
+
+    /**
+     * 下载报修表单(CSV格式)
+     * @param int $id 报修单ID
+     * @return \think\response\Stream|\think\response\Redirect
+     */
+    public function download($id)
+    {
+        if (!$id) {
+            $this->error('请选择要下载的报修单');
+        }
+        // 调用模型生成下载文件流
+        $stream = DeviceRepairModel::createDownloadStream($id);
+        if (!$stream) {
+            $this->error(DeviceRepairModel::getError() ?: '报修单不存在或已删除');
+        }
+        return $stream;
+    }
+
+    /**
+     * 删除报修单
+     * @param int $id 报修单ID
+     * @return json
+     */
+    public function delete($id)
+    {
+        if (!$id) {
+            return Json::fail('请选择要删除的报修单');
+        }
+        // 调用模型删除
+        if (DeviceRepairModel::delRepair($id)) {
+            return Json::successful('删除成功');
+        } else {
+            return Json::fail(DeviceRepair::getError() ?: '删除失败,请稍后重试');
+        }
+    }
+}

+ 129 - 0
app/admin/model/store/DeviceRepair.php

@@ -0,0 +1,129 @@
+<?php
+namespace app\admin\model\store;
+
+use think\Model;
+use think\facade\Db;
+
+/**
+ * 设备报修申请表模型
+ * 处理单号生成、表单新增、状态更新、列表查询
+ */
+class DeviceRepair extends Model
+{
+    // 关联数据表名
+    protected $name = 'device_repair';
+    // 主键字段
+    protected $pk = 'id';
+
+    /**
+     * 自动生成报修单号(规则:REPAIR+日期+6位随机数,确保唯一)
+     * @return string 唯一报修单号
+     */
+    public static function generateRepairSn()
+    {
+        $date = date('Ymd'); // 日期:20251021
+        $rand = mt_rand(100000, 999999); // 6位随机数
+        $sn = "REPAIR{$date}{$rand}";
+
+        // 校验单号唯一性(极端情况重名时重新生成)
+        $exists = self::where('repair_sn', $sn)->find();
+        if ($exists) {
+            return self::generateRepairSn();
+        }
+        return $sn;
+    }
+
+    /**
+     * 提交新的报修表单
+     * @param array $data 表单数据(device_name/device_number等)
+     * @return false|Model 成功返回模型实例,失败返回false
+     */
+    public static function addRepairForm($data)
+    {
+        // 补充默认数据
+        $submitData = [
+            'repair_sn' => self::getNewOrderId(), // 自动填单号
+            'device_name' => $data['device_name'],
+            'device_number' => $data['device_number'],
+            'repair_problem' => $data['repair_problem'],
+            'return_address' => $data['return_address'],
+            'contact_name' => $data['contact_name'],
+            'contact_phone' => $data['contact_phone'],
+            'create_time' => time(), // 提交时间
+            'handle_status' => 0 // 初始状态:未处理
+        ];
+
+        // 新增数据
+        return self::create($submitData);
+    }
+    /**
+     * 生成充值订单号
+     * @param int $uid
+     * @return bool|string
+     */
+    public static function getNewOrderId($uid = 0)
+    {
+        if (!$uid) return false;
+        $count = (int)self::where('uid', $uid)->where('add_time', '>=', strtotime(date("Y-m-d")))->where('add_time', '<', strtotime(date("Y-m-d", strtotime('+1 day'))))->count();
+        return 'bx' . date('YmdHis', time()) . (10000 + $count + $uid);
+    }
+    /**
+     * 后台获取报修列表(带分页、状态筛选)
+     * @param int $page 页码
+     * @param int $limit 每页条数
+     * @param int $status 处理状态(-1=全部,0=未处理,1=已处理)
+     * @return \think\Paginator 分页列表
+     */
+    public static function getAdminRepairList($page = 1, $limit = 10, $status = -1)
+    {
+        $query = self::order('create_time DESC'); // 按提交时间倒序
+
+        // 状态筛选(-1表示不筛选)
+        if ($status != -1) {
+            $query->where('handle_status', $status);
+        }
+
+        // 分页查询
+        return $query->paginate([
+            'page' => $page,
+            'list_rows' => $limit,
+            'query' => request()->param() // 保留分页链接参数
+        ]);
+    }
+
+    /**
+     * 标记报修单为“已处理”
+     * @param int $id 报修单ID
+     * @param int $adminId 处理人ID
+     * @return bool 成功返回true,失败返回false
+     */
+    public static function markAsHandled($id, $adminId)
+    {
+        return self::where('id', $id)->update([
+                'handle_status' => 1,
+                'handle_admin_id' => $adminId,
+                'handle_time' => time()
+            ]) > 0;
+    }
+
+    /**
+     * 根据ID获取单个报修单详情(用于下载)
+     * @param int $id 报修单ID
+     * @return array|null 详情数据
+     */
+    public static function getRepairDetailForDownload($id)
+    {
+        $detail = self::find($id);
+        if (!$detail) {
+            return null;
+        }
+
+        // 格式化时间(时间戳转字符串)
+        $detail = $detail->toArray();
+        $detail['create_time_text'] = date('Y-m-d H:i:s', $detail['create_time']);
+        $detail['handle_time_text'] = $detail['handle_time'] ? date('Y-m-d H:i:s', $detail['handle_time']) : '未处理';
+        $detail['status_text'] = $detail['handle_status'] ? '已处理' : '未处理';
+
+        return $detail;
+    }
+}

+ 142 - 0
app/admin/view/store/device_repair/index.php

@@ -0,0 +1,142 @@
+{extend name="public/admin_base"}
+{block name="content"}
+<div class="layui-container">
+    <div class="layui-card">
+        <div class="layui-card-header">
+            <div class="layui-row">
+                <div class="layui-col-md6">设备报修管理</div>
+                <div class="layui-col-md6 layui-form">
+                    <!-- 状态筛选 -->
+                    <div class="layui-form-item layui-form-pane" style="margin: 0; float: right;">
+                        <div class="layui-inline">
+                            <label class="layui-form-label">处理状态</label>
+                            <div class="layui-input-inline" style="width: 150px;">
+                                <select name="status" lay-filter="statusFilter">
+                                    <option value="-1" {if $status == -1}selected{/if}>全部</option>
+                                    <option value="0" {if $status == 0}selected{/if}>未处理</option>
+                                    <option value="1" {if $status == 1}selected{/if}>已处理</option>
+                                </select>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="layui-card-body">
+            <!-- 报修列表表格 -->
+            <table class="layui-hide" id="repairTable" lay-filter="repairTable"></table>
+
+            <!-- 表格工具栏模板 -->
+            <script type="text/html" id="repairToolBar">
+                <div class="layui-btn-container">
+                    <button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="refresh">刷新列表</button>
+                </div>
+            </script>
+
+            <!-- 操作列模板 -->
+            <script type="text/html" id="repairAction">
+                <button class="layui-btn layui-btn-xs layui-btn-primary" lay-event="download">下载表单</button>
+                {{#  if(d.handle_status == 0) { }}
+                <button class="layui-btn layui-btn-xs layui-btn-warm" lay-event="markHandled">标记已处理</button>
+                {{#  } }}
+            </script>
+
+            <!-- 状态列模板 -->
+            <script type="text/html" id="repairStatus">
+                {{#  if(d.handle_status == 0) { }}
+                <span class="layui-badge layui-badge-danger">未处理</span>
+                {{#  } else { }}
+                <span class="layui-badge layui-badge-normal">已处理</span>
+                {{#  } }}
+            </script>
+        </div>
+    </div>
+</div>
+{/block}
+
+{block name="script"}
+<script src="{__STATIC__}/layui/layui.js"></script>
+<script>
+    layui.use(['table', 'jquery', 'form', 'layer'], function() {
+        var table = layui.table,
+            $ = layui.jquery,
+            form = layui.form,
+            layer = layui.layer;
+
+        // 渲染报修列表表格
+        var repairTable = table.render({
+            elem: '#repairTable',
+            url: "{:url('admin/device_repair/getRepairList')}", // 数据接口
+            toolbar: '#repairToolBar', // 工具栏
+            page: true, // 分页
+            limit: 10, // 每页条数
+            limits: [10, 20, 30],
+            cols: [[
+                {field: 'id', title: 'ID', width: 80, align: 'center'},
+                {field: 'repair_sn', title: '报修单号', width: 180, align: 'center'},
+                {field: 'device_name', title: '设备名称', width: 150, align: 'center'},
+                {field: 'device_number', title: '数量', width: 80, align: 'center'},
+                {field: 'contact_name', title: '联系人', width: 120, align: 'center'},
+                {field: 'contact_phone', title: '联系电话', width: 130, align: 'center'},
+                {field: 'create_time', title: '提交时间', width: 180, align: 'center',
+                    templet: function(d) { return layui.util.toDateString(d.create_time * 1000, 'yyyy-MM-dd HH:mm:ss'); }},
+                {field: 'handle_status', title: '处理状态', width: 120, align: 'center', templet: '#repairStatus'},
+                {fixed: 'right', title: '操作', width: 200, align: 'center', toolbar: '#repairAction'}
+            ]],
+            where: {
+                status: {$status} // 状态筛选参数
+            }
+        });
+
+        // 表格工具栏事件
+        table.on('toolbar(repairTable)', function(obj) {
+            switch(obj.event) {
+                case 'refresh':
+                    repairTable.reload(); // 刷新列表
+                    break;
+            }
+        });
+
+        // 表格行操作事件
+        table.on('tool(repairTable)', function(obj) {
+            var data = obj.data; // 当前行数据
+            switch(obj.event) {
+                // 下载表单
+                case 'download':
+                    window.location.href = "{:url('admin/device_repair/download')}?id=" + data.id;
+                    break;
+
+                // 标记已处理
+                case 'markHandled':
+                    layer.confirm('确定要标记此报修单为“已处理”吗?', {icon: 3}, function(index) {
+                        $.ajax({
+                            url: "{:url('admin/device_repair/markHandled')}",
+                            type: 'POST',
+                            data: {id: data.id},
+                            dataType: 'JSON',
+                            success: function(res) {
+                                if (res.code == 200) {
+                                    layer.msg(res.msg, {icon: 1});
+                                    repairTable.reload(); // 刷新列表
+                                } else {
+                                    layer.msg(res.msg, {icon: 2});
+                                }
+                            },
+                            error: function() {
+                                layer.msg('网络异常,请重试', {icon: 2});
+                            }
+                        });
+                        layer.close(index);
+                    });
+                    break;
+            }
+        });
+
+        // 状态筛选下拉框事件
+        form.on('select(statusFilter)', function(data) {
+            // 跳转到对应状态的列表页
+            window.location.href = "{:url('admin/device_repair/index')}?status=" + data.value;
+        });
+    });
+</script>
+{/block}

+ 81 - 0
app/api/controller/store/DeviceRepairController.php

@@ -0,0 +1,81 @@
+<?php
+namespace app\controller\api;
+
+use app\admin\model\store\DeviceRepair as DeviceRepairModel;
+//use think\Controller;
+use app\Request;
+use think\facade\Validate;
+
+/**
+ * 用户端设备报修表单控制器
+ * 处理表单展示、提交验证
+ */
+class DeviceRepair
+{
+    /**
+     * 展示报修表单页面
+     * @return \think\response\View
+     */
+//    public function index()
+//    {
+//        return $this->fetch();
+//    }
+
+    /**
+     * 提交报修表单(AJAX接口)
+     * @return \think\response\Json
+     */
+    public function submit()
+    {
+        // 1. 获取表单数据
+        $data = Request::post([
+            'device_name', // 设备名称
+            'device_number', // 数量
+            'order_id',
+            'product_id',
+            'repair_problem', // 报修问题
+            'return_address', // 寄回地址
+            'contact_name', // 联系人
+            'contact_phone' // 联系电话
+        ]);
+        // 2. 表单验证
+        $validate = Validate::make([
+            'device_name' => 'require|max:100', // 设备名称必填,最多100字
+            'device_number' => 'require|integer|min:1', // 数量必填,正整数
+            'repair_problem' => 'require', // 问题描述必填
+            'return_address' => 'require|max:255', // 地址必填,最多255字
+            'contact_name' => 'require|max:50', // 联系人必填,最多50字
+            'contact_phone' => 'require|mobile', // 电话必填,手机号格式
+        ], [
+            'device_name.require' => '请填写设备名称',
+            'device_number.require' => '请填写设备数量',
+            'device_number.min' => '设备数量至少1台',
+            'repair_problem.require' => '请描述报修问题',
+            'return_address.require' => '请填写寄回地址',
+            'contact_name.require' => '请填写联系人姓名',
+            'contact_phone.require' => '请填写联系电话',
+            'contact_phone.mobile' => '请填写正确的手机号'
+        ]);
+
+        if (!$validate->check($data)) {
+            return json(['code' => 0, 'msg' => $validate->getError()]);
+        }
+
+        // 3. 提交表单到数据库
+        $result = DeviceRepairModel::addRepairForm($data);
+        if (!$result) {
+            return json(['code' => 0, 'msg' => '报修表单提交失败,请重试']);
+        }
+
+        // 4. 返回成功(带报修单号)
+        return json([
+            'code' => 200,
+            'msg' => '报修表单提交成功',
+            'data' => [
+                'repair_sn' => $result['repair_sn'], // 自动生成的单号
+                'tips' => '请保存单号,以便查询进度'
+            ]
+        ]);
+    }
+
+}

+ 8 - 6
app/models/store/StoreCart.php

@@ -173,6 +173,7 @@ class StoreCart extends BaseModel
         $list = $model->select()->toArray();
         if (!count($list)) return compact('valid', 'invalid');
         $now = time();
+        $type_wholesale=1;
         foreach ($list as $k => $cart) {
             if ($cart['seckill_id']) {
                 $product = StoreSeckill::field($seckillInfoField)
@@ -196,7 +197,6 @@ class StoreCart extends BaseModel
                 //商品删除或无库存
             } else if (!$product['is_show'] || $product['is_del'] || !$product['stock']) {
                 $invalid[] = $cart;
-
                 //秒杀产品未开启或者已结束
             } else if ($cart['seckill_id'] && ($product['start_time'] > $now || $product['stop_time'] < $now - 86400)) {
                 $invalid[] = $product;
@@ -205,7 +205,9 @@ class StoreCart extends BaseModel
                 $invalid[] = $cart;
                 //正常商品
             } else {
-
+                if ($product['is_wholesale'] == 1){  //是否有批发商品
+                    $type_wholesale = 2;
+                }
                 if ($cart['seckill_id']) {
                     $config = SystemGroupData::get($product['time_id']);
                     if ($config) {
@@ -238,8 +240,8 @@ class StoreCart extends BaseModel
                             $cart['truePrice'] = $attrInfo['price'];
                             $cart['vip_truePrice'] = 0;
                         } else {
-                            $cart['truePrice'] = (float)StoreProduct::setLevelPrice($attrInfo['price'], $uid, true);
-                            $cart['vip_truePrice'] = (float)StoreProduct::setLevelPrice($attrInfo['price'], $uid);
+                            $cart['truePrice'] = (float)StoreProduct::setLevelPrice($attrInfo['price'], $uid, true,$type_wholesale);
+                            $cart['vip_truePrice'] = (float)StoreProduct::setLevelPrice($attrInfo['price'], $uid,false,$type_wholesale);
                         }
                         $cart['trueStock'] = $attrInfo['stock'];
                         $cart['costPrice'] = $attrInfo['cost'];
@@ -257,8 +259,8 @@ class StoreCart extends BaseModel
                         $cart['productInfo']['attrInfo']['weight'] = $product['weight'];
                         $cart['productInfo']['attrInfo']['volume'] = $product['volume'];
                     } else {
-                        $cart['truePrice'] = (float)StoreProduct::setLevelPrice($cart['productInfo']['price'], $uid, true);
-                        $cart['vip_truePrice'] = (float)StoreProduct::setLevelPrice($cart['productInfo']['price'], $uid);
+                        $cart['truePrice'] = (float)StoreProduct::setLevelPrice($cart['productInfo']['price'], $uid, true,$type_wholesale);
+                        $cart['vip_truePrice'] = (float)StoreProduct::setLevelPrice($cart['productInfo']['price'], $uid,false,$type_wholesale);
                     }
                     $cart['trueStock'] = $cart['productInfo']['stock'];
                     $cart['costPrice'] = $cart['productInfo']['cost'];

+ 25 - 9
app/models/store/StoreProduct.php

@@ -7,8 +7,10 @@
 
 namespace app\models\store;
 
+use app\admin\controller\user\UserAgentLevel;
 use app\admin\model\store\StoreProductAttrValue as StoreProductAttrValueModel;
 use app\models\system\SystemUserLevel;
+use app\models\user\User;
 use app\models\user\UserLevel;
 use crmeb\basic\BaseModel;
 use crmeb\services\GroupDataService;
@@ -94,6 +96,7 @@ class StoreProduct extends BaseModel
         $page = $data['page'];
         $limit = $data['limit'];
         $type = $data['type']; // 某些模板需要购物车数量 1 = 需要查询,0 = 不需要
+        $type_wholesale = 1;
         $model = self::validWhere();
         if ($sId) {
             $model->whereIn('id', function ($query) use ($sId) {
@@ -110,6 +113,7 @@ class StoreProduct extends BaseModel
         if ($news != 0) $model->where('is_new', 1);
         if ($is_wholesale != 0){
             $model->where('is_wholesale', 1);
+            $type_wholesale = 2;
         }else{
             $model->where('is_wholesale', 0);
         }
@@ -133,7 +137,7 @@ class StoreProduct extends BaseModel
                 $list[$k]['activity'] = self::activity($v['id']);
             }
         }
-        return self::setLevelPrice($list, $uid);
+        return self::setLevelPrice($list, $uid,false,$type_wholesale);
     }
 
     /*
@@ -270,21 +274,33 @@ class StoreProduct extends BaseModel
      * @param int $uid 用户uid
      * @return array
      * */
-    public static function setLevelPrice($list, $uid, $isSingle = false)
+    public static function setLevelPrice($list, $uid, $isSingle = false,$type = 1)
     {
         if (is_object($list)) $list = count($list) ? $list->toArray() : [];
         if (!sys_config('vip_open')) {
             if (is_array($list)) return $list;
             return $isSingle ? $list : 0;
         }
-        $levelId = UserLevel::getUserLevel($uid);
-        if ($levelId) {
-            $discount = UserLevel::getUserLevelInfo($levelId, 'discount');
-            $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
-        } else {
-            $discount = SystemUserLevel::getLevelDiscount();
-            $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
+        if ($type == 1){
+            $levelId = UserLevel::getUserLevel($uid);
+            if ($levelId) {
+                $discount = UserLevel::getUserLevelInfo($levelId, 'discount');
+                $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
+            } else {
+                $discount = SystemUserLevel::getLevelDiscount();
+                $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
+            }
+        }else if ($type == 2){
+            $levelId = User::where('uid',$uid)->value('agent');
+            if ($levelId > 0) {
+                $discount = \app\models\user\UserAgentLevel::where('id',$levelId)->value('discount');
+                $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
+            } else {
+                $discount = 100;
+                $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
+            }
         }
+
         //如果不是数组直接执行减去会员优惠金额
         if (!is_array($list))
             //不是会员原价返回