FastAdmin后端列表导入表格数据

后台添加数据的时候增加通过表格导入功能

如下图index.html页面增加导入和模板下载按钮代码如下

<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('kecheng/english/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('kecheng/english/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('kecheng/english/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
                        <!-- 增加的两个按钮-->
                        {:build_toolbar('import')}
                        <a href="__ROOT__/public/export/english.xlsx" class="btn btn-success btn-export" title="{:__('Export')}" ><i class="fa fa-download"></i>{:__('下载模版')}</a>
                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('kecheng/english/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"
                           data-operate-edit="{:$auth->check('kecheng/english/edit')}"
                           data-operate-del="{:$auth->check('kecheng/english/del')}"
                           width="100%">
                    </table>
                </div>
            </div>

        </div>
    </div>
</div>

对应的 js 文件设置处理导入逻辑的后台方法即import_url

            // 初始化表格参数配置
            Table.api.init({
                extend: {
                    index_url: 'kecheng/english/index' + location.search,
                    add_url: 'kecheng/english/add'+ location.search,
                    edit_url: 'kecheng/english/edit',
                    del_url: 'kecheng/english/del',
                    multi_url: 'kecheng/english/multi',
                    import_url: 'kecheng/english/import'+ location.search,//此处设置处理导入的后台方法location.search是带url中所传的参数
                    table: 'kecheng_english',
                }
            });

重写app\admin\library\traits\Backend.php中的readFile方法

  /**
     * 读取文件数据并返回
     * @return array
     */
    protected function readFile($file) {
        if (!$file) {
            $this->error(__('Parameter %s can not be empty', 'file'));
        }
        $filePath = ROOT_PATH . DS . 'public' . DS . $file;
        if (!is_file($filePath)) {
            $this->error(__('No results were found'));
        }

        // 实例化reader
        $ext = pathinfo($filePath, PATHINFO_EXTENSION);
        if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
            $this->error(__('Unknown data format'));
        }

        if ($ext === 'csv') {
            $file = fopen($filePath, 'r');
            $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
            $fp = fopen($filePath, "w");
            $n = 0;
            while ($line = fgets($file)) {
                $line = rtrim($line, "\n\r\0");
                $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
                if ($encoding != 'utf-8') {
                    $line = mb_convert_encoding($line, 'utf-8', $encoding);
                }
                if ($n == 0 || preg_match('/^".*"$/', $line)) {
                    fwrite($fp, $line . "\n");
                } else {
                    fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
                }
                $n++;
            }
            fclose($file) || fclose($fp);

            $reader = new Csv();
        } elseif ($ext === 'xls') {
            $reader = new Xls();
        } else {
            $reader = new Xlsx();
        }

        // 加载文件
        try {
            if (!$PHPExcel = $reader->load($filePath)) {
                $this->error(__('Unknown data format'));
            }
            $currentSheet = $PHPExcel->getSheet(0);  // 读取文件中的第一个工作表
            $allColumn = $currentSheet->getHighestDataColumn(); // 取得最大的列号
            $allRow = $currentSheet->getHighestRow(); // 取得一共有多少行
            $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);

            // 读取第一行字段名
            $fields = [];
            for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $fields[] = $this->convertToPlainText($val); // 将字段名转换为纯文本
                }
            }

            // 读取行数据
            $row = [];
            for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
                $values = [];
                for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                    $values[] = $this->convertToPlainText($val); // 将单元格值转换为纯文本
                }

                $row[] = array_combine($fields, $values);
            }
        } catch (Exception $exception) {
            $this->error($exception->getMessage());
        }

        if (!$row) {
            $this->error(__('No rows were updated'));
        }
        return $row;
    }

    /**
     * 将值转换为纯文本
     * @param mixed $value
     * @return string
     */
    protected function convertToPlainText($value) {
        if ($value instanceof \PhpOffice\PhpSpreadsheet\RichText\RichText) {
            // 如果是富文本对象,提取所有文本内容
            $plainText = '';
            foreach ($value->getRichTextElements() as $element) {
                $plainText .= $element->getText();
            }
            return $plainText;
        } elseif (is_null($value)) {
            // 如果是空值,返回空字符串
            return '';
        } else {
            // 其他情况,强制转换为字符串
            return (string) $value;
        }
    }

方法返回以第一行为key的数组。如下:

array(1) {
  [0] => array(12) {
    ["序号"] => string(1) "1"
    ["年级"] => string(24) "人教PEP三年级上册"
    ["单元"] => string(6) "Unit 1"
    ["单词"] => string(5) "ruler"
    ["音标"] => string(14) "/ˈruːlə(r)/"
    ["词义"] => string(6) "尺子"
    ["词组"] => string(26) "a ruler (一把尺子)"
    ["例句"] => string(78) "I need a ruler to draw a straight line.(我需要一把尺子画直线。)"
    ["正确选项"] => string(6) "尺子"
    ["错误选项1"] => string(6) "筷子"
    ["错误选项2"] => string(6) "绳子"
    ["错误选项3"] => string(6) "汽车"
  }
}

