vue 使用docx-preview 预览替换文档内的特定变量

在开发合同管理中,需要使用到此功能,就是替换合同模板内的一些字符串,如:甲乙方名称,金额日期等,合同内容不变。效果如下:

使用docx-preview 好处是只预览不可编辑内容。

前端vue

javascript 复制代码
import { renderAsync } from 'docx-preview';

// 替换文件内容
function onWordSave(){
  axios({
    method: "post",
    responseType: "blob", // 因为是流文件,所以要指定blob类型
    url: Http.getBaseURL() + "/contract/Index/setWord", // 自己的服务器,提供的一个word下载文件接口
    data:{'fieldData':select_field.value,'tem_id':form.value.tem_id}
  }).then(response => {
    if (response.status === 200) {
      // 检查Content-Type是否是预期的类型
      const contentType = response.headers['content-type'] || response.headers['Content-Type'];
      if (contentType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
        // 数据正确,处理blob数据
        ElMessage({type:'success', message:'替换模板内容成功'})
        file_url.value = response.data
      }else {
        // 数据类型不匹配
        ElMessage({type:'error', message: '模板内容替换失败'})
      }
    } else {
      // 响应状态不是200
      ElMessage({type:'error', message: 'failed to open stream: No such file or directory'})
    }
  }).catch(error => {
    // 请求失败,处理错误
    ElMessage({type:'error', message:error})
  });
}
// 预览文件
function docxRender() {
  ContractFileRef.value.innerHTML = ''; // 清空之前的内容
  if(file_url.value != ''){
    let blob = new Blob([file_url.value]); // 将 OSS 文件转为 Blob 对象
    // 渲染文档并获取内容控件
    renderAsync(blob, ContractFileRef.value);
  }
}

后端 控制器方法:

php 复制代码
 /**
     * @名称:模板内容替换
     * User: congxion
     * Date: 2024/10/31 16:44
     */
    public function setWord(){
        try{
            $param = $this->request->param();
            if(empty($param['tem_id'])){
                return jsonError('请选择合同模板');
            }
            if(empty($param['fieldData'])){
                return jsonError('没有可替换的内容');
            }
            return $res = ContractService::setWord($param['fieldData'], $param['tem_id']);
        }catch(\Exception $e){
            return jsonError($e->getMessage());
        }
    }

后端逻辑层方法

php 复制代码
public static function setWord($data,$met_id){
        $template = Db::name('template')->where(['id'=>$met_id])->find();
        if(empty($template['file_url'])){
            throw new Exception('没有模板文件');
        }
        // 加载Word文档
        $template_path = public_path().'storage/'.$template['file_url'];
        if(!file_exists($template_path)){
            throw new Exception(public_path().'storage/'.$template['file_url']);
        }
        //读取模版word的版本最好是docx,要不然可能会读取不了
        $templateProcessor = new TemplateProcessor($template_path);
        $data_str = "";
        foreach ($data as $k => $v) { //读取模版word的版本最好是docx,要不然可能会读取不了
            $newname = !empty($v['newname']) ? $v['newname']: '';
            $templateProcessor->setValue($v['key'], $newname); //替换模板中的变量,对应word里的 ${xxxx}
            $data_str .= $v['key'].$newname;
        }
        $save_name = GetRandStr(5).'_'.time() . '.docx'; //保存的文件名
        $return_path = 'storage/temword/'.date('Ymd').'/'; //保存的文件路径
        $savepath = public_path() . $return_path;
        if (!is_dir($savepath)) {
            @mkdir($savepath,0777);
        }
        $templateProcessor->saveAs($savepath.$save_name); //将内容保存到生成新的word中
        $data_md5 = md5($met_id.$data_str);
        // 缓存文件名
        Cache::set($data_md5, $return_path.$save_name, 3600);
        // 或输出到浏览器
        header('Content-Description: File Transfer');
        header('Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
        header('Content-Disposition: attachment; filename="output.docx"');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Expires: 0');
        readfile($savepath.$save_name);
        exit;
    }

接口返回的是文件流,前端插件可直接使用

相关推荐
VT.馒头42 分钟前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
css趣多多1 小时前
一个UI内置组件el-scrollbar
前端·javascript·vue.js
-凌凌漆-1 小时前
【vue】pinia中的值使用 v-model绑定出现[object Object]
javascript·vue.js·ecmascript
大橙子额3 小时前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
WooaiJava4 小时前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
LYFlied4 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
Never_Satisfied5 小时前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html
董世昌415 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
B站_计算机毕业设计之家5 小时前
豆瓣电影数据采集分析推荐系统 | Python Vue Flask框架 LSTM Echarts多技术融合开发 毕业设计源码 计算机
vue.js·python·机器学习·flask·echarts·lstm·推荐算法
WeiXiao_Hyy6 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端