Browse Source

first commit

liuhairui 3 weeks ago
parent
commit
a8f5ea1d48

+ 36 - 0
application/admin/controller/Newrecords.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\controller\Backend;
+use think\Db;
+
+/**
+ *
+ *
+ * @icon fa fa-circle-o
+ */
+class Newrecords extends Backend
+{
+
+    /**
+     * Records模型对象
+     * @var \app\admin\model\Newrecords
+     */
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new \app\admin\model\Newrecords;
+    }
+
+
+
+    /**
+     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
+     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
+     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
+     */
+
+}

+ 203 - 2
application/admin/controller/Records.php

@@ -3,9 +3,10 @@
 namespace app\admin\controller;
 
 use app\common\controller\Backend;
+use think\Db;
 
 /**
- * 
+ *
  *
  * @icon fa fa-circle-o
  */
@@ -22,7 +23,6 @@ class Records extends Backend
     {
         parent::_initialize();
         $this->model = new \app\admin\model\Records;
-
     }
 
 
@@ -34,4 +34,205 @@ class Records extends Backend
      */
 
 
+
+    /**
+     * 处理Excel文件上传并获取数据,然后保存到数据库
+     */
+    public function getxlsxdata(){
+        // 处理POST请求
+        if (!$this->request->isPost()) {
+            return json(['code' => 0, 'msg' => '请求方式错误,需要POST请求']);
+        }
+        
+        // 获取上传的文件
+        $file = $this->request->file('file');
+        if (!$file) {
+            return json(['code' => 0, 'msg' => '请选择要上传的文件']);
+        }
+        
+        try {
+            // 验证文件类型
+            $info = $file->validate(['ext' => 'xlsx,xls'])->move(ROOT_PATH . 'public/uploads/excel/');
+            if (!$info) {
+                return json(['code' => 0, 'msg' => '文件验证失败: ' . $file->getError()]);
+            }
+            
+            // 获取文件路径
+            $fullPath = ROOT_PATH . 'public/uploads/excel/' . $info->getSaveName();
+            // 读取Excel文件内容
+            $excelData = [];
+            // 根据文件扩展名选择相应的读取方法
+            $ext = strtolower(pathinfo($fullPath, PATHINFO_EXTENSION));
+            
+            try {
+                // 检查是否安装了PhpSpreadsheet
+                if (class_exists('\PhpOffice\PhpSpreadsheet\IOFactory')) {
+                    $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader(ucfirst($ext));
+                    $spreadsheet = $reader->load($fullPath);
+                    $sheet = $spreadsheet->getActiveSheet();
+                    $excelData = $sheet->toArray();
+                } 
+                // 检查是否安装了PHPExcel
+                else if (class_exists('\PHPExcel_IOFactory')) {
+                    $reader = \PHPExcel_IOFactory::createReader(ucfirst($ext));
+                    $excel = $reader->load($fullPath);
+                    $sheet = $excel->getActiveSheet();
+                    $excelData = $sheet->toArray();
+                }
+                // 如果都没有,返回文件已上传但无法解析的信息
+                else {
+                    return json([
+                        'code' => 0,
+                        'msg' => '文件上传成功,但服务器缺少Excel解析库',
+                        'data' => ['file_name' => $info->getFilename()]
+                    ]);
+                }
+            } catch (\Exception $e) {
+                // 清理上传的文件
+                @unlink($fullPath);
+                return json(['code' => 0, 'msg' => '解析Excel文件时出错:' . $e->getMessage()]);
+            }
+            
+            // 清理上传的临时文件
+            @unlink($fullPath);
+            // 检查数据是否为空
+            if (count($excelData) < 2) {
+                return json(['code' => 0, 'msg' => 'Excel文件数据为空或只有表头', 'data' => ['file_name' => $info->getFilename()]]);
+            }
+            // 获取表头(第一行)
+            $headers = $excelData[0];
+            
+            // 定义表头与数据库字段的映射关系
+            $fieldMapping = [
+                '电子耳标号' => 'rfid',
+                '国标号' => 'number',
+                '出生日期' => 'birthDate',
+                '品类' => 'category',
+                '性别' => 'gender',
+                '日龄' => 'dayage'
+            ];
+            
+            // 准备要插入数据库的数据
+            $insertData = [];
+            $successCount = 0;
+            $errorCount = 0;
+            $errorMessages = [];
+            
+            // 处理数据行(从第二行开始)
+            for ($i = 1; $i < count($excelData); $i++) {
+                $rowData = $excelData[$i];
+                $record = [];
+                $hasData = false;
+                
+                // 构建关联数组
+                for ($j = 0; $j < count($headers); $j++) {
+                    $header = $headers[$j];
+                    $value = isset($rowData[$j]) ? trim($rowData[$j]) : '';
+                    // 如果表头在映射中存在,添加到记录中
+                    if (isset($fieldMapping[$header])) {
+                        $field = $fieldMapping[$header];
+                        // 特殊字段处理
+                        if ($field === 'birthDate' && !empty($value)) {
+                            // 尝试转换日期格式,只保留日期部分
+                            $timestamp = strtotime($value);
+                            if ($timestamp) {
+                                $record[$field] = date('Y-m-d', $timestamp);
+                            } else {
+                                $record[$field] = $value; // 保持原样
+                            }
+                        } else {
+                            $record[$field] = $value;
+                        }
+                        
+                        if (!empty($value)) {
+                            $hasData = true;
+                        }
+                    }
+                }
+                // 如果记录有数据,添加创建时间和更新时间
+                if ($hasData) {
+                    // $record['createtime'] = time();
+                    // $record['updatetime'] = time();
+                    $insertData[] = $record;
+                    $successCount++;
+                } else {
+                    $errorCount++;
+                    $errorMessages[] = "第" . ($i + 1) . "行数据为空";
+                }
+            }
+            
+            // 准备导入进度数据
+            $totalRows = count($excelData) - 1; // 减去表头
+            $totalInsertData = count($insertData);
+            $insertedCount = 0;
+            $batchSize = 50; // 每批插入的数据量
+            $duplicateCount = 0; // 重复数据计数
+            
+            // 打印要插入的数据(仅开发环境使用)
+            if (!empty($insertData)) {
+                // 打印数据
+                // echo "<pre>";
+                // echo "要插入的数据总量: " . count($insertData) . " 条\n";
+                // print_r(array_slice($insertData, 0, 5));
+                // echo "</pre>";
+                
+                // 提取所有rfid值用于检查重复
+                $rfidValues = array_column($insertData, 'rfid');
+                
+                // 查询数据库中已存在的rfid值
+                $existingRfids = Db::name('new_records')
+                    ->where('rfid', 'in', $rfidValues)
+                    ->column('rfid');
+                
+                // 过滤掉重复数据,只保留不存在的记录
+                $uniqueData = [];
+                foreach ($insertData as $record) {
+                    if (!in_array($record['rfid'], $existingRfids)) {
+                        $uniqueData[] = $record;
+                    } else {
+                        $duplicateCount++;
+                        $errorMessages[] = "重复数据,rfid: " . $record['rfid'] . " 已存在,跳过插入";
+                    }
+                }
+                
+                // 如果有唯一数据需要插入
+                if (!empty($uniqueData)) {
+                    // 将数据分成多批
+                    $batches = array_chunk($uniqueData, $batchSize);
+                    foreach ($batches as $batch) {
+                        try {
+                            $result = Db::name('new_records')->insertAll($batch);
+                            $insertedCount += $result;
+                        } catch (\Exception $e) {
+                            // 记录错误
+                            $errorCount++;
+                            $errorMessages[] = "插入数据时出错:" . $e->getMessage();
+                        }
+                    }
+                }
+            }
+            
+            // 返回成功信息
+            return json([
+                'code' => 1,
+                'msg' => '文件上传并保存成功!',
+                'data' => [
+                    'file_name' => $info->getFilename(),
+                    'total_rows' => $totalRows,
+                    'total_data_rows' => $totalInsertData,
+                    'inserted_count' => $insertedCount,
+                    'success_count' => $insertedCount,
+                    'duplicate_count' => $duplicateCount,
+                    'error_count' => $errorCount,
+                    'error_messages' => $errorMessages
+                ]
+            ]);
+            
+        } catch (\Exception $e) {
+            return json(['code' => 0, 'msg' => '处理文件时出错:' . $e->getMessage()]);
+        }
+    }
+
+    
+
 }

