本地Word图文直接复制到富文本编辑器中

当前功能基于PHP,其它语言流程大致相同

1.新增上传word json配置

在ueditor\php\config.json中新增如下配置:

    /* 上传word配置 */

    "wordActionName": "wordupload", /* 执行上传视频的action名称 */

    "wordFieldName": "upfile", /* 提交的视频表单名称 */

    "wordPathFormat": "/public/uploads/word/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */

    "wordMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */

    "wordAllowFiles": [".docx"] /* 仅支持docx格式的word */

2.修改编辑器配置文件,在工具栏上新增按钮

在ueditor\ueditor.config.js文件中,新增按钮名称"wordupload",并添加鼠标悬浮提示,如下所示:

        //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义

        , toolbars: [[

            'fullscreen', 'source', '|', 'undo', 'redo', '|',

            'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',

            'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',

            'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',

            'directionalityltr', 'directionalityrtl', 'indent', '|',

            'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',

            'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',

            'simpleupload', 'insertimage', 'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|',

            'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|',

            'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|',

            'print', 'preview', 'searchreplace', 'drafts', 'help', 'wordupload'

        ]]

        //当鼠标放在工具栏上时显示的tooltip提示,留空支持自动多语言配置,否则以配置值为准

        ,labelMap:{

           'wordupload': '上传word文件',

        }

在ueditor\themes\default\images\目录下新增按钮图标"word_upload.png":

 在ueditor\themes\default\css\ueditor.css文件中新增按钮样式:

.edui-for-wordupload .edui-icon {

    width: 16px;

    height: 16px;

    background: url(../images/word_upload.png) no-repeat 2px 2px !important;

}

最后在ueditor\ueditor.all.js文件中editorui["simpleupload"] = function (editor){}后面添加如下代码:

/* word上传 */

    editorui["wordupload"] = function (editor) {

        var name = 'wordupload',

            ui = new editorui.Button({

                className:'edui-for-' + name,

                title:editor.options.labelMap[name] || editor.getLang("labelMap." + name) || '',

                onclick:function () {},

                theme:editor.options.theme,

                showText:false

            });

        editorui.buttons[name] = ui;

        editor.addListener('ready', function() {

            var b = ui.getDom('body'),

                iconSpan = b.children[0];

            editor.fireEvent('worduploadbtnready', iconSpan);

        });

        editor.addListener('selectionchange', function (type, causeByUi, uiReady) {

            var state = editor.queryCommandState(name);

            if (state == -1) {

                ui.setDisabled(true);

                ui.setChecked(false);

            } else {

                if (!uiReady) {

                    ui.setDisabled(false);

                    ui.setChecked(state);

                }

            }

        });

        return ui;

};

最终样式如下:

 3. 新增语言配置

在ueditor\lang\zh-cn\zh-cn.js文件中在"simpleupload"配置下方新增以下配置:

'simpleupload':{

        'exceedSizeError': '文件大小超出限制',

        'exceedTypeError': '文件格式不允许',

        'jsonEncodeError': '服务器返回格式错误',

        'loading':"正在上传...",

        'loadError':"上传错误",

        'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!'

    },

    'wordupload':{

        'exceedSizeError': '文件大小超出限制',

        'exceedTypeError': '文件格式不允许',

        'jsonEncodeError': '服务器返回格式错误',

        'loading':"正在上传...",

        'loadError':"上传错误",

        'errorLoadConfig': '后端配置项没有正常加载,上传插件不能正常使用!'

    },

在ueditor\lang\zh-cn\en.js文件中在"simpleupload"配置下方新增以下配置:

'simpleupload':{

        'exceedSizeError': 'File Size Exceed',

        'exceedTypeError': 'File Type Not Allow',

        'jsonEncodeError': 'Server Return Format Error',

        'loading':"loading...",

        'loadError':"load error",

        'errorLoadConfig': 'Server config not loaded, upload can not work.',

    },

    'wordupload':{

        'exceedSizeError': 'File Size Exceed',

        'exceedTypeError': 'File Type Not Allow',

        'jsonEncodeError': 'Server Return Format Error',

        'loading':"loading...",

        'loadError':"load error",

        'errorLoadConfig': 'Server config not loaded, upload can not work.',

    },

