PHP+laravel 生成word

此功能较为繁琐我会从源头讲起

首先是数据库设置,下面是我的数据库结构

合同模版表

CREATE TABLE `contract_tpl` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '合同名称',
  `file` varchar(191) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '合同文件',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_unicode_ci;

生成word,可以参考phpword使用整理-CSDN博客

实现思路:

编写一个合同模版,将word文件中变量使用“${变量名}”的格式填写如下图所示:

执行命令安装phpword:

composer require phpoffice/phpword

代码如下图:

static public function word()
    {

        $order_id = request()->get('order_id');
        $tpl_id = request()->get('tpl_id');

        $saleData = SaleItem::where('order_id',$order_id)->get()->toArray();
        if ($saleData == null){
            return '此订单没有选择产品';
        }

        $sale_order = SaleOrderModel::with(['customer','items','user.employee','amount'])->where('id',$order_id)->first();
        $modelcontract = ContractTplModel::where('id',$tpl_id)->first();

        if ($sale_order->user == null){
            return '此订单没有负责人';
        }
        $folderPath = storage_path('app/public/contract');
        if (!file_exists($folderPath)) {
            // 文件夹不存在,创建文件夹
            mkdir($folderPath, 0777, true); // 第一个参数是路径,第二个参数是权限,第三个参数表示递归创建
        }

        $file = $modelcontract->file;
        if ($file == null){
            return '请上传合同模版';
        }

        foreach($sale_order->items as $key => $val){
//            $unit = GoodsSkuModel::UNIT_MAP[$items->sku->unit];
            $item_data[$key]['id'] = $key+1;
            $item_data[$key]['item_id'] =  $val->sku_id;
            $item_data[$key]['goods_name'] = $val->sku->goods_name ?? '';
            $item_data[$key]['sku_name'] = $val->sku->sku_name ?? '';
            $item_data[$key]['num'] = $val->should_num ?? '';
            $item_data[$key]['after_tax_price'] = $val->after_tax_price ?? '';
            $item_data[$key]['point_price'] = $val->point_price ?? '';
            $item_data[$key]['point'] = $val->point ?? '';
            $goods_name[] = $val->sku->goods_name ?? '';

        }
        $trade_name = implode("、", array_unique($goods_name));

        $file_path = storage_path('app/public/' . $file);
//        dd($file_path);
        if (!file_exists($file_path)) {
            return '该合同模版文件不存在,请重新上传模版文件';
        }

        $templateProcessor = new TemplateProcessor($file_path);

        $party_a = $sale_order->customer->name;//甲方名称
        $product_name = $trade_name;//产品名称
        $total_amount = $sale_order->total_amount ?? ''; //含税总价
        $first_price = $total_amount * 0.7;
        $tow_price = $total_amount * 0.2;
        $price3 = $total_amount *0.1;
        $support = new Support();
        $first_price_cn = $support->convertAmountToCn($first_price);
        $tow_price_cn = $support->convertAmountToCn($tow_price);
        $price3_cn = $support->convertAmountToCn($price3);

        $prefix = str_replace('-','','sk'.$sale_order->user->prefix.build_ws_no()) ?? '';//合同前缀

        $templateProcessor->setValues(array(
            '合同编号'=>$prefix,
            '甲方名称'=>$party_a,
            '产品名称'=>$product_name,
            '含税总价'=>$sale_order->total_amount,
            '大写总价'=>$support->convertAmountToCn($sale_order->total_amount),
            '第一笔金额'=>$first_price,
            '第一笔金额大写'=>$first_price_cn,
            '一笔货款发出时间'=>3,
            '收到货物工作日'=>2,
            '收到货物百分比'=>30,
            '第二笔金额'=>$tow_price,
            '第二笔金额大写'=>$tow_price_cn,
            '第二笔货款工作日'=>$tow_price,
            '第三笔货款'=>$price3,
            '第三笔货款大写'=>$price3_cn,
            '甲方负责人姓名'=>$sale_order->customer->contacts_name??'',
            '甲方负责人电话'=>$sale_order->customer->contacts_mobile ?? '',
            '乙方负责人姓名'=>$sale_order->user->employee->name ?? '',
            '乙方负责人电话'=>$sale_order->user->employee->mobile ?? '',
            '增值税专用发票'=> 6 ?? '',
        ));
        if (count($item_data)){
            $templateProcessor->cloneRow('id',count($item_data));

            foreach ($item_data as $k =>  $v) {
                $templateProcessor->setValue('id#'. ($k + 1), $v['id']);
                $templateProcessor->setValue('goods_name#'. ($k + 1), $v['goods_name']);
                $templateProcessor->setValue('sku_name#'. ($k + 1), $v['sku_name']);
                $templateProcessor->setValue('num#' . ($k + 1), $v['num']);
                $templateProcessor->setValue('after_tax_price#' . ($k + 1), $v['after_tax_price']);
                $templateProcessor->setValue('point#' . ($k + 1), $v['point']);
                $templateProcessor->setValue('point_price#' . ($k + 1), $v['point_price']);
            }
        }
        $word_name = $sale_order->customer->name;
        $templateProcessor->saveAs( storage_path("app/public/contract/".$word_name.".docx"));

        $file_path = "/contract/".$word_name.".docx";  // 文件的路径和名称
        SaleOrderModel::query()->where('id',$order_id)->update([
            'tpl_id'=>$tpl_id,
            'contract'=>$file_path,
        ]);
        $tpl = ContractTplModel::query()->get()->toArray();
        $file_name = get_file_path($file_path);

        return view('page/generate_office',compact('order_id','tpl_id','file_name','tpl'));
    }

