WPS加载项报Network Error

问题描述

我在写一个WPS的加载项,写到发送请求拿到数据,但是就是一直Network Error。然后我用同样的请求在另外一个普通的Vue项目中试了一下发现完全没问题。

img

img

相关代码

WPS加载项的

这是TaskPane.vue


<template>
  <div>
    
    <el-select v-model="value" placeholder="请选择" size="small">
      <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.label"
          :value="item.value">
      el-option>
    el-select>
    <basic-search :keywords="keywords" v-on:search="search">basic-search>
    <DocItem>DocItem>
    <DocItem>DocItem>

  div>
template>

<script>
...

export default {
  name: 'TaskPane',
  components: {DocItem, BasicSearch},
  methods: {
    ...
    search(keywords) {
      // alert(keywords);
      this.$axios({
        method: 'get',
        url: 'http://localhost:8080/myzproduct/getAllByTitle',
        params: {
          title: "iphone",
        }
      }).then(res=>{
        alert("suceess");
        alert(res.data);
        console.log(res.data);
      },err=>{
        alert("错误是" + err);
        console.log(err);
      })
    },
    ...
}
script>

这是main.js


import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
// 完整引入,main.js写入以下代码
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import axios from 'axios'

Vue.use(ElementUI)
Vue.use(VueRouter)
Vue.prototype.$axios = axios
Vue.config.productionTip = false

const routerCfg= [
  {
    path: '/', 
    name: '默认页',
    component:()=>import('./components/Root.vue')
  },{
    path: '/taskpane', 
    name: '任务窗格',
    component:()=>import('./components/TaskPane.vue')
  }
]

new Vue({
  render: h => h(App),
  router: new VueRouter({routes:routerCfg}),
  created: function () {
    //
  }
}).$mount('#app')

这是package.json

{
    "name": "cyanfox_1",
    "addonType": "wps",
    "version": "1.0.0",
    "private": true,
    "scripts": {
        "serve": "vue-cli-service serve --port 3889",
        "build": "vue-cli-service build",
        "lint": "vue-cli-service lint"
    },
    "dependencies": {
        "axios": "^0.19.2",
        "core-js": "^3.6.4",
        "element-ui": "^2.15.13",
        "vue": "^2.6.11",
        "vue-router": "^3.1.3"
    },
    "devDependencies": {
        "@vue/cli-plugin-babel": "~4.2.0",
        "@vue/cli-service": "~4.2.0",
        "vue-template-compiler": "^2.6.11",
        "wps-jsapi": "latest"
    },
    "eslintConfig": {
        "root": true,
        "env": {
            "node": false
        },
        "extends": [
            "plugin:vue/essential",
            "eslint:recommended"
        ],
        "parserOptions": {
            "parser": "babel-eslint"
        },
        "rules": {},
        "globals": {
            "wps": "readonly"
        }
    },
    "browserslist": [
        "> 1%",
        "last 2 versions"
    ]
}

这是vue.config.js


// const { defineConfig } = require('@vue/cli-service')
module.exports = {
    "publicPath": "",
    "productionSourceMap": false,
    devServer: {
        proxy: "http://localhost:8081" // 这里存放的是真正的服务器
    }
}

普通Vue项目的

这是vue.config.js


```javascript
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  //关闭eslint
  lintOnSave:false,
  devServer: {
    proxy: "http://localhost:8081" // 这里存放的是真正的服务器
  }
})

这是发送请求的

```javascript
mounted() {
    this.$axios({
      method: 'get',
      url: 'http://localhost:8080/myzproduct/getAllByTitle',
      params: {
        title: "iphone",
      }
    }).then(res=>{
      alert("suceess");
      alert(res.data);
      console.log(res.data);
    },err=>{
      alert("错误是" + err);
      console.log(err);
    })
  },

操作环境

Win11,2023.4.6为止最新的WPS,后端是用SSM写的

要求

请尽可能详细描述,采纳标准为我成功在WPS加载项中拿到数据

你TaskPane.vue端口号是8080,后面的端口号是8081,不太懂vue,还是不行的话先用 jsonp 将就下,这里用wpsjs create HelloWps创建一个Excel加载项简单说明。
nodejs后端代码,前提安装koa包

const Koa = require('koa');
const app = new Koa();
const items = [{ id: 1, title: '“情人节讲屁话没用,让别人也单身”' }, { id: 2, title: '那年廿八,还是单身,站着如喽啰' }]

app.use(async (ctx, next) => {
  if (ctx.path == '/api/jsonp') {
    const { cb, id } = ctx.query;
    const title = items.find(item => item.id == id)['title']
    ctx.body = `${cb}(${JSON.stringify({title})})`;
    return;
  }
})
console.log('示例链接: http://localhost:8080/api/jsonp?id=1&cb=jsonpCallback')
app.listen(8080)

在前端taskpane.html页面插入一个script标签输入以下代码,或者直接写js文件引入也可以。

<script>
    function JSONP({
        url,
        params = {},
        callbackKey = 'cb',
        callback
    }) {
        // 定义本地的唯一callbackId,若是没有的话则初始化为1
        JSONP.callbackId = JSONP.callbackId || 1;
        let callbackId = JSONP.callbackId;
        // 把要执行的回调加入到JSON对象中,避免污染window
        JSONP.callbacks = JSONP.callbacks || [];
        JSONP.callbacks[callbackId] = callback;
        // 把这个名称加入到参数中: 'cb=JSONP.callbacks[1]'
        params[callbackKey] = `JSONP.callbacks[${callbackId}]`;
        // 得到'id=1&cb=JSONP.callbacks[1]'
        const paramString = Object.keys(params).map(key => {
            return `${key}=${encodeURIComponent(params[key])}`
        }).join('&')
        // 创建 script 标签
        const script = document.createElement('script');
        script.setAttribute('src', `${url}?${paramString}`);
        document.body.appendChild(script);
        // id自增,保证唯一
        JSONP.callbackId++;
    }
</script>

taskpane.js 的onbuttonclick函数下的switch语句添加两个 case

function onbuttonclick(idStr) {
    if (typeof (wps.Enum) != "object") { // 如果没有内置枚举值
        wps.Enum = WPS_Enum
    }
    switch (idStr) {
        case "addString": {
            let curSheet = wps.EtApplication().ActiveSheet;
            if (curSheet) {
                JSONP({
                    url: 'http://localhost:8080/api/jsonp',
                    params: {
                        id: 1
                    },
                    callbackKey: 'cb',
                    callback(res) {
                        curSheet.Cells.Item(1, 1).Formula = "请求数据成功 " + res.title
                    }
                })
            }
            break;
        }
        case "getDocName": {
            let curSheet = wps.EtApplication().ActiveSheet;
            if (curSheet) {
                JSONP({
                    url: 'http://localhost:8080/api/jsonp',
                    params: {
                        id: 2
                    },
                    callbackKey: 'cb',
                    callback(res) {
                        curSheet.Cells.Item(2, 1).Formula = "请求数据成功 " + res.title
                    }
                })
            }
            break
        }
    }
}

动图效果

img

jsonp跨域的问题参考这篇文章:前端跨域jsonp的细节,挡住面试官的连环提问

该回答引用ChatGPT
根据提供的信息,可以初步判断该问题可能是由于WPS加载项的请求被阻止导致的。为了确认问题,可以按照以下步骤进行操作:

1. 在WPS加载项中使用相同的网络请求库进行请求测试,确保其能够正常工作。如果在其他项目中可以正常工作,但在WPS加载项中失败,那么问题可能是由于WPS的安全限制导致的。

2. 确保WPS加载项是否正确配置了网络请求的协议、主机和端口。由于WPS可能会有一些安全限制,因此必须确保请求的主机和端口正确匹配。

3. 如果在尝试以上两个方法后仍无法解决问题,可以考虑在WPS加载项中使用WPS提供的API进行网络请求。WPS提供了一些用于加载项开发的API,可以轻松地进行网络请求并确保安全访问。

顺便提醒一下,在暴露在外网上的请求中,应该避免把自己的 localhost:8080 作为主机,正式发布时使用真实的IP和端口,否则根据WPS的安全限制机制会拦截请求。

该回答引用于ChatGPT:
根据您提供的代码及描述,我看不出具体的问题。但通常 Network Error 是由于无法访问服务器引起的,可能是网络连接不稳定、代理设置不正确等原因导致的。

在 WPS 的加载项中访问数据,需要注意以下几点:

  1. 跨域问题:WPS 加载项运行的环境与普通的 Web 应用程序有所不同。默认情况下,WPS 加载项的 JavaScript 代码不能通过 AJAX 访问跨域资源。要解决这个问题,需要将跨域策略添加到服务器端,或者使用 JSONP 或 CORS 等技术。

  2. 网络连接问题:如果网络连接不稳定或存在其他问题,可能会导致请求失败或响应延迟。建议使用 Chrome 浏览器进行调试,并查看控制台中的网络请求信息和错误提示,以便找出问题所在。

  3. 代理设置问题:如果您的网络使用了代理服务器,可能会影响到 WPS 加载项的网络访问。建议检查您的代理设置是否正确,并尝试通过 http-proxy-middlewarehttp-proxy-agent 等库来配置代理。

在您的代码中,您将 API 地址设置为 http://localhost:8080/myzproduct/getAllByTitle,请确保本地服务器已经启动并监听了 8080 端口。如果服务器没有正确启动或者监听的端口不正确,也会导致 Network Error。

在排查上述可能性之后,如果问题仍然无法解决,请提供更多详细的报错信息和代码。这样我们才可以更好地帮助您。

以下内容部分参考ChatGPT模型:
这个问题可能是由于WPS加载项的跨域问题导致的。在普通的Vue项目中,可以通过在vue.config.js中配置proxy来解决跨域问题,但是在WPS加载项中,由于是在WPS的环境下运行,可能需要使用WPS提供的API来解决跨域问题。

解决思路如下:

  1. 确认是否是跨域问题:在WPS加载项中发送请求时,需要注意是否会有跨域的问题。可以通过浏览器的开发者工具查看请求是否被阻止,或者在WPS加载项中使用WPS提供的API来查看是否有错误信息。

  2. 使用WPS提供的API来解决跨域问题:WPS提供了一些API来帮助开发者解决跨域问题,比如wps.proxy和wps.httpRequest。可以尝试使用这些API来发送请求,具体使用方法可以参考WPS开发文档。

  3. 在后端中添加跨域配置:如果是后端的问题导致跨域,可以在后端中添加跨域配置来解决问题。具体方法可以根据后端框架和语言不同而有所不同,可以参考相应的文档。

  4. 在WPS加载项中使用JSONP:如果以上方法都无法解决问题,可以尝试在WPS加载项中使用JSONP来发送请求。JSONP是一种跨域解决方案,可以通过在请求中添加callback参数来实现跨域请求。具体使用方法可以参考相关文档。

例子:

以下是一个使用wps.httpRequest发送请求的例子,用于获取WPS文档的标题:

wps.httpRequest({
  url: 'http://localhost:8080/myzproduct/getTitle',
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
  },
  success: function (res) {
    console.log(res.data.title);
  },
  error: function (err) {
    console.log(err);
  }
});

其中,url为请求的地址,method为请求的方法,headers为请求头,success为请求成功的回调函数,error为请求失败的回调函数。在success回调函数中可以获取到返回的数据,在error回调函数中可以获取错误信息。
如果我的建议对您有帮助、请点击采纳、祝您生活愉快