|
@@ -1,4 +1,4 @@
|
|
|
-import { ref, nextTick } from 'vue'
|
|
|
|
|
|
|
+import { ref, nextTick } from 'vue'
|
|
|
import { storeToRefs } from 'pinia'
|
|
import { storeToRefs } from 'pinia'
|
|
|
import { parse, type Shape, type Element, type ChartItem, type BaseElement } from 'pptxtojson'
|
|
import { parse, type Shape, type Element, type ChartItem, type BaseElement } from 'pptxtojson'
|
|
|
import { nanoid } from 'nanoid'
|
|
import { nanoid } from 'nanoid'
|
|
@@ -1954,19 +1954,22 @@ export default () => {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 纯 JS 跨域抓 HTML(最后兜底方案):通过公共 CORS 代理 allorigins 获取目标页面源码
|
|
|
|
|
|
|
+ // 纯 JS 跨域抓 HTML(最后兜底方案):通过公共 CORS 代理获取目标页面源码
|
|
|
// 用于 type=73 在 getHTML/getFile/getFile2 全部失败后的兜底
|
|
// 用于 type=73 在 getHTML/getFile/getFile2 全部失败后的兜底
|
|
|
- const getHtmlPureJS = (url: string): Promise<string> => {
|
|
|
|
|
|
|
+ // 公共代理可用性不稳定(尤其国内网络),依次尝试多个,一个失败换下一个
|
|
|
|
|
+ const CORS_PROXIES: Array<(url: string) => string> = [
|
|
|
|
|
+ url => 'https://api.allorigins.win/raw?url=' + encodeURIComponent(url),
|
|
|
|
|
+ url => 'https://corsproxy.io/?url=' + encodeURIComponent(url),
|
|
|
|
|
+ url => 'https://api.codetabs.com/v1/proxy?quest=' + encodeURIComponent(url),
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ const fetchViaProxy = (proxyFn: (url: string) => string, url: string): Promise<string> => {
|
|
|
return new Promise((resolve, reject) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
const xhr = new XMLHttpRequest()
|
|
const xhr = new XMLHttpRequest()
|
|
|
|
|
+ xhr.open('GET', proxyFn(url), true)
|
|
|
|
|
+ xhr.timeout = 12000 // iPad WebView 可能挂起不回调,必须加超时
|
|
|
|
|
|
|
|
- // 关键:必须用公共 CORS 代理,否则低版本 WebView 跨域直接拦截
|
|
|
|
|
- const proxyUrl = 'https://api.allorigins.win/raw?url=' + encodeURIComponent(url)
|
|
|
|
|
-
|
|
|
|
|
- xhr.open('GET', proxyUrl, true)
|
|
|
|
|
- xhr.timeout = 15000 // iPad WebView 可能挂起不回调,必须加超时
|
|
|
|
|
-
|
|
|
|
|
- xhr.onreadystatechange = function () {
|
|
|
|
|
|
|
+ xhr.onreadystatechange = function() {
|
|
|
if (xhr.readyState === 4) {
|
|
if (xhr.readyState === 4) {
|
|
|
if (xhr.status === 200 && xhr.responseText) {
|
|
if (xhr.status === 200 && xhr.responseText) {
|
|
|
resolve(xhr.responseText)
|
|
resolve(xhr.responseText)
|
|
@@ -1977,19 +1980,30 @@ export default () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- xhr.ontimeout = function () {
|
|
|
|
|
|
|
+ xhr.ontimeout = function() {
|
|
|
reject(new Error('Request Timeout'))
|
|
reject(new Error('Request Timeout'))
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- xhr.onerror = function () {
|
|
|
|
|
|
|
+ xhr.onerror = function() {
|
|
|
reject(new Error('Network Error'))
|
|
reject(new Error('Network Error'))
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
xhr.send()
|
|
xhr.send()
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const getHtmlPureJS = async (url: string): Promise<string> => {
|
|
|
|
|
+ let lastError: unknown = null
|
|
|
|
|
+ for (const proxyFn of CORS_PROXIES) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ return await fetchViaProxy(proxyFn, url)
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ console.warn('CORS 代理失败,尝试下一个:', proxyFn(url).slice(0, 50), err)
|
|
|
|
|
+ lastError = err
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ throw lastError || new Error('All proxies failed')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return {
|
|
return {
|
|
|
importSpecificFile,
|
|
importSpecificFile,
|
|
|
importJSON,
|
|
importJSON,
|