1 parent
9e7d0aeee6
commit
e64a8e9bc5
26 files changed
+1111
-77
No files matched your search
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"python.testing.pytestArgs": [
|
||||
"tests"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"python.testing.autoTestDiscoverOnSaveEnabled": true,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
# WPS 表格自动化(插件版)
|
||||
@@ -1,12 +0,0 @@
|
||||
from ET import ET
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
et1 = ET()
|
||||
sheets_name = et1.get_sheets()
|
||||
print(f"et1: {sheets_name}")
|
||||
|
||||
et2 = ET()
|
||||
et2.workbook_name = "工作簿2"
|
||||
sheets_name = et2.get_sheets()
|
||||
print(f"et2:{sheets_name}")
|
||||
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
|
||||
|
||||
from .client import Client
|
||||
|
||||
|
||||
class ET(Client):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.workbook_name = "" # 用于判断当前打开的表格
|
||||
# self.check_addon_install() # 调试模式暂时不判断
|
||||
self.inject_flag = self._inject_js_code()
|
||||
|
||||
def open(self, file_path):
|
||||
"""open et"""
|
||||
pass
|
||||
|
||||
def get_sheets(self) -> list:
|
||||
"""get all sheets"""
|
||||
func = "getSheets"
|
||||
sheets_name = self._wrap_invoke_func(func)
|
||||
|
||||
return sheets_name
|
||||
|
||||
def _wrap_invoke_func(self, func, args={}):
|
||||
"""将工作簿的名称自动带进去"""
|
||||
if self.workbook_name:
|
||||
args["workbook_name"] = self.workbook_name
|
||||
res = self.invoke_func(func, args)
|
||||
if res.get("code") != 0:
|
||||
raise Exception(f"调用函数 {func} 失败, 错误信息: {res.get('msg')}")
|
||||
return res.get("data")
|
||||
|
||||
def _inject_js_code(self) -> bool:
|
||||
"""注入js脚本"""
|
||||
current_path = os.path.abspath(__file__)
|
||||
js_code_path = os.path.join(os.path.dirname(current_path), "et.js")
|
||||
if not os.path.exists(js_code_path):
|
||||
raise Exception(f"js code not found: {js_code_path}")
|
||||
# 读取js代码
|
||||
with open(js_code_path, encoding="utf8") as f:
|
||||
code = f.read()
|
||||
func = "inject"
|
||||
args = {"code": code}
|
||||
res = self.invoke_func(func, args)
|
||||
return res.get("code") == 0
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,22 +1,124 @@
|
||||
import base64
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
import json
|
||||
import http.client
|
||||
import webbrowser
|
||||
import os
|
||||
import platform
|
||||
import xml.dom.minidom as minidom
|
||||
import sys
|
||||
import shutil
|
||||
import zipfile
|
||||
import time
|
||||
import shutil
|
||||
import base64
|
||||
import zipfile
|
||||
import platform
|
||||
import webbrowser
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__file__)
|
||||
|
||||
import http.client
|
||||
import xml.dom.minidom as minidom
|
||||
|
||||
from xml.etree import ElementTree
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(self):
|
||||
self.addon_name = "XbotWps"
|
||||
self.addon_name = "xbot-et"
|
||||
self.addon_type = "et"
|
||||
self.addon_version = "1.0.0"
|
||||
self.url = "http://127.0.0.1:3889/"
|
||||
self.start_http_server()
|
||||
|
||||
def start_http_server(self) -> bool:
|
||||
for _ in range(10):
|
||||
if self._get_version():
|
||||
print("Wps server started")
|
||||
return True
|
||||
self._start_http_server()
|
||||
time.sleep(1)
|
||||
raise ("Wps server not started")
|
||||
|
||||
def get_addon_list(self) -> list:
|
||||
"""获取插件列表"""
|
||||
path = "/publishlist"
|
||||
conn = http.client.HTTPConnection("127.0.0.1", 58890)
|
||||
conn.request("GET", path, body="{}", headers={})
|
||||
response = conn.getresponse()
|
||||
data = response.read()
|
||||
conn.close()
|
||||
json_data = json.loads(data.decode("utf-8"))
|
||||
return json_data
|
||||
|
||||
def verify_addon_status(self) -> bool:
|
||||
"""验证插件状态"""
|
||||
url = self.url + "ribbon.xml"
|
||||
data = {"method": "get", "url": url, "data": ""}
|
||||
payload = base64.b64encode(json.dumps(data).encode("utf-8")).decode()
|
||||
print(f"payload: {payload}")
|
||||
conn = http.client.HTTPConnection("127.0.0.1", 58890)
|
||||
conn.request("POST", "/redirect/runParams", payload, {})
|
||||
response = conn.getresponse()
|
||||
data = response.read()
|
||||
conn.close()
|
||||
try:
|
||||
root = ElementTree.fromstring(data)
|
||||
# 检查根标签名是否包含 customUI(包含命名空间)
|
||||
return root.tag.endswith("customUI")
|
||||
except ElementTree.ParseError:
|
||||
return False
|
||||
|
||||
def enable_addon(self) -> bool:
|
||||
"""开启插件"""
|
||||
data = {
|
||||
"cmd": "enable",
|
||||
"name": self.addon_name,
|
||||
"url": self.url,
|
||||
"addonType": "et",
|
||||
"online": "true",
|
||||
"time": int(time.time()),
|
||||
}
|
||||
path = "/deployaddons/runParams"
|
||||
payload = base64.b64encode(json.dumps(data).encode("utf-8")).decode()
|
||||
conn = http.client.HTTPConnection("127.0.0.1", 58890)
|
||||
conn.request("POST", path, payload, {})
|
||||
response = conn.getresponse()
|
||||
data = response.read()
|
||||
conn.close()
|
||||
return data.decode() == "OK"
|
||||
|
||||
def disable_addon(self) -> bool:
|
||||
"""禁用插件"""
|
||||
data = {
|
||||
"cmd": "disable",
|
||||
"name": self.addon_name,
|
||||
"url": self.url,
|
||||
"addonType": "et",
|
||||
"online": "true",
|
||||
"time": int(time.time()),
|
||||
}
|
||||
path = "/deployaddons/runParams"
|
||||
payload = base64.b64encode(json.dumps(data).encode("utf-8")).decode()
|
||||
conn = http.client.HTTPConnection("127.0.0.1", 58890)
|
||||
conn.request("POST", path, payload, {})
|
||||
|
||||
response = conn.getresponse()
|
||||
data = response.read()
|
||||
conn.close()
|
||||
return data.decode() == "OK"
|
||||
|
||||
def is_client_running(self) -> bool:
|
||||
"""检查客户端是否运行"""
|
||||
# --data-raw '{"app":"et"}'
|
||||
path = "/isRunning"
|
||||
data = {
|
||||
"app": self.addon_type,
|
||||
}
|
||||
payload = json.dumps(data)
|
||||
|
||||
conn = http.client.HTTPConnection("127.0.0.1", 58890)
|
||||
conn.request("POST", path, payload, {})
|
||||
|
||||
response = conn.getresponse()
|
||||
data = response.read()
|
||||
conn.close()
|
||||
return data.decode() == "Client is running."
|
||||
|
||||
def invoke_func(self, func, args={}):
|
||||
|
||||
@@ -35,7 +137,7 @@ class Client:
|
||||
xhr.send(JSON.stringify({{id: '{req_uui}', response: res}}));void(0"
|
||||
|
||||
data = {
|
||||
"name": "xbot-et",
|
||||
"name": self.addon_name,
|
||||
"function": "var res = InvokeFromXbot",
|
||||
"info": info,
|
||||
"showToFront": True,
|
||||
@@ -95,26 +197,6 @@ class Client:
|
||||
|
||||
print("Installation completed successfully.")
|
||||
|
||||
def check_addon_install(self):
|
||||
"""通过文件夹是否存在判断插件是否安装"""
|
||||
install_dir = self._get_install_directory()
|
||||
addon_name_with_version = f"{self.addon_name}_{self.addon_version}"
|
||||
file_path = os.path.join(install_dir, addon_name_with_version)
|
||||
|
||||
if os.path.exists(file_path):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_http_status(self):
|
||||
for _ in range(10):
|
||||
if self._get_version():
|
||||
print("Wps server started")
|
||||
return
|
||||
self._start_http_server()
|
||||
time.sleep(1)
|
||||
raise ("Wps server not started")
|
||||
|
||||
def _start_http_server(self):
|
||||
"""start debug"""
|
||||
webbrowser.open("ksowpscloudsvr://start=RelayHttpServer")
|
||||
@@ -289,37 +371,3 @@ class Client:
|
||||
except Exception as e:
|
||||
print(f"Error extracting archive: {e}")
|
||||
return False
|
||||
|
||||
|
||||
class ET(Client):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.workbook_name = "" # 用于判断当前打开的表格
|
||||
self.check_http_status()
|
||||
# self.check_addon_install() # 调试模式暂时不判断
|
||||
self._inject_js_code()
|
||||
|
||||
def open(self, file_path):
|
||||
"""open et"""
|
||||
pass
|
||||
|
||||
def get_sheets(self) -> list:
|
||||
"""get all sheets"""
|
||||
func = "getSheets"
|
||||
sheets_name = self._wrap_invoke_func(func)
|
||||
return sheets_name
|
||||
|
||||
def _wrap_invoke_func(self, func, args={}):
|
||||
"""将工作簿的名称自动带进去"""
|
||||
if self.workbook_name:
|
||||
args["workbook_name"] = self.workbook_name
|
||||
return self.invoke_func(func, args)
|
||||
|
||||
def _inject_js_code(self):
|
||||
path = r"C:\Users\32075\OneDrive\文档\Code\RPA_Script\wps-js-extension\XbotWps\py-et\et.js"
|
||||
with open(path, encoding="utf8") as f:
|
||||
code = f.read()
|
||||
func = "inject"
|
||||
args = {"code": code}
|
||||
res = self.invoke_func(func, args)
|
||||
return res
|
||||
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,70 @@
|
||||
# test src/et.py client
|
||||
|
||||
from src.ET import Client
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def test_create_client():
|
||||
"""创建测试用的client"""
|
||||
client = Client()
|
||||
yield client
|
||||
|
||||
|
||||
def test_client_get_addon_list(test_create_client):
|
||||
"""测试获取插件列表"""
|
||||
client = test_create_client
|
||||
print("Getting addon list...")
|
||||
addon_list = client.get_addon_list()
|
||||
print(f"Retrieved {len(addon_list)} addons")
|
||||
assert isinstance(addon_list, list)
|
||||
assert len(addon_list) > 0
|
||||
assert all(isinstance(addon, dict) for addon in addon_list)
|
||||
# 遍历所有插件, 并输出
|
||||
for i, addon in enumerate(addon_list):
|
||||
print(f"Addon {i}: {addon}")
|
||||
print("First addon in list:", addon_list[0] if addon_list else "None")
|
||||
print("Addon list test passed!")
|
||||
|
||||
|
||||
def test_client_verify_addon_status(test_create_client):
|
||||
"""测试插件状态"""
|
||||
client = test_create_client
|
||||
print("Verifying addon status...")
|
||||
status = client.verify_addon_status()
|
||||
print(f"Addon status: {status}")
|
||||
assert status is True, "Addon status is not verified successfully"
|
||||
print("Addon status test passed!")
|
||||
|
||||
|
||||
def test_client_enable_addon(test_create_client):
|
||||
"""测试启用插件"""
|
||||
client = test_create_client
|
||||
print("Enabling addon...")
|
||||
status = client.enable_addon()
|
||||
print(f"Addon enabled: {status}")
|
||||
assert status is True, "Failed to enable addon"
|
||||
print("Enable addon test passed!")
|
||||
|
||||
|
||||
def test_client_disable_addon(test_create_client):
|
||||
"""测试禁用插件"""
|
||||
client = test_create_client
|
||||
print("Disabling addon...")
|
||||
status = client.disable_addon()
|
||||
print(f"Addon disabled: {status}")
|
||||
assert status is True, "Failed to disable addon"
|
||||
print("Disable addon test passed!")
|
||||
|
||||
def test_client_is_client_running(test_create_client):
|
||||
"""测试客户端是否运行"""
|
||||
client = test_create_client
|
||||
print("Checking if client is running...")
|
||||
is_running = client.is_client_running()
|
||||
print(f"Client is running: {is_running}")
|
||||
assert isinstance(is_running, bool), "Client running status is not a boolean"
|
||||
print("Client running status test passed!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Add direct test execution for better debugging
|
||||
pass
|
||||
@@ -0,0 +1,39 @@
|
||||
import pytest
|
||||
|
||||
from src.ET import ET
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def test_create_client():
|
||||
"""创建测试用的client"""
|
||||
client = ET()
|
||||
yield client
|
||||
|
||||
|
||||
def test_et_check_inject():
|
||||
"""测试注入"""
|
||||
et = ET()
|
||||
print("Injecting...")
|
||||
assert et.inject_flag is True, "Injection failed"
|
||||
print("Inject test passed!")
|
||||
|
||||
|
||||
def test_et_get_sheets():
|
||||
"""测试获取工作表"""
|
||||
et = ET()
|
||||
print("Getting sheets...")
|
||||
sheets_name = et.get_sheets()
|
||||
print(f"Retrieved {len(sheets_name)} sheets")
|
||||
print(f"Sheets_name: {sheets_name}")
|
||||
assert isinstance(sheets_name, list)
|
||||
assert len(sheets_name) > 0
|
||||
assert all(isinstance(sheet, str) for sheet in sheets_name)
|
||||
# 遍历所有工作表, 并输出
|
||||
for i, sheet in enumerate(sheets_name):
|
||||
print(f"Sheet {i}: {sheet}")
|
||||
print("First sheet in list:", sheets_name[0] if sheets_name else "None")
|
||||
print("Get sheets test passed!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
# WPS 表格自动化
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1743477113372" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1505" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 1024C229.376 1024 0 794.624 0 512S229.376 0 512 0s512 229.376 512 512-229.376 512-512 512z m0-949.248C271.36 74.752 75.776 271.36 75.776 512S271.36 949.248 512 949.248 949.248 752.64 949.248 512 752.64 74.752 512 74.752z m0 753.664a45.44 45.44 0 0 1-45.056-45.056V444.416c0-25.6 20.48-45.056 45.056-45.056s45.056 19.456 45.056 45.056V783.36A45.44 45.44 0 0 1 512 828.416z m0-474.112c-24.576 0-45.056-20.48-45.056-46.08V240.64c0-24.576 20.48-45.056 45.056-45.056s45.056 20.48 45.056 45.056v67.584c0 25.6-20.48 46.08-45.056 46.08z" p-id="1506"></path></svg>
|
||||
|
After Width: | Height: | Size: 893 B |
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="21px" height="20px" viewBox="0 0 21 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>从模版新建</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Artboard" transform="translate(-31.000000, -26.000000)">
|
||||
<g id="从模版新建" transform="translate(29.000000, 24.000000)">
|
||||
<g id="Group" stroke-width="1">
|
||||
<g id="新增节" transform="translate(2.000000, 2.000000)">
|
||||
<path d="M19.9587402,10 L18.9587402,10 L18.9587402,2 C18.9587402,1.44771525 18.511025,1 17.9587402,1 L6.0300293,1 C5.47774455,1 5.0300293,1.44771525 5.0300293,2 L5.0300293,18 C5.0300293,18.5522847 5.47774455,19 6.0300293,19 L9.95874023,19 L9.95874023,20 L6.0300293,20 C4.9254598,20 4.0300293,19.1045695 4.0300293,18 L4.0300293,2 C4.0300293,0.8954305 4.9254598,2.02906125e-16 6.0300293,0 L17.9587402,0 C19.0633097,-2.02906125e-16 19.9587402,0.8954305 19.9587402,2 L19.9587402,10 Z" id="Combined-Shape" fill="#404040" fill-rule="nonzero"></path>
|
||||
<path d="M6,1 L4,1 C3.44771525,1 3,1.44771525 3,2 L3,18 C3,18.5522847 3.44771525,19 4,19 L6,19 L6,20 L4,20 C2.8954305,20 2,19.1045695 2,18 L2,2 C2,0.8954305 2.8954305,2.02906125e-16 4,0 L6,0 L6,1 Z" id="Combined-Shape-Copy-2" fill="#404040" fill-rule="nonzero"></path>
|
||||
<path d="M4,1 L2,1 C1.44771525,1 1,1.44771525 1,2 L1,18 C1,18.5522847 1.44771525,19 2,19 L4,19 L4,20 L2,20 C0.8954305,20 1.03797111e-16,19.1045695 0,18 L0,2 C-1.10284431e-16,0.8954305 0.8954305,2.02906125e-16 2,0 L4,0 L4,1 Z" id="Combined-Shape-Copy-3" fill="#404040" fill-rule="nonzero"></path>
|
||||
<path d="M17,15 L20.5,15 C20.7761424,15 21,15.2238576 21,15.5 C21,15.7761424 20.7761424,16 20.5,16 L17,16 L17,19.5 C17,19.7761424 16.7761424,20 16.5,20 C16.2238576,20 16,19.7761424 16,19.5 L16,16 L12.5,16 C12.2238576,16 12,15.7761424 12,15.5 C12,15.2238576 12.2238576,15 12.5,15 L16,15 L16,11.5 C16,11.2238576 16.2238576,11 16.5,11 C16.7761424,11 17,11.2238576 17,11.5 L17,15 Z" id="Combined-Shape" fill="#5789D9"></path>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="Rectangle-15" fill="#404040" x="9" y="6" width="10" height="1"></rect>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="./main.js"></script>
|
||||
</html>
|
||||
<!--这个文件是wps加载项的入口文件,wps在启动时加载这个文件-->
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
//这个函数在整个wps加载项中是第一个执行的
|
||||
function OnAddinLoad(ribbonUI) {
|
||||
if (typeof (window.Application.ribbonUI) != "object") {
|
||||
window.Application.ribbonUI = ribbonUI
|
||||
}
|
||||
|
||||
if (typeof (window.Application.Enum) != "object") { // 如果没有内置枚举值
|
||||
window.Application.Enum = WPS_Enum
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
function OnAction(control) {
|
||||
const eleId = control.Id
|
||||
switch (eleId) {
|
||||
case "btnShowAbout":
|
||||
{
|
||||
alert("关于我们\n\n作者:Jianxin\n\n版本:1.0.0\n\n说明:自动化插件\n\n感谢使用!")
|
||||
}
|
||||
break;
|
||||
case "contactAuthor":
|
||||
{
|
||||
wps.ShowDialog(GetUrlPath() + "/ui/author.html", "联系作者", 400 * window.devicePixelRatio, 400 * window.devicePixelRatio, false)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
function GetImage(control) {
|
||||
const eleId = control.Id
|
||||
switch (eleId) {
|
||||
case "btnShowAbout":
|
||||
return "images/about.svg"
|
||||
default:
|
||||
;
|
||||
}
|
||||
return "images/newFromTemp.svg"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
//在后续的wps版本中,wps的所有枚举值都会通过wps.Enum对象来自动支持,现阶段先人工定义
|
||||
var WPS_Enum = {
|
||||
msoCTPDockPositionLeft: 0,
|
||||
msoCTPDockPositionRight: 2
|
||||
}
|
||||
|
||||
function GetUrlPath() {
|
||||
let e = document.location.toString()
|
||||
return -1 != (e = decodeURI(e)).indexOf("/") && (e = e.substring(0, e.lastIndexOf("/"))), e
|
||||
}
|
||||
/**
|
||||
* 通过wps提供的接口执行一段脚本
|
||||
* @param {*} param 需要执行的脚本
|
||||
*/
|
||||
function shellExecuteByOAAssist(param) {
|
||||
if (wps != null) {
|
||||
wps.OAAssist.ShellExecute(param)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
let wpsInstance = null;
|
||||
|
||||
|
||||
function InvokeFromXbot(param) {
|
||||
// 1. 解析参数, 如果不是字符串, 则转换为字符串, 并用json解析, 解析失败直接retrun
|
||||
if (typeof param !== 'string') {
|
||||
param = JSON.stringify(param);
|
||||
}
|
||||
try {
|
||||
param = JSON.parse(param);
|
||||
} catch (e) {
|
||||
return { msg: '参数解析失败', code: -1 };
|
||||
}
|
||||
|
||||
// 2. 判断是否有method字段, 如果没有直接return
|
||||
if (!param.method) {
|
||||
return { msg: '参数错误', code: -2 };
|
||||
}
|
||||
|
||||
// 3. 获取 method 字段对应的方法和 args 参数
|
||||
let method = param.method;
|
||||
|
||||
let args = null;
|
||||
|
||||
try {
|
||||
args = JSON.parse(param.args);
|
||||
} catch (e) {
|
||||
args = {};
|
||||
}
|
||||
|
||||
|
||||
console.log("method:", method);
|
||||
console.log("args:", args);
|
||||
// confsole.log("args", typeof args);
|
||||
|
||||
// 4. 判断 method 是否为 inject, 如果是则执行注入方法, 其他走默认方法执行调用函数
|
||||
if (method === 'inject') {
|
||||
let code = args.code;
|
||||
console.log("start eval code");
|
||||
console.log(code);
|
||||
console.log(new Function(code)());
|
||||
wpsInstance = new Function(code)(); // 执行并获取返回值
|
||||
console.log("success eval code");
|
||||
return { message: "inject ok", code: 0 }
|
||||
}
|
||||
|
||||
// 5. 判断是否有 wpsInstance, 如果没有直接return
|
||||
if (!wpsInstance) {
|
||||
return { msg: '未注入', code: -3 };
|
||||
}
|
||||
|
||||
// 6. 判断 wpsInstance 是否有 method 方法, 如果没有直接return
|
||||
if (!wpsInstance[method]) {
|
||||
return { msg: '方法不存在', code: -4 };
|
||||
}
|
||||
|
||||
// 7. 执行 wpsInstance 的 method 方法, 并返回结果
|
||||
try {
|
||||
const result = wpsInstance[method](args ?? null);
|
||||
return { msg: '执行成功', code: 0, data: result };
|
||||
} catch (e) {
|
||||
return { msg: '执行失败', code: -5 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
//这个文件由index.html包含
|
||||
document.write("<script language='javascript' src='js/util.js'></script>");
|
||||
document.write("<script language='javascript' src='js/ribbon.js'></script>");
|
||||
document.write("<script language='javascript' src='js/xbot.js'></script>");
|
||||
@@ -0,0 +1,15 @@
|
||||
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" onLoad="OnAddinLoad">
|
||||
<ribbon startFromScratch="false">
|
||||
<tabs>
|
||||
<tab id="wpsAddinTab" label="影刀插件">
|
||||
<group id="btnDemoGroup" label="group1">
|
||||
<button id="btnShowAbout" label="关于插件" onAction="OnAction" getImage="GetImage"
|
||||
visible="true" size="large" />
|
||||
<button id="contactAuthor" label="联系作者" onAction="OnAction"
|
||||
getEnabled="OnGetEnabled" getImage="GetImage" visible="true" size="large" />
|
||||
</group>
|
||||
|
||||
</tab>
|
||||
</tabs>
|
||||
</ribbon>
|
||||
</customUI>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<img class="authImg" src="https://won-link.oss-cn-hangzhou.aliyuncs.com/halo/AuthorWx.png">
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.authImg {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,628 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WPS加载项配置</title>
|
||||
<link rel="icon" type="image/png" sizes="32x32"
|
||||
href="data:image/png;base64,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 truncated
|
||||
<style>
|
||||
body {
|
||||
margin: 30px;
|
||||
}
|
||||
|
||||
.addonList {
|
||||
max-width: 80%;
|
||||
flex-direction: column;
|
||||
padding: 18px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.addonItem {
|
||||
font-size: 16px;
|
||||
line-height: 36px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.addonItem:hover {
|
||||
border-radius: 2px;
|
||||
border: 1px dashed silver;
|
||||
}
|
||||
|
||||
.addonItemName1 {
|
||||
display: inline-block;
|
||||
width: 15%;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.addonItemName2 {
|
||||
display: inline-block;
|
||||
width: 10%;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.addonItemName3 {
|
||||
display: inline-block;
|
||||
width: 10%;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.addonItemName4 {
|
||||
display: inline-block;
|
||||
width: 35%;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.addonItemName5 {
|
||||
display: inline-block;
|
||||
width: 15%;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.addonItemName6 {
|
||||
display: inline-block;
|
||||
width: 10%;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.addonItemButton {
|
||||
padding: 4px 8px;
|
||||
background-color: #417ff9;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.addonItemButton:hover {
|
||||
background-color: #5696ff;
|
||||
}
|
||||
|
||||
.addonItemTitle {
|
||||
padding: 0px;
|
||||
border-bottom: 1px solid silver;
|
||||
}
|
||||
|
||||
.addonItemTitle:hover {
|
||||
border-radius: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.ClearAll {
|
||||
max-width: 80%;
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
border: 1px dashed silver;
|
||||
padding: 0px 18px;
|
||||
}
|
||||
|
||||
.ClearAll:hover {
|
||||
border-radius: 2px;
|
||||
background-color: silver;
|
||||
}
|
||||
|
||||
.divTitle {
|
||||
font-size: 30px;
|
||||
font-weight: bolder;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function getHttpObj() {
|
||||
var httpobj = null;
|
||||
if (IEVersion() < 10) {
|
||||
try {
|
||||
httpobj = new XDomainRequest();
|
||||
} catch (e1) {
|
||||
httpobj = new createXHR();
|
||||
}
|
||||
} else {
|
||||
httpobj = new createXHR();
|
||||
}
|
||||
return httpobj;
|
||||
}
|
||||
//兼容IE低版本的创建xmlhttprequest对象的方法
|
||||
function createXHR() {
|
||||
if (typeof XMLHttpRequest != 'undefined') { //兼容高版本浏览器
|
||||
return new XMLHttpRequest();
|
||||
} else if (typeof ActiveXObject != 'undefined') { //IE6 采用 ActiveXObject, 兼容IE6
|
||||
var versions = [ //由于MSXML库有3个版本,因此都要考虑
|
||||
'MSXML2.XMLHttp.6.0',
|
||||
'MSXML2.XMLHttp.3.0',
|
||||
'MSXML2.XMLHttp'
|
||||
];
|
||||
|
||||
for (var i = 0; i < versions.length; i++) {
|
||||
try {
|
||||
return new ActiveXObject(versions[i]);
|
||||
} catch (e) {
|
||||
//跳过
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new Error('您的浏览器不支持XHR对象');
|
||||
}
|
||||
}
|
||||
|
||||
var fromCharCode = String.fromCharCode;
|
||||
// encoder stuff
|
||||
var cb_utob = function (c) {
|
||||
if (c.length < 2) {
|
||||
var cc = c.charCodeAt(0);
|
||||
return cc < 0x80 ? c :
|
||||
cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6)) +
|
||||
fromCharCode(0x80 | (cc & 0x3f))) :
|
||||
(fromCharCode(0xe0 | ((cc >>> 12) & 0x0f)) +
|
||||
fromCharCode(0x80 | ((cc >>> 6) & 0x3f)) +
|
||||
fromCharCode(0x80 | (cc & 0x3f)));
|
||||
} else {
|
||||
var cc = 0x10000 +
|
||||
(c.charCodeAt(0) - 0xD800) * 0x400 +
|
||||
(c.charCodeAt(1) - 0xDC00);
|
||||
return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07)) +
|
||||
fromCharCode(0x80 | ((cc >>> 12) & 0x3f)) +
|
||||
fromCharCode(0x80 | ((cc >>> 6) & 0x3f)) +
|
||||
fromCharCode(0x80 | (cc & 0x3f)));
|
||||
}
|
||||
};
|
||||
var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
|
||||
var utob = function (u) {
|
||||
return u.replace(re_utob, cb_utob);
|
||||
};
|
||||
var _encode = function (u) {
|
||||
var isUint8Array = Object.prototype.toString.call(u) === '[object Uint8Array]';
|
||||
if (isUint8Array)
|
||||
return u.toString('base64')
|
||||
else
|
||||
return btoa(utob(String(u)));
|
||||
}
|
||||
|
||||
if (typeof btoa !== 'function') btoa = func_btoa;
|
||||
|
||||
function func_btoa(input) {
|
||||
var str = String(input);
|
||||
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
for (
|
||||
// initialize result and counter
|
||||
var block, charCode, idx = 0, map = chars, output = '';
|
||||
// if the next str index does not exist:
|
||||
// change the mapping table to "="
|
||||
// check if d has no fractional digits
|
||||
str.charAt(idx | 0) || (map = '=', idx % 1);
|
||||
// "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
|
||||
output += map.charAt(63 & block >> 8 - idx % 1 * 8)
|
||||
) {
|
||||
charCode = str.charCodeAt(idx += 3 / 4);
|
||||
if (charCode > 0xFF) {
|
||||
throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
|
||||
}
|
||||
block = block << 8 | charCode;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
function encode(u, urisafe) {
|
||||
return !urisafe ?
|
||||
_encode(u) :
|
||||
_encode(String(u)).replace(/[+\/]/g, function (m0) {
|
||||
return m0 == '+' ? '-' : '_';
|
||||
}).replace(/=/g, '');
|
||||
}
|
||||
|
||||
function IEVersion() {
|
||||
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
|
||||
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
|
||||
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
|
||||
var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
|
||||
if (isIE) {
|
||||
var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
|
||||
reIE.test(userAgent);
|
||||
var fIEVersion = parseFloat(RegExp["$1"]);
|
||||
if (fIEVersion == 7) {
|
||||
return 7;
|
||||
} else if (fIEVersion == 8) {
|
||||
return 8;
|
||||
} else if (fIEVersion == 9) {
|
||||
return 9;
|
||||
} else if (fIEVersion == 10) {
|
||||
return 10;
|
||||
} else {
|
||||
return 6; //IE版本<=7
|
||||
}
|
||||
} else if (isEdge) {
|
||||
return 20; //edge
|
||||
} else if (isIE11) {
|
||||
return 11; //IE11
|
||||
} else {
|
||||
return 30; //不是ie浏览器
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成guid的接口
|
||||
* @returns guid
|
||||
*/
|
||||
function guid() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义协议启动服务端
|
||||
* 默认不带参数serverId,linux未升级之前不要使用多用户
|
||||
*/
|
||||
function InitWpsCloudSvr() {
|
||||
if (serverId == undefined)
|
||||
window.location.href = "ksoWPSCloudSvr://start=RelayHttpServer"//是否启动wps弹框
|
||||
else
|
||||
window.location.href = "ksoWPSCloudSvr://start=RelayHttpServer" + "&serverId=" + serverId //是否启动wps弹框
|
||||
}
|
||||
|
||||
var serverId = undefined;
|
||||
|
||||
/**
|
||||
* 获取serverId的接口
|
||||
* @returns serverId
|
||||
*/
|
||||
function getServerId() {
|
||||
if (window.localStorage) {
|
||||
if (localStorage.getItem("serverId")) {
|
||||
//
|
||||
}
|
||||
else {
|
||||
localStorage.setItem("serverId", guid());
|
||||
}
|
||||
return localStorage.getItem("serverId");
|
||||
}
|
||||
else {
|
||||
return guid();
|
||||
}
|
||||
}
|
||||
|
||||
function startWps(req, t, callback) {
|
||||
function startWpsInnder(reqInner, tryCount, bPop) {
|
||||
if (tryCount < 1) {
|
||||
if (callback)
|
||||
callback({
|
||||
status: 2,
|
||||
message: "请允许浏览器打开WPS Office"
|
||||
});
|
||||
return;
|
||||
}
|
||||
var bRetry = true;
|
||||
var xmlReq = getHttpObj();
|
||||
//WPS客户端提供的接收参数的本地服务,HTTP服务端口为58890,HTTPS服务端口为58891
|
||||
//这俩配置,取一即可,不可同时启用
|
||||
xmlReq.open(reqInner.type, reqInner.url);
|
||||
xmlReq.onload = function (res) {
|
||||
if (res.target.status != 200) {
|
||||
var responseStr = IEVersion() < 10 ? xmlReq.responseText : res.target.response;
|
||||
var errorMessage = JSON.parse(responseStr)
|
||||
if (errorMessage.data == "Subserver not available." && tryCount == 4 && bPop) {
|
||||
InitWpsCloudSvr();
|
||||
setTimeout(function () {
|
||||
if (bRetry) {
|
||||
bRetry = false;
|
||||
startWpsInnder(reqInner, --tryCount, false);
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
if (callback)
|
||||
callback({
|
||||
status: 0,
|
||||
res: res
|
||||
});
|
||||
}
|
||||
xmlReq.ontimeout = xmlReq.onerror = function (res) {
|
||||
xmlReq.bTimeout = true;
|
||||
if (bPop) { //打开wps并传参
|
||||
InitWpsCloudSvr()
|
||||
}
|
||||
setTimeout(function () {
|
||||
if (bRetry) {
|
||||
bRetry = false;
|
||||
startWpsInnder(reqInner, --tryCount, false);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
if (IEVersion() < 10) {
|
||||
xmlReq.onreadystatechange = function () {
|
||||
if (xmlReq.readyState != 4)
|
||||
return;
|
||||
if (xmlReq.bTimeout) {
|
||||
return;
|
||||
}
|
||||
if (xmlReq.status === 200)
|
||||
xmlReq.onload();
|
||||
else
|
||||
xmlReq.onerror();
|
||||
}
|
||||
}
|
||||
xmlReq.timeout = 3000;
|
||||
xmlReq.send(t)
|
||||
}
|
||||
startWpsInnder(req, 4, true);
|
||||
return;
|
||||
}
|
||||
|
||||
function CheckPlugin(element) {
|
||||
var id = GetAddonId(element);
|
||||
var ele = document.getElementById(id + "_status");
|
||||
var xmlReq = getHttpObj();
|
||||
var offline = element.online === "false";
|
||||
var url = offline ? element.url : element.url + "ribbon.xml";
|
||||
xmlReq.open("POST", "http://localhost:58890/redirect/runParams");
|
||||
xmlReq.onload = function (res) {
|
||||
if ((offline && res.target.response.startsWith("7z"))
|
||||
|| !offline && res.target.response.startsWith("<customUI")) {
|
||||
ele.style.color = "green";
|
||||
ele.style.textAlign = "center";
|
||||
ele.innerHTML = "正常";
|
||||
} else {
|
||||
ele.style.color = "white";
|
||||
ele.style.backgroundColor = "gray";
|
||||
ele.style.textAlign = "center";
|
||||
ele.innerHTML = "无效";
|
||||
ele.title = offline ? ("不是有效的7z格式" + url) : ("不是有效的ribbon.xml," + url);
|
||||
}
|
||||
}
|
||||
xmlReq.onerror = function (res) {
|
||||
xmlReq.bTimeout = true;
|
||||
ele.style.color = "white";
|
||||
ele.style.backgroundColor = "gray";
|
||||
ele.style.textAlign = "center";
|
||||
ele.innerHTML = "无效";
|
||||
ele.title = "网页路径不可访问,如果是跨域问题,不影响使用:" + url;
|
||||
}
|
||||
xmlReq.ontimeout = function (res) {
|
||||
xmlReq.bTimeout = true;
|
||||
ele.style.color = "white";
|
||||
ele.style.backgroundColor = "gray";
|
||||
ele.style.textAlign = "center";
|
||||
ele.innerHTML = "异常";
|
||||
ele.title = "访问超时," + url;
|
||||
}
|
||||
if (IEVersion() < 10) {
|
||||
xmlReq.onreadystatechange = function () {
|
||||
if (xmlReq.readyState != 4)
|
||||
return;
|
||||
if (xmlReq.bTimeout) {
|
||||
return;
|
||||
}
|
||||
if (xmlReq.status === 200)
|
||||
xmlReq.onload();
|
||||
else
|
||||
xmlReq.onerror();
|
||||
}
|
||||
}
|
||||
xmlReq.timeout = 5000;
|
||||
var data = {
|
||||
method: "get",
|
||||
url: url,
|
||||
data: ""
|
||||
}
|
||||
var sendData = FormatSendData(data)
|
||||
xmlReq.send(sendData);
|
||||
}
|
||||
|
||||
function GetAddonId(element) {
|
||||
return element.name + "/" + element.addonType;
|
||||
}
|
||||
|
||||
function UpdateElement(element, cmd) {
|
||||
if (typeof element.name === 'undefined')
|
||||
return
|
||||
var id = GetAddonId(element);
|
||||
var addonList = document.getElementById("addonList");
|
||||
//var param = JSON.stringify(element).replace(/"/g, "\'");
|
||||
var buttonLabel = cmd === 'enable' ? "安装" : "卸载";
|
||||
var des = "文字";
|
||||
if (element.addonType == "et")
|
||||
des = "电子表格";
|
||||
else if (element.addonType == "wpp")
|
||||
des = "演示";
|
||||
var loadType = "在线";
|
||||
if (element.online == "false")
|
||||
loadType = "离线";
|
||||
var old = document.getElementById(id);
|
||||
if (old !== null) {
|
||||
var oldOnline = old.wpsaddon.online === "false";
|
||||
var newOnline = element.online === "false";
|
||||
if (cmd === 'disable'
|
||||
&& (oldOnline !== newOnline
|
||||
|| old.wpsaddon.url !== element.url
|
||||
|| (oldOnline && old.wpsaddon.version !== element.version))) {
|
||||
buttonLabel = "更新/卸载";
|
||||
cmd = "choose";
|
||||
}
|
||||
old.wpsaddoncmd = cmd;
|
||||
document.getElementById(id + '_button').innerHTML = buttonLabel;
|
||||
} else {
|
||||
var ele = document.createElement("div");
|
||||
ele.className = "addonItem";
|
||||
ele.id = id;
|
||||
ele.wpsaddon = element;
|
||||
ele.wpsaddoncmd = cmd;
|
||||
ele.innerHTML =
|
||||
'<div class="addonItemName1">' + element.name + '</div>\n' +
|
||||
'<div class="addonItemName2">' + des + '</div>\n' +
|
||||
'<div class="addonItemName3">' + loadType + '</div>\n' +
|
||||
'<div class="addonItemName4">' + element.url + '</div>\n' +
|
||||
'<div class="addonItemName5"><div class="addonItemButton" id="' + id + '_button' + '" onclick="WpsAddonHandle(\'' + id + '\')">' + buttonLabel + '</div></div>\n' +
|
||||
'<div class="addonItemName6" id="' + id + '_status' + '">验证中...</div>\n';
|
||||
addonList.appendChild(ele);
|
||||
CheckPlugin(element);
|
||||
}
|
||||
}
|
||||
|
||||
function WpsAddonHandle(id) {
|
||||
var ele = document.getElementById(id);
|
||||
var element = ele.wpsaddon;
|
||||
var cmd = ele.wpsaddoncmd;
|
||||
WpsAddonHandleEx(element, cmd)
|
||||
}
|
||||
|
||||
function WpsAddonHandleEx(element, cmd) {
|
||||
if (cmd === "choose") {
|
||||
if (confirm("点击确定将更新 WPS 加载项,或点击取消完成卸载")) {
|
||||
cmd = "enable";
|
||||
} else {
|
||||
cmd = "disable";
|
||||
}
|
||||
}
|
||||
var data = FormartData(element, cmd);
|
||||
var req = { url: "http://localhost:58890/deployaddons/runParams", type: "POST" };
|
||||
startWps(req, data, function (res) {
|
||||
if (res.status == 0) {
|
||||
if (cmd === "disableall") {
|
||||
window.location.reload();
|
||||
} else {
|
||||
if (res.res.target.response == "OK"
|
||||
|| (res.res.target.response == "" && res.res.target.status == 200)) {
|
||||
var newCmd = 'disable';
|
||||
if (cmd === 'disable')
|
||||
newCmd = 'enable';
|
||||
UpdateElement(element, newCmd)
|
||||
alert("配置成功!");
|
||||
}
|
||||
else {
|
||||
alert("配置失败!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
alert(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function FormartData(element, cmd) {
|
||||
var data = {
|
||||
"cmd": cmd, //"enable", 启用, "disable", 禁用, "disableall", 禁用所有
|
||||
"name": element.name,
|
||||
"url": element.url,
|
||||
"addonType": element.addonType,
|
||||
"online": element.online,
|
||||
"version": element.version
|
||||
}
|
||||
return FormatSendData(data);
|
||||
}
|
||||
|
||||
function FormatSendData(data) {
|
||||
var strData = JSON.stringify(data);
|
||||
if (IEVersion() < 10)
|
||||
eval("strData = '" + JSON.stringify(strData) + "';");
|
||||
|
||||
if (serverVersion >= "1.0.2" && serverId != undefined) {
|
||||
var base64Data = encode(strData);
|
||||
return JSON.stringify({
|
||||
serverId: serverId,
|
||||
data: base64Data
|
||||
})
|
||||
}
|
||||
else {
|
||||
return encode(strData);
|
||||
}
|
||||
}
|
||||
|
||||
function LoadLocalAddons() {
|
||||
var baseData
|
||||
if (serverVersion >= "1.0.2" && serverId != undefined)
|
||||
baseData = JSON.stringify({ serverId: serverId });
|
||||
var req = { url: "http://127.0.0.1:58890/publishlist", type: "POST" };
|
||||
startWps(req, baseData, function (res) {
|
||||
if (res.status == 0) {
|
||||
var addonList = document.getElementById("addonList");
|
||||
var curList = JSON.parse(res.res.target.response);
|
||||
curList.forEach(function (element) {
|
||||
if (element.enable === "false")
|
||||
return;
|
||||
UpdateElement(element, 'disable')
|
||||
});
|
||||
} else {
|
||||
alert(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function LoadPublishAddons() {
|
||||
var addonList = document.getElementById("addonList");
|
||||
var curList = [{ "name": "test123", "addonType": "wps", "online": "true", "multiUser": "false", "url": "http://www.test.a/" }, { "name": "XbotWps", "addonType": "et", "online": "true", "multiUser": "false", "url": "https://wps.woni.link/jsplugindir/" }, { "name": "xbotwps", "addonType": "wps", "online": "false", "multiUser": "false", "url": "123/xbotwps.7z", "version": "1.0.0" }, { "name": "xbot-et", "addonType": "et", "online": "false", "multiUser": "false", "url": "http://127.0.0.1:8000/xbot-et.7z", "version": "1.0.0" }];
|
||||
curList.forEach(function (element) {
|
||||
var param = JSON.stringify(element).replace("\"", "\'");
|
||||
UpdateElement(element, 'enable')
|
||||
});
|
||||
}
|
||||
|
||||
var serverVersion = "wait";
|
||||
function InitSdk() {
|
||||
var req = { url: "http://127.0.0.1:58890/version", type: "POST" };
|
||||
startWps(
|
||||
req,
|
||||
JSON.stringify({ serverId: serverId }),
|
||||
function (res) {
|
||||
if (res.status !== 0) {
|
||||
return;
|
||||
}
|
||||
if (serverVersion == "wait") {
|
||||
serverVersion = res.res.target.response;
|
||||
LoadPublishAddons();
|
||||
LoadLocalAddons();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function LoadAddons() {
|
||||
var addonList = document.getElementById("addonList");
|
||||
addonList.style.maxWidth = 800 * window.devicePixelRatio + "px";
|
||||
var ClearAll = document.getElementById("ClearAll");
|
||||
ClearAll.style.maxWidth = 800 * window.devicePixelRatio + "px";
|
||||
InitSdk();
|
||||
}
|
||||
|
||||
function ClearAll() {
|
||||
if (confirm('确定要禁用所有WPS加载项吗?')) {
|
||||
var element = {};
|
||||
WpsAddonHandleEx(element, 'disableall');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="LoadAddons()">
|
||||
<div class="divTitle">WPS加载项配置</div>
|
||||
<div class="addonList" id="addonList">
|
||||
<div class="addonItem addonItemTitle">
|
||||
<div class="addonItemName1">加载项名称</div>
|
||||
<div class="addonItemName2">类型</div>
|
||||
<div class="addonItemName3">加载方式</div>
|
||||
<div class="addonItemName4">URL</div>
|
||||
<div class="addonItemName5">管理</div>
|
||||
<div class="addonItemName6">状态</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ClearAll" onclick="ClearAll()" id="ClearAll">禁用所有 WPS 加载项</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Binary file not shown.
Reference in new issue
Block a user