+ 16 - 0
application/admin/lang/zh-cn/newrecords.php

@@ -0,0 +1,16 @@
+<?php
+
+return [
+    'Username'     => '用户名',
+    'UserId'       => '用户ID',
+    'Rfid'         => '耳标签',
+    'Rfid_num'     => '耳标当前提交数量',
+    'BuildingName' => '栋舍',
+    'RoomName'     => '房间号',
+    'PenNo'        => '栏位号',
+    'Sys_rq'       => '日期',
+    'Type'         => '类型',
+    'Node'         => '备用字段',
+    'Node1'        => '备用字段',
+    'Node2'        => '备用字段'
+];

+ 36 - 0
application/admin/model/Newrecords.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+
+
+class Newrecords extends Model
+{
+
+    // 表名
+    protected $name = 'records';
+
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = false;
+
+    // 定义时间戳字段名
+    protected $createTime = false;
+    protected $updateTime = false;
+    protected $deleteTime = false;
+
+    // 追加属性
+    protected $append = [
+
+    ];
+
+
+
+
+
+
+
+
+
+
+}

+ 6 - 6
application/admin/model/Records.php

@@ -8,13 +8,13 @@ use think\Model;
 class Records extends Model
 {
 
-    
 
-    
+
+
 
     // 表名
-    protected $name = 'records';
-    
+    protected $name = 'new_records';
+
     // 自动写入时间戳字段
     protected $autoWriteTimestamp = false;
 
@@ -27,9 +27,9 @@ class Records extends Model
     protected $append = [
 
     ];
-    
 
-    
+
+
 
 
 

+ 81 - 0
application/admin/view/newrecords/add.html

@@ -0,0 +1,81 @@
+<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-username" class="form-control" name="row[username]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('UserId')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-userId" class="form-control" name="row[userId]" type="number">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Rfid')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-rfid" class="form-control " rows="5" name="row[rfid]" cols="50"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Rfid_num')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-rfid_num" class="form-control" name="row[rfid_num]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('BuildingName')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-buildingName" class="form-control" name="row[buildingName]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('RoomName')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-roomName" class="form-control" name="row[roomName]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('PenNo')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-penNo" class="form-control" name="row[penNo]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Sys_rq')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-sys_rq" class="form-control" name="row[sys_rq]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-type" class="form-control" name="row[type]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Node')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-node" class="form-control" name="row[node]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Node1')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-node1" class="form-control" name="row[node1]" type="text">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Node2')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-node2" class="form-control" name="row[node2]" type="text">
+        </div>
+    </div>
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 48 - 0
application/admin/view/newrecords/edit.html

