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

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

相关推荐
Devil枫10 分钟前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
GIS程序媛—椰子1 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享2 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果2 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
凉辰4 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
清灵xmf4 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
薛一半5 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js
过期的H2O25 小时前
【H2O2|全栈】JS进阶知识(四)Ajax
开发语言·javascript·ajax