表格结构如下:

定义import_url对应的后台方法示例如下:

    /**
     * 重写import方法
     */
    public function import()
    {
        $file = $this->request->request('file'); //'file'为文件字段名
        $data_file = $this->readFile($file);
        $course_id = $this->request->get('course_id');
        if(empty($course_id)){
            $this->error('课程参数错误');
        }
        $data = [];
        foreach ($data_file as $key=>$value){
            if(!empty($value['单词'])){
                $data[] = [
                    'course_id'=>$course_id,
                    'nianji' => empty($value['年级']) ? '' : $value['年级'],
                    'danyuan' => empty($value['单元']) ? '' : $value['单元'],
                    'danci' => $value['单词'],
                    'yinbiao' => empty($value['音标']) ? '' : $value['音标'],
                    'ciyi' => empty($value['词义']) ? '' : $value['词义'],
                    'cizu' => empty($value['词组']) ? '' : $value['词组'],
                    'liju' => empty($value['例句']) ? '' : $value['例句'],
                    'zhengque' => empty($value['正确选项']) ? '' : $value['正确选项'],
                    'cuowu_one' => empty($value['错误选项1']) ? '' : $value['错误选项1'],
                    'cuowu_two' => empty($value['错误选项2']) ? '' : $value['错误选项2'],
                    'cuowu_three' => empty($value['错误选项3']) ? '' : $value['错误选项3'],
                ];
            }
        }
        if(empty($data)){
            $this->error('可导入数据为空');
        }
        $this->model->saveAll($data);
        $this->success('成功导入'.count($data).'条数据');
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/971959.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

可调节图片参数,解决图片模糊及尺寸过小问题的工具

软件介绍 你是否正为图片模糊、尺寸太小而烦恼&#xff1f;别担心&#xff0c;有这样一款神器能帮你轻松解决。它能精准调节图片参数&#xff0c;即便原本模糊不清的图片&#xff0c;经它处理后也能变得高清锐利&#xff0c;瞬间让图片焕然一新。而且&#xff0c;它还具备导出…

Windows网络安全基础

随着互联网的发展和普及&#xff0c;Windows网络安全问题愈发严重。在本文中&#xff0c;我们将会介绍Windows网络安全的基本概念&#xff0c;包括网络攻击类型、网络安全威胁、网络安全防御措施等等&#xff0c;帮助初学者更好地了解Windows网络安全。 一、网络攻击类型 网络…

代码补全『三重奏』:EverEdit如何用上下文识别+语法感知+智能片段重构你的编码效率!

1 代码自动完成 1.1 应用场景 在编辑文档时&#xff0c;为了提高编辑效率&#xff0c;编辑器一般都会带有自动完成功能&#xff0c;比如&#xff1a;输入括号时自动补全另一半&#xff0c;输入文字时&#xff0c;自动补全剩下的部分。 1.2 使用方法 1.2.1 自动缩进 单击主菜…

vue,vue3 keepalive没有效果,无法缓存页面include无效,keep-alive

keepalive没有效果&#xff0c;无法缓存页面&#xff1f; 问题大概是组件的name值不对应&#xff0c;vue2修改组件文件的name值&#xff0c;vue3保持组件文件名称和路由页面配置的name一致就可以了&#xff0c;如果vue3不想保持一致&#xff0c;必须手动在文件后面添加export..…

栈回溯方案

注&#xff1a;栈回溯无法很好的定位到未调优化的函数&#xff0c;需要编译前使用 -fno-optimize-sibling-calls 选项禁止尾调优化。 基于unwind的栈回溯 在 arm 架构下&#xff0c;不少32位系统用的是 unwind 形式的栈回溯&#xff0c;这种栈回溯要复杂很多。首先需要程序有一…

【存储中间件API】MySQL、Redis、MongoDB、ES常见api操作及性能比较

常见中间件api操作及性能比较 ☝️ MySQL crud操作✌️ maven依赖✌️ 配置✌️ 定义实体类✌️ 常用api ☝️ Redis crud操作✌️ maven依赖✌️ 配置✌️ 常用api ☝️ MongoDB crud操作✌️ maven依赖✌️ 配置文件✌️ 定义实体类✌️ MongoDB常用api ☝️ ES crud操作 ⭐️…

解锁D3.js与PlantUML的交互奥秘:探索知识图谱数据可视化新领域

解锁D3.js与PlantUML的交互魔法&#xff1a;数据可视化新征程 在前端开发的广袤天地里&#xff0c;数据可视化一直是一颗璀璨的明珠&#xff0c;吸引着无数开发者探索其奥秘。而当D3.js这一强大的JavaScript库&#xff0c;遇上专注于创建UML图的PlantUML&#xff0c;一场奇妙的…

DeepSeek24小时写作机器人,持续创作高质量文案

内容创作已成为企业、自媒体和创作者的核心竞争力。面对海量的内容需求&#xff0c;人工创作效率低、成本高、质量参差不齐等问题日益凸显。如何在有限时间内产出高质量内容&#xff1f;DeepSeek写作机器人&#xff0c;一款24小时持续创作的智能工具&#xff0c;为企业和个人提…

使用html css js 来实现一个服装行业的企业站源码-静态网站模板

最近在练习 前端基础&#xff0c;html css 和js 为了加强 代码的 熟悉程序&#xff0c;就使用 前端 写了一个个服装行业的企业站。把使用的技术 和 页面效果分享给大家。 应用场景 该制衣服装工厂官网前端静态网站模板主要用于前端练习和编程练习&#xff0c;适合初学者进行 HT…

使用html css js 开发一个 教育机构前端静态网站模板

这个教育机构网站模板是专为前端开发初学者设计的练习项目&#xff0c;适合正在学习前端的学生或自学者使用。网站内容包括首页、课程体系、师资力量、关于我们和联系我们等基础页面&#xff0c;帮助学习者熟悉网页布局、样式设计和交互功能的实现。 静态页面 简单截图 应用…

(蓝桥杯——10. 小郑做志愿者)洛斯里克城志愿者问题详解

题目背景 小郑是一名大学生,她决定通过做志愿者来增加自己的综合分。她的任务是帮助游客解决交通困难的问题。洛斯里克城是一个六朝古都,拥有 N 个区域和古老的地铁系统。地铁线路覆盖了树形结构上的某些路径,游客会询问两个区域是否可以通过某条地铁线路直达,以及有多少条…

React 低代码项目:网络请求与问卷基础实现

&#x1f35e;吐司问卷&#xff1a;网络请求与问卷基础实现 Date: February 10, 2025 Log 技术要点&#xff1a; HTTP协议XMLHttpRequest、fetch、axiosmock.js、postmanWebpack devServer 代理、craco.js 扩展 webpackRestful API 开发要点&#xff1a; 搭建 mock 服务 …

大流量汽(柴)油机泵,抗洪抢险的可靠选择|深圳鼎跃

近年来&#xff0c;全球范围内极端天气频发&#xff0c;洪涝灾害成为危及人民生命财产安全的重要因素。在抗洪抢险行动中&#xff0c;如何迅速、高效地排除积水&#xff0c;保障救援通道和安全区域成为关键。汽柴油机泵凭借其动力强、移动灵活、环境适应性强等特点&#xff0c;…

游戏开发微信小程序--工具箱之父

小程序工具箱之父已更新 Page({data: {score: 0,lives: 3,gameOver: false,playerVisible: true,level: 1,petType: cat,speedBuff: 1,coins: 0,friends: [],achievements: [],currentPetFrame: 0, // 当前宠物动画帧scoreMultiplier: 1, // 得分倍率gameSpeed: 1, // …

一.数据治理理论架构

1、数据治理核心思想&#xff1a; 数据治理理论架构图描绘了一个由顶层设计、管控机制、核心领域和管理系统四个主要部分组成的数据治理框架。它旨在通过系统化的方法&#xff0c;解决数据治理机制缺失引发的业务和技术问题&#xff0c;并最终提升企业的数据管理水平。 数据治…

一键安装教程

有需要的可以私信 亮点&#xff1a; 不再需要安装完去配置环境变量&#xff0c;下载完程序&#xff0c;解压后&#xff0c;右键进行管理员安装&#xff0c;安装完毕自动配置环境变量&#xff0c;即可使用 Maven 安装 右键 以管理员身份运行点击 下一步安装完成后会同步配置环境…

crud项目分析(2)

JWT令牌验证是否登录成功 简单的验证账号密码是否正确(存在) 全局异常处理器 过滤器 因为login下只有这一个网页 唯一一种操作 package com.itheima.filter;import ch.qos.logback.core.util.StringUtil; import com.alibaba.fastjson.JSONObject; import com.itheima.pojo.R…

深入解析iOS视频录制(二):自定义UI的实现

深入解析 iOS 视频录制&#xff08;一&#xff09;&#xff1a;录制管理核心MWRecordingController 类的设计与实现 深入解析iOS视频录制&#xff08;二&#xff09;&#xff1a;自定义UI的实现​​​​​​​ 深入解析 iOS 视频录制&#xff08;三&#xff09;&#xff1a;完…

【Linux系统】生产者消费者模型:基于环形队列(信号量机制)

理论层面 1、环形队列的特性认识 环形队列采用数组模拟&#xff0c;用模运算来模拟环状特性 环形结构起始状态和结束状态都是⼀样的&#xff0c;不好判断为空或者为满&#xff0c;所以可以通过加计数器或者标记位来判断满或者空。另外也可以预留⼀个空的位置&#xff0c;作为…

【笔记】LLM|Ubuntu22服务器极简本地部署DeepSeek+API使用方式

2025/02/18说明&#xff1a;2月18日~2月20日是2024年度博客之星投票时间&#xff0c;走过路过可以帮忙点点投票吗&#xff1f;我想要前一百的实体证书&#xff0c;经过我严密的计算只要再拿到60票就稳了。一人可能会有多票&#xff0c;Thanks♪(&#xff65;ω&#xff65;)&am…