@@ -0,0 +1,48 @@
+<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
+
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Rfid')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-rfid" class="form-control " rows="5" name="row[rfid]" cols="50">{$row.rfid|htmlentities}</textarea>
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('BuildingName')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-buildingName" class="form-control" name="row[buildingName]" type="text" value="{$row.buildingName|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('RoomName')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-roomName" class="form-control" name="row[roomName]" type="text" value="{$row.roomName|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('PenNo')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-penNo" class="form-control" name="row[penNo]" type="text" value="{$row.penNo|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Sys_rq')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-sys_rq" class="form-control" name="row[sys_rq]" type="text" value="{$row.sys_rq|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-type" class="form-control" name="row[type]" type="text" value="{$row.type|htmlentities}">
+        </div>
+    </div>
+
+    <div class="form-group layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
+        </div>
+    </div>
+</form>

+ 23 - 0
application/admin/view/newrecords/index.html

@@ -0,0 +1,23 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
+                        <!--<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('records/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>-->
+<!--                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('records/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>-->
+                        <!--<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('records/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>-->
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
+                           width="100%">
+                    </table>
+
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 11 - 11
application/admin/view/records/edit.html

@@ -2,40 +2,40 @@
 
 
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Rfid')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">电子耳标号</label>
         <div class="col-xs-12 col-sm-8">
             <textarea id="c-rfid" class="form-control " rows="5" name="row[rfid]" cols="50">{$row.rfid|htmlentities}</textarea>
         </div>
     </div>
 
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('BuildingName')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">国标号</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-buildingName" class="form-control" name="row[buildingName]" type="text" value="{$row.buildingName|htmlentities}">
+            <input id="c-number" class="form-control" name="row[number]" type="text" value="{$row.number|htmlentities}">
         </div>
     </div>
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('RoomName')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">出生日期</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-roomName" class="form-control" name="row[roomName]" type="text" value="{$row.roomName|htmlentities}">
+            <input id="c-birthDate" class="form-control" name="row[birthDate]" type="text" value="{$row.birthDate|htmlentities}">
         </div>
     </div>
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('PenNo')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">品类</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-penNo" class="form-control" name="row[penNo]" type="text" value="{$row.penNo|htmlentities}">
+            <input id="c-category" class="form-control" name="row[category]" type="text" value="{$row.category|htmlentities}">
         </div>
     </div>
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Sys_rq')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">性别</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-sys_rq" class="form-control" name="row[sys_rq]" type="text" value="{$row.sys_rq|htmlentities}">
+            <input id="c-gender" class="form-control" name="row[gender]" type="text" value="{$row.gender|htmlentities}">
         </div>
     </div>
     <div class="form-group">
-        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <label class="control-label col-xs-12 col-sm-2">日龄</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-type" class="form-control" name="row[type]" type="text" value="{$row.type|htmlentities}">
+            <input id="c-dayage" class="form-control" name="row[dayage]" type="text" value="{$row.dayage|htmlentities}">
         </div>
     </div>
 

+ 7 - 5
application/admin/view/records/index.html

@@ -8,12 +8,14 @@
                     <div id="toolbar" class="toolbar">
                         <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
                         <!--<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('records/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>-->
-                        <!--<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('records/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>-->
+                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('records/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
                         <!--<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('records/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>-->
-
-
-
-
+                        <div class="btn-group">
+                            <button type="button" class="btn btn-info btn-file" id="importBtn">
+                                <i class="fa fa-upload"></i> 导入xlsx表格
+                            </button>
+                            <input type="file" id="xlsxFile" accept=".xlsx, .xls" style="display: none;" />
+                        </div>
 
                     </div>
                     <table id="table" class="table table-striped table-bordered table-hover table-nowrap"

+ 69 - 31
application/api/controller/Index.php

@@ -242,56 +242,42 @@ class Index extends Api
 
         $param = input();
 
-        $rfidPairs = array_filter(array_map('trim', explode(',', $param['rfid'] ?? '')));
-
-        if (empty($rfidPairs)) {
-            return json([
-                'code' => 1,
-                'msg' => 'RFID数据不能为空',
-            ]);
-        }
-
         $insertData = [];
-
-        foreach ($rfidPairs as $item) {
-            if (strpos($item, ':') === false) {
-                continue;
-            }
-
-            list($rfid, $type) = explode(':', $item, 2);
-
+        foreach ($param as $item) {
             $insertData[] = [
-                'username'     => $param['username'] ?? '',
-                'userId'       => $param['userId'] ?? '',
-                'rfid'         => trim($rfid),
-                'rfid_num'     => count($rfidPairs),
-                'buildingName' => $param['buildingName'] ?? '',
-                'roomName'     => $param['roomName'] ?? '',
-                'penNo'        => $param['penNo'] ?? '',
-                'model'        => $param['deviceModel'] ?? '',
-                'version'        => $param['deviceVersion'] ?? '',
-                'type'         => trim($type),
+                'username'     => $item['username'] ?? '',
+                'userId'       => $item['userId'] ?? '',
+                'rfid'         => trim($item['rfid']),
+                'rfid_num'     => count($param), // 总记录数
+                'buildingName' => $item['buildingName'] ?? '',
+                'roomName'     => $item['roomName'] ?? '',
+                'penNo'        => $item['penNo'] ?? '',
+                'model'        => $item['deviceModel'] ?? '',
+                'version'      => $item['deviceVersion'] ?? '',
+                'type'         => $item['type'] ?? '',
                 'sys_rq'       => date('Y-m-d H:i:s'),
+                'gender'       => $item['gender'] ?? '',
+                'birthDate'    => $item['birthDate'] ?? '',
+                'notes'        => $item['notes'] ?? '',
             ];
         }
 
         if (empty($insertData)) {
             return json([
                 'code' => 1,
-                'msg' => '无有效RFID数据',
+                'msg' => '无有效数据',
             ]);
         }
 
+
         try {
             $result = Db::name("records")->insertAll($insertData);
 
             return json([
                 'code' => 0,
-                'msg' => '数据已提交成功',
-                'count' => $result,
+                'msg' => '数据已提交成功'
             ]);
         } catch (\Exception $e) {
-            // 打印日志可选
             Log::error('插入失败:' . $e->getMessage());
 
             return json([
@@ -301,4 +287,56 @@ class Index extends Api
         }
     }
 
+    //获取数据信息
+    public function GetListArr(){
+        header('Access-Control-Allow-Origin: *');
+        header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
+        header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, X-Requested-With');
+
+        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
+            exit;
+        }
+        
+        // 创建最终返回的数据数组
+        $list = [];
+        
+        // 查询new_records表的所有数据,保持原样
+        $newRecordsData = Db::name("new_records")
+            ->select();
+        
+        // 将new_records表的数据添加到结果数组
+        if (!empty($newRecordsData)) {
+            $list = array_merge($list, $newRecordsData);
+        }
+        
+        // 查询records表的数据,按sys_rq倒序
+        $recordsData = Db::name("records")
+            ->order('sys_rq DESC')
+            ->select();
+        
+        // 对records表数据按rfid去重,只保留每个rfid最新的一条记录
+        $rfidMap = [];
+        $uniqueRecords = [];
+        
+        foreach ($recordsData as $record) {
+            $rfid = trim($record['rfid']);
+            // 如果这个rfid还没有处理过,则添加到结果中
+            if (!isset($rfidMap[$rfid])) {
+                $rfidMap[$rfid] = true;
+                $uniqueRecords[] = $record;
+            }
+        }
+        
+        // 将去重后的records表数据添加到结果数组
+        if (!empty($uniqueRecords)) {
+            $list = array_merge($list, $uniqueRecords);
+        }
+        
+        return json([
+            'code' => 0,
+            'msg' => '数据获取成功',
+            'list' => $list
+        ]);
+    }
+
 }

+ 62 - 0
public/assets/js/backend/newrecords.js

@@ -0,0 +1,62 @@
+define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+
+    var Controller = {
+        index: function () {
+            // 初始化表格参数配置
+            Table.api.init({
+                extend: {
+                    index_url: 'newrecords/index' + location.search,
+                    add_url: 'newrecords/add',
+                    edit_url: 'newrecords/edit',
+                    del_url: 'newrecords/del',
+                    multi_url: 'newrecords/multi',
+                    import_url: 'newrecords/import',
+                    table: 'newrecords',
+                }
+            });
+
+            var table = $("#table");
+
+            // 初始化表格
+            table.bootstrapTable({
+                url: $.fn.bootstrapTable.defaults.extend.index_url,
+                pk: 'id',
+                sortName: 'id',
+                fixedColumns: true,
+                fixedRightNumber: 1,
+                columns: [
+                    [
+                        {checkbox: true},
+                        {field: 'id', title: __('Id')},
+                        {field: 'username', title: '用户名', operate: 'LIKE'},
+                        {field: 'userId', title: '用户ID', operate: 'LIKE'},
+                        {field: 'rfid', title: '电子耳标号', operate: 'LIKE'},
+                        {field: 'buildingName', title:'栋舍', operate: 'LIKE'},
+                        {field: 'roomName', title:'房间号', operate: 'LIKE'},
+                        {field: 'penNo', title:'栏位号', operate: 'LIKE'},
+                        {field: 'birthDate', title:"出生日期", operate: 'LIKE'},
+                        {field: 'category', title: "品类", operate: 'LIKE'},
+                        {field: 'gender', title:"性别", operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'sys_rq', title: "创建日期", operate: 'LIKE'},
+                        // {field: 'dayage', title: "日龄", operate: 'LIKE'},
+                        // {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
+                    ]
+                ]
+            });
+            // 为表格绑定事件
+            Table.api.bindevent(table);
+        },
+        add: function () {
+            Controller.api.bindevent();
+        },
+        edit: function () {
+            Controller.api.bindevent();
+        },
+        api: {
+            bindevent: function () {
+                Form.api.bindevent($("form[role=form]"));
+            }
+        }
+    };
+    return Controller;
+});

+ 137 - 9
public/assets/js/backend/records.js

@@ -28,20 +28,148 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                     [
                         {checkbox: true},
                         {field: 'id', title: __('Id')},
-                        {field: 'username', title: __('Username'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
-                        {field: 'userId', title: __('UserId')},
-                        {field: 'rfid', title: '耳标签号', operate: 'LIKE'},
-                        // {field: 'rfid_num', title: __('Rfid_num'), operate: 'LIKE'},
-                        {field: 'buildingName', title: __('BuildingName'), operate: 'LIKE'},
-                        {field: 'roomName', title: __('RoomName'), operate: 'LIKE'},
-                        {field: 'penNo', title: __('PenNo'), operate: 'LIKE'},
-                        {field: 'sys_rq', title: __('Sys_rq'), operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
-                        {field: 'type', title: __('Type'), operate: 'LIKE'},
+                        {field: 'rfid', title: '电子耳标号', operate: 'LIKE'},
+                        {field: 'number', title:'国标号', operate: 'LIKE'},
+                        {field: 'birthDate', title:"出生日期", operate: 'LIKE'},
+                        {field: 'category', title: "品类", operate: 'LIKE'},
+                        {field: 'gender', title:"性别", operate: 'LIKE', table: table, class: 'autocontent', formatter: Table.api.formatter.content},
+                        {field: 'dayage', title: "日龄", operate: 'LIKE'},
                         // {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
                     ]
                 ]
             });
 
+
+            // 使用全局事件委托,确保即使DOM动态变化也能触发
+            $(document).ready(function() {
+                console.log('绑定事件');
+                // 直接绑定到body的点击事件,用于测试按钮点击是否有反应
+                $(document).on('click', '.btn-file', function() {
+                    console.log('按钮被点击了');
+                    // 手动触发文件输入框
+                    var fileInput = $('#xlsxFile');
+                    if(fileInput.length) {
+                        console.log('文件输入框存在,触发点击');
+                        fileInput.click();
+                    } else {
+                        console.error('文件输入框不存在!');
+                    }
+                });
+
+                // 绑定文件选择事件
+                $(document).on('change', '#xlsxFile', function() {
+                    console.log('文件选择事件触发!');
+
+                    var file = this.files[0];
+                    if (!file) {
+                        console.log('未选择文件');
+                        return;
+                    }
+
+                    console.log('已选择文件:', file.name, '大小:', file.size, '类型:', file.type);
+
+                    // 检查文件类型
+                    var ext = file.name.split('.').pop().toLowerCase();
+                    console.log('文件扩展名:', ext);
+
+                    if (ext !== 'xlsx' && ext !== 'xls') {
+                        layer.msg('请选择Excel文件(.xlsx或.xls)', {icon: 2});
+                        return;
+                    }
+
+                    var formData = new FormData();
+                    formData.append('file', file);
+
+                    // 检查formData内容
+                    for (var pair of formData.entries()) {
+                        console.log('FormData键值对:', pair[0], pair[1]);
+                    }
+
+                    console.log('准备发送AJAX请求');
+
+                    // 创建进度条弹窗
+                    var progressBar = layer.open({
+                        type: 1,
+                        title: '导入进度',
+                        area: ['400px', '200px'],
+                        content: '<div style="padding: 20px;"><div class="progress" style="margin-bottom: 10px;"><div id="importProgressBar" class="progress-bar progress-bar-success" role="progressbar" style="width: 0%;">0%</div></div><p id="importProgressText">准备导入...</p><p id="importProgressDetail"></p></div>',
+                        cancel: function() {
+                            // 阻止用户手动关闭弹窗,必须等待导入完成
+                            return false;
+                        }
+                    });
+
+                    $.ajax({
+                        url: 'records/getxlsxdata',
+                        type: 'post',
+                        data: formData,
+                        contentType: false,
+                        processData: false,
+                        // 添加超时设置
+                        timeout: 30000,
+                        // 添加全局错误处理
+                        xhr: function() {
+                            var xhr = new XMLHttpRequest();
+                            // 上传进度事件
+                            xhr.upload.addEventListener('progress', function(e) {
+                                if (e.lengthComputable) {
+                                    var percentComplete = (e.loaded / e.total) * 100;
+                                    console.log('文件上传进度: ' + percentComplete.toFixed(2) + '%');
+                                }
+                            }, false);
+                            return xhr;
+                        },
+                        success: function(res) {
+                            console.log('AJAX请求成功,返回数据:', res);
+
+                            // 更新进度条为100%
+                            $('#importProgressBar').css('width', '100%').text('100%');
+
+                            if (res.code === 1) {
+                                // 更新进度文本
+                                $('#importProgressText').text('导入完成');
+                                $('#importProgressDetail').text('总共' + res.data.total_rows + '条数据,成功导入' + res.data.inserted_count + '条');
+
+                                // 2秒后关闭进度条弹窗并显示成功消息
+                                setTimeout(function() {
+                                    layer.close(progressBar);
+                                    layer.msg(res.msg || '导入成功', {icon: 1});
+                                    // 刷新表格数据
+                                    $('.btn-refresh').trigger('click');
+                                }, 2000);
+                            } else {
+                                // 更新进度文本为失败信息
+                                $('#importProgressText').text('导入失败');
+                                $('#importProgressDetail').text(res.msg || '未知错误');
+
+                                // 2秒后关闭进度条弹窗并显示失败消息
+                                setTimeout(function() {
+                                    layer.close(progressBar);
+                                    layer.msg(res.msg || '导入失败', {icon: 2});
+                                }, 2000);
+                            }
+                        },
+                        error: function(xhr, status, error) {
+                            console.error('AJAX请求失败:', error, '状态:', status);
+                            console.error('XHR详情:', xhr);
+
+                            // 更新进度文本为错误信息
+                            $('#importProgressText').text('导入失败');
+                            $('#importProgressDetail').text('请求失败,请重试');
+
+                            // 2秒后关闭进度条弹窗并显示错误消息
+                            setTimeout(function() {
+                                layer.close(progressBar);
+                                layer.msg('请求失败,请重试', {icon: 2});
+                            }, 2000);
+                        },
+                        complete: function(xhr, status) {
+                            console.log('AJAX请求完成,状态:', status);
+                        }
+                    });
+                });
+            });
+
             // 为表格绑定事件
             Table.api.bindevent(table);
         },