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

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

相关推荐
ggdpzhk33 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
小曲曲2 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•3 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS4 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o5 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā6 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder7 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript