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;
    }

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

相关推荐
爱的叹息15 分钟前
解决 Dart Sass 的旧 JS API 弃用警告 的详细步骤和解决方案
javascript·rust·sass
夕水1 小时前
这个提升效率宝藏级工具一定要收藏使用
前端·javascript·trae
会飞的鱼先生1 小时前
vue3 内置组件KeepAlive的使用
前端·javascript·vue.js
苹果酱05671 小时前
【Azure Redis 缓存】在Azure Redis中,如何限制只允许Azure App Service访问?
java·vue.js·spring boot·mysql·课程设计
前端大白话2 小时前
前端崩溃瞬间救星!10 个 JavaScript 实战技巧大揭秘
前端·javascript
一千柯橘2 小时前
Nestjs 解决 request entity too large
javascript·后端
举个栗子dhy2 小时前
如何处理动态地址栏参数,以及Object.entries() 、Object.fromEntries()和URLSearchParams.entries()使用
javascript
宁静_致远2 小时前
React Native 技术栈:基于 macOS 开发平台的 iOS 应用开发指南
前端·javascript·react native
H5开发新纪元2 小时前
VS Code 插件开发实战:代码截图工具
javascript·visual studio code
DevUI团队3 小时前
超越input!基于contentediable实现github全局搜索组件:从光标定位到输入事件的全链路设计
前端·javascript