word文件在页面展示:

这里用到的是amis前端框架网址可参考:amis - 低代码前端框架

创建一个视图文件如下图所示:

文件代码:

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="UTF-8" />
    <title>@yield('title')</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta
        name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1"
    />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <!-- amis -->
    <link rel="stylesheet" href="{{ asset('static/css/sdk.css') }}" />
    <link rel="stylesheet" href="{{ asset('static/css/helper.css') }}" />
    <link rel="stylesheet" href="{{ asset('static/css/iconfont.css') }}" />
    <link rel="stylesheet" href="{{ asset('static/css/main.css?v='.config('admin.version')) }}" />
    <!-- 这是默认主题所需的,如果是其他主题则不需要 -->
    <!-- 从 1.1.0 开始 sdk.css 将不支持 IE 11,如果要支持 IE11 请引用这个 css,并把前面那个删了 -->
    <!-- <link rel="stylesheet" href="sdk-ie11.css" /> -->
    <!-- 不过 amis 开发团队几乎没测试过 IE 11 下的效果,所以可能有细节功能用不了,如果发现请报 issue -->
    <style>
        html,
        body,
        .app-wrapper {
            position: relative;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    @yield('head')
</head>
<body>
<div id="root" class="app-wrapper"></div>
<script src="{{ asset('static/js/sdk.js') }}"></script>
<script src="{{ asset('static/js/charts.js') }}"></script>
<script src="{{ asset('static/js/office-viewer.js') }}"></script>
<script src="{{ asset('static/js/papaparse.js') }}"></script>
<script src="{{ asset('static/js/pdf-viewer.js') }}"></script>
<script src="{{ asset('static/js/tinymce.js') }}"></script>
@yield('foot')
</body>
</html>

创建一个视图文件,使用下图方式引入模版文件

@extends('layouts.amis')
@section('title','生产工单时间线')
@section('foot')
    

@endsection

完整代码

@extends('layouts.amis')
@section('title','生产工单时间线')
@section('foot')
    
    <script type="text/javascript">

        (function () {
            let amis = amisRequire('amis/embed');
            // 通过替换下面这个配置来生成不同页面
            let amisJSON = {
                "type": "page",
                //侧边栏
                "aside": {
                    "type": "nav",
                    "name": "nav",
                    "stacked": true,
                    "source": "{{admin_url('tpl_info?order_id='.$order_id)}}",

                },
                "body": [
                {
                    "type": "nav",
                    "stacked": true,
                    "source": "${nav}",
                },
                @if(isset($error) && $error == 2)
                    {
                        "type": "page",
                        "body": "请点击左侧合同模版"
                    },
                @endif
                    @if($file_name != null )
                    {
                        "type": "button-toolbar",
                        "buttons": [
                            {
                                "type": "action",
                                "label": "下载word文档",
                                "cssVars": {
                                    "--primary-padding": "10px 200px",
                                },
                                "onEvent": {
                                    "click": {
                                        "actions": [
                                            {
                                                "actionType": "saveAs",
                                                "componentId": "office-viewer-download",
                                            },
                                        ],

                                    }
                                }
                            },
                            {
                                "type": "office-viewer",
                                "id": "office-viewer-download",
                                "display": false,
                                "src": "{{$file_name}}",
                                "padding": "10px 200px",
                                "ignoreWidth": true,
                            },
                            {
                                "type": "link",
                                'body':'PDF下载',
                                "className" : "pdf_span  span",
                                "href": "{{admin_url('sale-order/wordToPdf?order_id='.$order_id)}}",
                                "style": {
                                    "margin-left": "80px",
                                    "margin-top" : "5px",
                                    "padding" : "3px 12px",
                                }
                            },
                        ]
                    },
                    {
                        "type": "office-viewer",
                        'name':'word',
                        'id':'word',
                        "src": "{{$file_name}}",
                        "wordOptions": {
                            "padding": "10px 200px",
                            "ignoreWidth": true,
                        }
                    },

                        @else

            {
                "type": "page",
                "body": "请点击左侧合同模版"
            }

            @endif
                ]


            };
            // window.location.reload()
            let amisScoped = amis.embed('#root', amisJSON);
        })();

    </script>
@endsection

侧边栏是一个单独的接口/或者说也可以写为固定值

    public function tpl_info()
    {
        $line = ContractTplModel::query()->get();
        $order_id = request()->get('order_id');
        foreach ($line as $item){
            $options[] = [

                'label'=>$item->name,
                'value'=>$item->id,
                'to'=> admin_url("sale-order/word?order_id=".$order_id."&"."tpl_id=".$item->id),
            ];
        }
        $this->amis_res([
            'options'=>$options
        ]);

    }

最终效果如图所示:

 

生成PDF留在下节讲解

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

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

相关文章

redis集群简单介绍及其搭建过程

Redis集群 1、哨兵模式 哨兵可以有多个&#xff0c;从服务器也可以有多个&#xff0c;从服务器也可以有多个&#xff0c;在Redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态&#xff0c;如果master节点异常&#xff0c;则会实现主从切换&#x…

WMV 视频格式怎么转换?WMV 视频为什么不流行了?

目前有越来越多的视频格式类型&#xff0c;如常见的 MP4、FLV、AVI 等等&#xff0c;而技术的演变也逐渐让一些常见的视频格式变的越来越少了。 今天我们一起来聊下 WMV 这个视频格式&#xff0c;让我们看看它的发展以及为什么现在越来越少人使用了。 什么是 WMV 视频格式&…

沙姆镜头标定与重建

沙姆定律&#xff08; Scheimpflug principle&#xff09;则可以保证测量平面的物体能够清晰成像&#xff0c; 因此能够起到调整景深区域位置的作用。Scheimpflug 镜头就是根据沙姆定律所设计的一种特殊的镜头&#xff0c;通过机械结构使镜头与相机本体发生一定程度的偏转&…

如何将本地的Django项目部署到阿里云服务器上?

场景&#xff1a;在本地的pycharm上已经写好了一个Django架构的网站&#xff0c;现在要把它放到公网上 一、阿里云服务器 选择云服务器ECS&#xff0c;新用户可以免费使用三个月 购买时选择预装宝塔面板 买好后&#xff0c;进入云服务器控制台 重置实例密码 远程连接至服务…

腰背肌筋膜炎的症状及治疗

腰背肌筋膜炎的症状 一、疼痛特点&#xff1a; 主要表现为腰背部弥漫性钝痛&#xff0c;尤以两侧腰肌及髂嵴上方更为明显。疼痛特点为晨起痛&#xff0c;日间轻&#xff0c;傍晚复重。长时间不活动或活动过度均可诱发疼痛&#xff0c;病程长&#xff0c;且因劳累及气候变化而发…

东南亚本地化游戏

通常&#xff0c;亚洲电子游戏市场首先与中国联系在一起。但最近&#xff0c;分析人士越来越关注一个邻近地区&#xff1a;东南亚。而且有充分的理由。 该地区包括中南半岛、马来群岛和邻近岛屿上的十一个国家。1967年&#xff0c;其中10个国家&#xff08;除东帝汶外&#xf…

透明屏幕的魅力:为何它如此受欢迎

在科技日新月异的今天&#xff0c;透明屏幕技术以其独特的魅力和广泛的应用前景&#xff0c;逐渐成为了科技领域的一颗璀璨明星。从智能手机、平板电脑到大型显示屏&#xff0c;透明屏幕技术以其前所未有的视觉体验和实用性&#xff0c;赢得了广大消费者的喜爱。 一、透明屏幕的…

进阶篇07——InnoDB引擎介绍

概览 逻辑存储结构 架构 当执行增删改查操作时&#xff0c;操作的是缓冲区的数据&#xff0c;如果缓冲区里没有要操作的数据&#xff0c;就会从磁盘中读取数据加载到缓冲区中&#xff1b;缓冲区的数据会以一定的频率通过后台线程刷新到磁盘中永久存储。 内存结构 磁盘结构 后…

vue3 antv/g6 动态设置mode,让节点不可以拖动

1、查看一下官网的设置说明 G6 设置mode 默认模式&#xff1a; const graph new G6.Graph({container: div,width: 500,height: 500,modes: {default: [drag-node,drag-canvas],custom: [drag-canvas]} })默认情况下&#xff0c;我们定义的是default&#xff0c;然后创建节…

JavaWeb——MySQL:DML对表数据的修改

2.DML对表数据的修改 2.1 修改表的数据 (1) 修改单行单列 SQL语句&#xff1a;update 表名 set 列名1数值1 where 列名2数值2&#xff1b; 将sql_student表姓名为吕小布的那行&#xff0c;性别设置为女&#xff1b; (2) 修改单行多列 SQL语句&#xff1a;update 表名 set 列…

Dooprime外汇:如何高效规划家庭理财?从哪里开始?

摘要&#xff1a; 家庭理财是每个家庭都必须面对的重要课题。合理的理财规划不仅能提高家庭的生活质量&#xff0c;还能为未来的生活提供保障。然而&#xff0c;许多人在面对复杂的理财选项和信息时感到无从下手。本文将从不同角度详细分析如何进行高效的家庭理财规划&#xf…

SVN学习(007 svn安装Tortoise工具)

尚硅谷SVN高级教程(svn操作详解) 总时长 4:53:00 共72P 此文章包含第58p-第p72的内容 介绍 安装 选择自己想要装软件的文件夹 进入工作目录&#xff0c;发现无svn的图标&#xff0c;重启电脑即可 就能看到svn的图标 settings功能 进行图标的查看 修改subversion配置文件 …

基于 Redis 实现秒杀资格判断,提升并发性能

在互联网电商平台上&#xff0c;秒杀活动往往会吸引大量用户同时抢购&#xff0c;如何高效地处理高并发请求&#xff0c;保证用户体验&#xff0c;是一个重要的技术挑战。本文将介绍如何基于 Redis 实现秒杀资格的判断&#xff0c;提高并发性能。 基本思路 秒杀活动的核心流程…

Android跨进程调用,Binder线程池溢出导致ANR

Android跨进程调用&#xff0c;Binder线程池溢出导致ANR 如果发生ANR&#xff0c;找到trace.txt 、/data/anr目录下&#xff0c; "main" prio5 tid1 Native| group"main" sCount1 dsCount0 flags1 obj0x72c33e38 self0x78a64c2a00| sysTid1863 nice0 cgr…

任务4.8.4 利用Spark SQL实现分组排行榜

文章目录 1. 任务说明2. 解决思路3. 准备成绩文件4. 采用交互式实现5. 采用Spark项目实战概述&#xff1a;使用Spark SQL实现分组排行榜任务背景任务目标技术选型实现步骤1. 准备数据2. 数据上传至HDFS3. 启动Spark Shell或创建Spark项目4. 读取数据5. 数据转换6. 创建临时视图…

PS系统教程28

Alpha通道&#xff08;透明通道&#xff09; 8位的灰度通道&#xff0c;也有256个位置记录图片当中的透明度信息 作用&#xff1a;定义透明、半透明、不透明通道信息。保存、存储选区。 白色不透明区域黑色透明区域灰色半透明区域 案例 为了将我们抠出来的人物方便下次修改…

Opencv学习项目6——pyzbar

在之前我们学习了解码图片中的二维码&#xff0c;这次我们开启摄像头来解码视频中二维码 开启摄像头 # 打开摄像头 cap cv2.VideoCapture(0) cap.set(3, 640) # 设置摄像头画面宽度 cap.set(4, 480) # 设置摄像头画面高度 我使用的是笔记本上的摄像头来进行的&#xff0c;…

CleanMyMac中文版2024官方正式版下载!你的电脑清洁专家!

CleanMyMac中文版&#xff0c;你的电脑清洁专家&#xff01;✨&#x1f9f5; 你是否曾为电脑的卡顿和垃圾文件而烦恼&#xff1f;别担心&#xff0c;CleanMyMac中文版来帮你解决这些问题&#xff01;这款神奇的软件不仅可以帮助你清理垃圾文件&#xff0c;还能优化系统性能&…

什么是营销翻译?为什么要使用它?

营销翻译是将营销活动和宣传品翻译成不同语言的过程。它可能涉及翻译您的&#xff1a; 网站营销文案&#xff0c;社交媒体帖子&#xff0c;演示文稿&#xff0c;新闻稿&#xff0c;产品包装&#xff0c;产品说明&#xff0c;海报&#xff0c;宣传册&#xff0c;以及 虽然企业…

商家转账到零钱申请驳回解决方案

商家转账到零钱是什么&#xff1f; 商家转账到零钱&#xff0c;简单说&#xff0c;就是微信支付提供的一个功能&#xff0c;让商家能够方便、快捷、安全地将钱转到用户的微信零钱里。这个功能特别适用于那些需要给用户发红包、退款或者进行其他形式转账的商家。它提供了两种转…