4.修改过滤配置

由于导入word时,编辑器会自动过滤掉图片等样式,所以需取消过滤

在ueditor\ueditor.config.js文件中修改如下配置:

// xss 过滤是否开启,inserthtml等操作

,xssFilterRules: false

//input xss过滤

,inputXssFilter: false

//output xss过滤

,outputXssFilter: false

在ueditor\ueditor.all.js文件中,修改UE.plugins[‘defaultfilter’],新增return ;如下所示:

// plugins/defaultfilter.js

///import core

///plugin 编辑器默认的过滤转换机制

UE.plugins['defaultfilter'] = function () {

    return;

    var me = this;

    me.setOpt({

        'allowDivTransToP':true,

        'disabledTableInTable':true

    });

    ……

5.安装PHPword

composer require phpoffice/phpword

6.自定义文件转换类

实现上传文件,并将文件转换为HTML

直接将ueditor自带的上传文件"ueditor\php\Uploader.class.php"类内容直接复制到自定义WordToHtmlController.class.php文件中

<?php

class WordToHtmlController

{

    public function index()

    {

        require 'vendor/autoload.php';

        $base64 = "upload";

        $config = array(

            "pathFormat" => '/public/uploads/word/{yyyy}{mm}{dd}/{time}{rand:6}',

            "maxSize" => 102400000,

            "allowFiles" => [".docx"]

        );

        $fieldName = 'upfile';

        include 'Uploader.class.php';

        $up = new Uploader($fieldName, $config, $base64);

        $path = ltrim($up->getFileInfo()['url'], '/');

//        $phpWord = \PhpOffice\PhpWord\IOFactory::load('public/uploads/word/20211029/test.docx');

        $phpWord = \PhpOffice\PhpWord\IOFactory::load($path);

        // 直接输出到页面显示

//        $phpWord->save('php://output', 'HTML');

        $xmlWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML');

        header("Content-Type:text/html; charset=utf-8");

        exit($this->replaceImageSrc($xmlWriter->getContent()));

//        exit($xmlWriter->getContent());

    }

    /**

     * 将HTML代码中的所有图片地址替换

     * @param $content string 要查找的内容

     * @return string

     */

    private function replaceImageSrc($content)

    {

        $preg = '/(\s+src\s?\=)\s?[\'|"]([^\'|"]*)/is'; // 匹配img标签的正则表达式

        preg_match_all($preg, $content, $allImg); // 匹配所有的img

        if (!$allImg)

            return $content;

        foreach ($allImg[0] as $k => $v) {

            $old = ltrim($v, '" src=');

            preg_match('/^(data:\s*image\/(\w+);base64,)/', $old, $temp);

            $tempType = $temp[2];   // 获取类型

            // 判断目录是否存在,不存在时创建

            $tempFilePath = 'public/uploads/word_images/' . date('Y-m-d', time());

            if (!file_exists($tempFilePath))

                mkdir($tempFilePath);

            // 拼接完整路径

            $tempFileName = $tempFilePath . '/word_image_' . time() . $k . '.' . $tempType;

            $base64 = str_replace($temp[1], '', $old);

            file_put_contents($tempFileName, base64_decode($base64));

            // 替换路径字符串

            $content = str_replace($old, $tempFileName, $content);

        }

        return $content;

    }

}

7.编辑器实现导入操作

在ueditor\ueditor.all.js文件中UE.plugin.register('simpleupload', function (){})下方新增如下方法

/**

 * @description

 * word上传:点击按钮,直接选择文件上传

 */

UE.plugin.register('wordupload', function (){

    var me = this,

        isLoaded = false,

        containerBtn;

    function initUploadBtn(){

        var w = containerBtn.offsetWidth || 20,

            h = containerBtn.offsetHeight || 20,

            btnIframe = document.createElement('iframe'),

            btnStyle = 'display:block;width:' + w + 'px;height:' + h + 'px;overflow:hidden;border:0;margin:0;padding:0;position:absolute;top:0;left:0;filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity: 0;opacity: 0;cursor:pointer;';

        domUtils.on(btnIframe, 'load', function(){

            var timestrap = (+new Date()).toString(36),

                wrapper,

                btnIframeDoc,

                btnIframeBody;

            btnIframeDoc = (btnIframe.contentDocument || btnIframe.contentWindow.document);

            btnIframeBody = btnIframeDoc.body;

            wrapper = btnIframeDoc.createElement('div');

            wrapper.innerHTML = '<form id="edui_form_' + timestrap + '" target="edui_iframe_' + timestrap + '" method="POST" enctype="multipart/form-data" action="' + me.getOpt('serverUrl') + '" ' +

                'style="' + btnStyle + '">' +

                '<input id="edui_input_' + timestrap + '" type="file" accept="application/msword" name="' + me.options.wordFieldName + '" ' +

                'style="' + btnStyle + '">' +

                '</form>' +

                '<iframe id="edui_iframe_' + timestrap + '" name="edui_iframe_' + timestrap + '" style="display:none;width:0;height:0;border:0;margin:0;padding:0;position:absolute;"></iframe>';

            wrapper.className = 'edui-' + me.options.theme;

            wrapper.id = me.ui.id + '_iframeupload';

            btnIframeBody.style.cssText = btnStyle;

            btnIframeBody.style.width = w + 'px';

            btnIframeBody.style.height = h + 'px';

            btnIframeBody.appendChild(wrapper);

            if (btnIframeBody.parentNode) {

                btnIframeBody.parentNode.style.width = w + 'px';

                btnIframeBody.parentNode.style.height = w + 'px';

            }

            var form = btnIframeDoc.getElementById('edui_form_' + timestrap);

            var input = btnIframeDoc.getElementById('edui_input_' + timestrap);

            var iframe = btnIframeDoc.getElementById('edui_iframe_' + timestrap);

            domUtils.on(input, 'change', function(){

                if(!input.value) return;

                var loadingId = 'loading_' + (+new Date()).toString(36);

                var allowFiles = me.getOpt('wordAllowFiles');

                me.focus();

                me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme +'/images/spacer.gif" title="' + (me.getLang('wordupload.loading') || '') + '" >');

                function callback(){

                    try{

                        // 获取到内容

                        var body = (iframe.contentDocument || iframe.contentWindow.document).body;

                        // 获取加载中图片并关闭

                        var loader = me.document.getElementById(loadingId);

                        loader.removeAttribute('id');

                        domUtils.removeClasses(loader, 'loadingclass');

                        // 向编辑器赋值

                        me.setContent(body.innerHTML, false);

                        // me.execCommand('insertHtml', body.innerHTML);

                    }catch(er){

                        showErrorLoader && showErrorLoader(me.getLang('wordupload.loadError'));

                    }

                    form.reset();

                    domUtils.un(iframe, 'load', callback);

                }

                function showErrorLoader(title){

                    if(loadingId) {

                        var loader = me.document.getElementById(loadingId);

                        loader && domUtils.remove(loader);

                        me.fireEvent('showmessage', {

                            'id': loadingId,

                            'content': title,

                            'type': 'error',

                            'timeout': 4000

                        });

                    }

                }

                /* 判断后端配置是否没有加载成功 */

                if (!me.getOpt('wordActionName')) {

                    errorHandler(me.getLang('autoupload.errorLoadConfig'));

                    return;

                }

                // 判断文件格式是否错误

                var filename = input.value,

                    fileext = filename ? filename.substr(filename.lastIndexOf('.')):'';

                if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {

                    showErrorLoader(me.getLang('wordupload.exceedTypeError'));

                    return;

                }

                domUtils.on(iframe, 'load', callback);

                // 上传操作

                // form.action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?':'&') + params);

                // 替换请求地址为框架后台地址

                form.action = "/admin.php?m=fwordToHtml&a=index"//这个地址依据自己系统而定

                form.method = "post"

                form.submit();

            });

            var stateTimer;

            me.addListener('selectionchange', function () {

                clearTimeout(stateTimer);

                stateTimer = setTimeout(function() {

                    var state = me.queryCommandState('wordupload');

                    if (state == -1) {

                        input.disabled = 'disabled';

                    } else {

                        input.disabled = false;

                    }

                }, 400);

            });

            isLoaded = true;

        });

        btnIframe.style.cssText = btnStyle;

        containerBtn.appendChild(btnIframe);

    }

    return {

        bindEvents:{

            'ready': function() {

                //设置loading的样式

                utils.cssRule('loading',

                    '.loadingclass{display:inline-block;cursor:default;background: url(\''

                    + this.options.themePath

                    + this.options.theme +'/images/loading.gif\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;}\n' +

                    '.loaderrorclass{display:inline-block;cursor:default;background: url(\''

                    + this.options.themePath

                    + this.options.theme +'/images/loaderror.png\') no-repeat center center transparent;border:1px solid #cccccc;margin-right:1px;height: 22px;width: 22px;' +

                    '}',

                    this.document);

            },

            /* 初始化word上传按钮 */

            'worduploadbtnready': function(type, container) {

                containerBtn = container;

                me.afterConfigReady(initUploadBtn);

            }

        },

        outputRule: function(root){

            utils.each(root.getNodesByTagName('img'),function(n){

                if (/\b(loaderrorclass)|(bloaderrorclass)\b/.test(n.getAttr('class'))) {

                    n.parentNode.removeChild(n);

                }

            });

        },

        commands: {

            'wordupload': {

                queryCommandState: function () {

                    return isLoaded ? 0:-1;

                }

            }

        }

    }

});

然后在同文件下的btnCmds变量中添加上自定义的按钮:

    //为工具栏添加按钮,以下都是统一的按钮触发命令,所以写在一起

    var btnCmds = ['undo', 'redo', 'formatmatch',

        'bold', 'italic', 'underline', 'fontborder', 'touppercase', 'tolowercase',

        'strikethrough', 'subscript', 'superscript', 'source', 'indent', 'outdent',

        'blockquote', 'pasteplain', 'pagebreak',

        'selectall', 'print','horizontal', 'removeformat', 'time', 'date', 'unlink',

        'insertparagraphbeforetable', 'insertrow', 'insertcol', 'mergeright', 'mergedown', 'deleterow',

        'deletecol', 'splittorows', 'splittocols', 'splittocells', 'mergecells', 'deletetable', 'drafts', 'wordupload'];

至此,配置完成,结果示意图:

效果展示:

 

 

 

视频教程:

WordPaster网络图片上传功能

动易SiteFactory 4.7整合,动易SiteFactory 5.6整合,动易SiteFactory 6.2整合,PbootCMS整合,PHPCMS v9整合,dedecms 5.7-ueditor整合,dedecms 5.7-ckeditor3x整合,帝国CMS-ueditor整合,帝国CMS-ckeditor4x整合,dokuwiki整合,Windows控件安装,macOS控件安装,linux-deb控件安装,linux-rpm控件安装,uos控件安装,linux-银河麒麟控件安装,

更多详细资料可以参考这篇文章:

详细思路及源码

示例下载:

wordpaster-vue3-cli-ueditor1.5,wordpaster-vue-ueditor1.5,wordpaster-asp.net-ueditor1.5x,wordpaster-php-ueditor1x,wordpaster-jsp-ueditor1x​


 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【成为架构师课程系列】怎样进行物理架构、运行架构、开发架构的设计?

我认识一些架构师,他们的生活都是失控的。因为架构天性范围宽广,涉及人、工作量都非常多。一些架构师把他们的时间整天整天的花在跟“项目干系人”开会上,然后夜以继日,再搭上周末去实际的架构工作。 -- Eric Brechner, 《代码之道》 多重软件架构视图之所以必不可少,是因…

如何在一个中文大模型上,加入招投标字段标注的数据,搭建一个招投标字段解析的Transformer模型?

ChatGPT方案1 在一个中文大模型上加入招投标字段标注的数据&#xff0c;并搭建招投标字段解析的Transformer模型可以通过以下步骤实现&#xff1a; 收集并标注招投标相关的数据。可以使用现有的数据集&#xff0c;也可以通过爬虫技术获取相关数据&#xff0c;然后进行人工标注。…

程序员兼职网站(自由职业)

1、程序员客栈 www.proginn.com 2、码市 codemart.com 3、开源众包 4、智城外包 5、实现网 6、猿急送 7、人人开发 8、开发邦 9、电鸭社区 10、快码 11、英选 12、外包大师 13、我爱方案网 14、自由职客 15、智筹 16、SXsorft 17、猪八戒

程序员如何向自由职业过渡

点击上方“程序人生”&#xff0c;选择“置顶公众号” 第一时间关注程序猿&#xff08;媛&#xff09;身边的故事 未来一定会是一个从事自由职业越来越多的时代。当我们还不能放手一搏到自由职业中去的时候&#xff0c;我们实际上可以为其做一些准备。当然不是所有人都适合自由…

4大国外自由职业者项目外包网站

4大国外自由职业者项目外包网站 http://www.asfreelancer.com/articles/50.html 2011-06-27 / 分类&#xff1a;推荐专题, 职业资源 / 没有评论 这里介绍四个在国外自由职业圈中很流行的项目外包网站&#xff0c;很多个人和团队都会在上面开始自己的商业服务&#xff0c;尤…

程序员适合做自由职业者吗?

企业基于自身的弹性用工需求&#xff0c;雇佣兼职或自由职业者来解决用人难题&#xff0c;这种灵活用工模式效率更高、成本更低&#xff0c;企业把灵活用工与固定全职结合起来使用&#xff0c;正在变成一种常态。有数据指出&#xff0c;全球灵活用工业务总收入高达3万亿&#x…

如何迅速成为一个能够养活自己的自由职业者?

自由职业者&#xff0c;意味着自己的时间可以自由的安排&#xff0c;不用被强迫996&#xff0c;但是也同时意味着收入的不稳定&#xff0c;特别是在成为自由者的初期。 飞援 平台上也有一些自由职业者活跃&#xff0c;综合他们的经历经验&#xff0c;分享几点建议给想成为自由…

一个自由职业者兼职程序员对未来的畅想以及对目前生活的改变

最近一直在思考一个问题&#xff0c;未来是什么样子的&#xff0c;或者说&#xff0c;当我七老八十的时候&#xff0c;我希望日子是什么样子的。 关于自由 这里所谓的自由&#xff0c;肯定不是如同丰县的铁链女子亦或是缅北的血奴一般完全失去人身自由&#xff0c;而是能够自由…

自由职业,如何做好?

自由职业现实很骨感。 网络高速发达的今天&#xff0c;一个人一台电脑一个技能就是一家公司&#xff1b;不用早起不用打卡&#xff0c;甚至不必参加无聊的会议&#xff0c;这应该是多数职场人羡慕的“自由”。 近两年&#xff0c;自由职业一度中层和应届生追求&#xff0c;数…

我又有一位程序员朋友成了自由职业者

很多对数据结构和算法感兴趣的小伙伴&#xff0c;对【程序员小灰】这个公众号并不陌生&#xff0c;小灰在三年前开始&#xff0c;创造了一只可爱的小仓鼠&#xff0c;并用它来讲解编程技术和算法&#xff0c;一讲就是三年。 我之前和小灰有过一些互推的合作&#xff0c;也小窗交…

自由职业一时爽,一直自由一直爽

自由对一个人的意义&#xff0c;恐怕只有真正失去过自由的人才能真正的理解。 01. 可以说&#xff0c;在我第一天上班的时刻起&#xff0c;我就为这一天在准备着。当时我并不知道我想做什么&#xff0c;只是觉得我终究要自己做点事情。 刚毕业的时候&#xff0c;其实没有太多的…

程序员如何成为一名自由职业者?

作为一名三十而立的开发者&#xff0c;你会组建家庭、买房还贷&#xff0c;上有老人赡养&#xff0c;下有孩子待哺&#xff0c;你需要越来越多的钱&#xff0c;才能凑凑合合地安排好你的生活。 然而在公司工作到一定阶段后&#xff0c;总会遇到一些问题&#xff1a; 即使你的技…

自由职业2年了!

大家好&#xff0c;我是彭涛&#xff01; 截至今天&#xff0c;我自由职业刚好2年整了。 想到2年前的自己&#xff0c;莫名感慨万分&#xff0c;从一开始的忐忑不安&#xff0c;到现在的坦然从容&#xff0c;从最一开始的些许迷茫&#xff0c;到现在的目标坚定&#xff0c;这里…

一位自由职业者的日常

文/一位喵先生 01 刷着知乎的时候&#xff0c;看到一个自由职业者&#xff08;SOHO族&#xff09;&#xff0c;如何保持高效率工作的问题。看到下面这么多大牛在说着自己的经历&#xff0c;忽然觉得&#xff0c;这条路上并非独自一个。 不知不觉&#xff0c;已经经历了三个…

做自由职业者是怎样的体验

7 月 5 日&#xff0c;我主动成了一位自由职业者&#xff0c;以写书、咨询、授课为生。一个月过去了&#xff0c;来聊聊我的体验。 1. 自由 首先要说自由职业者的自由。 女儿看牙&#xff0c;时间约到周一下午&#xff0c;没关系&#xff0c;直接去了&#xff0c;不用请假。…

这是你希望的自由职业么

每到周末文章的打开率和阅读量就变得惨淡的不行&#xff0c;索性就不分享干货&#xff0c;闲聊一下九月份私活结束后的自由职业经历。看看这是否是你向往的自由职业生活状态么&#xff1f; 九月份&#xff0c;忙完了手头的项目&#xff0c;也没心思找工作&#xff0c;一心想着借…

自由职业的这两年

两年前&#xff0c;也就是2016年2月份&#xff0c;铺天盖地的沮丧&#xff0c;以及朝九晚五的时间制压垮了我的积极性&#xff0c;于是我辞职了。但是&#xff0c;生活在海湾地区又不便宜&#xff0c;所以我开始自由职业。这是我人生历程的转折点——不但可以控制自己的日程安排…

不自由的自由职业

大家好&#xff0c;我是良许&#xff0c;前码农&#xff0c;现在自由职业者。 有关注我朋友圈的小伙伴都知道&#xff0c;就在上周&#xff0c;我刚刚结束了长达 35 天的「假期」。 此言一出&#xff0c;立刻掀起了评论区留言狂潮&#xff0c;大家纷纷问我&#xff0c;你特么不…

ChatGPT 可能对未来哪些行业领域造成影响?

ChatGPT 是一种基于人工智能技术的聊天机器人&#xff0c;它可以模拟人类的对话方式&#xff0c;具有自然语言处理、机器学习、深度学习等技术&#xff0c;可以对未来的许多行业领域产生影响&#xff0c;以下是一些可能的领域&#xff1a; 1. 客户服务&#xff1a;ChatGPT 可以…

越南版微信Zalo开发记录 (zmp)

公司新项目需要到越南聊天软件的小程序中上架&#xff0c;让我接触到了Zalo 小程序开发 zalo开发在国内几乎没有先例&#xff0c;毕竟在越南那边现在也算是新奇玩意&#xff0c;因此在开发过程中遇到问题在网上基本找不到答案&#xff01;&#xff01; 这篇文章简单记录下zmp…