2025-11-23 17:22:35 +08:00
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
2025-11-29 05:16:23 +08:00
|
|
|
<head lang="zh">
|
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
|
|
|
<meta name="renderer" content="webkit" />
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=0" />
|
|
|
|
|
<title>Luckysheet</title>
|
|
|
|
|
<link rel="stylesheet" href="./plugins/css/pluginsCss.css" />
|
|
|
|
|
<link rel="stylesheet" href="./plugins/plugins.css" />
|
|
|
|
|
<link rel="stylesheet" href="./css/luckysheet.css" />
|
|
|
|
|
<link rel="stylesheet" href="./assets/iconfont/iconfont.css" />
|
|
|
|
|
<script src="./plugins/js/plugin.js"></script>
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
<!-- rollup luckysheet.js -->
|
|
|
|
|
<script src="./luckysheet.umd.js"></script>
|
|
|
|
|
<script src="./demoData/sheetVchart.js"></script>
|
|
|
|
|
<script src="./demoData/sheetChart.js"></script>
|
|
|
|
|
<script src="./demoData/sheetCell.js"></script>
|
|
|
|
|
<script src="./demoData/sheetPicture.js"></script>
|
|
|
|
|
</head>
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
<body>
|
|
|
|
|
<div id="luckysheet" style="margin: 0px; padding: 0px; position: absolute; width: 100%; height: 100%; left: 0px; top: 0px"></div>
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
<script>
|
|
|
|
|
// 公共配置项
|
|
|
|
|
const commonOptions = {
|
|
|
|
|
container: "luckysheet",
|
|
|
|
|
lang: "zh",
|
|
|
|
|
// showinfobar: false, // 隐藏信息栏
|
|
|
|
|
// showlogo: false, // 隐藏logo
|
|
|
|
|
plugins: [{ name: "vchart" }, { name: "chart" }],
|
|
|
|
|
data: [sheetCell],
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 打印像素比,设置越高,越清晰
|
|
|
|
|
printDevicePixelRatio: 4,
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 图片显示方式
|
|
|
|
|
imageMode: "cell", // 'cell' | 'float'
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 自定义快捷键
|
|
|
|
|
customShortcutKeys: [
|
|
|
|
|
{
|
|
|
|
|
key: 83,
|
|
|
|
|
ctrl: true,
|
|
|
|
|
callback: (e) => {
|
|
|
|
|
console.log("Ctrl S");
|
2025-11-23 17:22:35 +08:00
|
|
|
},
|
|
|
|
|
},
|
2025-11-29 05:16:23 +08:00
|
|
|
{
|
|
|
|
|
key: 80,
|
|
|
|
|
ctrl: true,
|
|
|
|
|
callback: (e) => {
|
|
|
|
|
luckysheet.print("sheet");
|
2025-11-23 17:22:35 +08:00
|
|
|
},
|
|
|
|
|
},
|
2025-11-29 05:16:23 +08:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// 自定义右键菜单
|
|
|
|
|
cellRightClickConfig: {
|
|
|
|
|
// copy: false,
|
|
|
|
|
copyAs: false,
|
|
|
|
|
// paste: false,
|
|
|
|
|
hideColumn: false,
|
|
|
|
|
columnWidth: false,
|
|
|
|
|
clear: false,
|
|
|
|
|
matrix: false,
|
|
|
|
|
sort: false,
|
|
|
|
|
filter: false,
|
|
|
|
|
chart: false,
|
|
|
|
|
image: false,
|
|
|
|
|
link: false,
|
|
|
|
|
data: false,
|
|
|
|
|
cellFormat: false,
|
|
|
|
|
customs: [
|
2025-11-23 17:22:35 +08:00
|
|
|
{
|
2025-11-29 05:16:23 +08:00
|
|
|
title: "test",
|
|
|
|
|
onClick: function (clickEvent, event, params) {
|
|
|
|
|
console.log("function test click", clickEvent, event, params);
|
|
|
|
|
},
|
|
|
|
|
},
|
2025-11-23 17:22:35 +08:00
|
|
|
],
|
|
|
|
|
},
|
2025-11-29 05:16:23 +08:00
|
|
|
|
|
|
|
|
// 项目菜单
|
|
|
|
|
menuHandler: {
|
|
|
|
|
// 隐藏内置菜单
|
|
|
|
|
// hideDefaultMenu: ['exportFile', 'importFile'],
|
|
|
|
|
// 自定义
|
|
|
|
|
customs: [
|
|
|
|
|
// 分割线
|
|
|
|
|
{
|
|
|
|
|
order: 0,
|
|
|
|
|
label: "自定义菜单",
|
|
|
|
|
value: "newFile",
|
|
|
|
|
callback: () => {
|
|
|
|
|
console.log("==> 自定义菜单");
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
order: 0,
|
|
|
|
|
value: "divider",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// loading 样式
|
|
|
|
|
loading: {
|
|
|
|
|
image: () => {
|
|
|
|
|
return `<svg viewBox="25 25 50 50" class="circular">
|
|
|
|
|
<circle cx="50" cy="50" r="20" fill="none"></circle>
|
|
|
|
|
</svg>`;
|
|
|
|
|
},
|
|
|
|
|
imageClass: "loadingAnimation",
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理协同图片上传
|
|
|
|
|
async function uploadImage(file, serviceServer) {
|
|
|
|
|
// 此处拿到的是上传的 file 对象,进行文件上传 ,配合 node 接口实现
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
formData.append("image", file);
|
|
|
|
|
|
|
|
|
|
// 结合 Ajax 实现图片上传
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: `${serviceServer}/uploadImage`,
|
|
|
|
|
type: "POST",
|
|
|
|
|
data: formData,
|
|
|
|
|
processData: false,
|
|
|
|
|
contentType: false,
|
|
|
|
|
success: function (res) {
|
|
|
|
|
if (res.code === 200) resolve(res.url);
|
|
|
|
|
else reject("image upload error");
|
|
|
|
|
},
|
|
|
|
|
error: function (err) {
|
|
|
|
|
reject("image upload error");
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
});
|
2025-11-23 17:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 处理上传图片的地址
|
|
|
|
|
function imageUrlHandle(url, serviceServer) {
|
|
|
|
|
// 已经是 // http data 开头则不处理
|
|
|
|
|
if (/^(?:\/\/|(?:http|https|data):)/i.test(url)) return url;
|
|
|
|
|
// 不然拼接服务器路径
|
|
|
|
|
return serviceServer + url;
|
2025-11-23 17:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 动态获取 luadUrl
|
|
|
|
|
function getLoadUrl(serviceServer, currentBranch, gridkey) {
|
|
|
|
|
return `${serviceServer}${currentBranch === "master-alpha" ? "/" : "/luckysheet/"}loadSheetData?gridkey=${gridkey}`;
|
2025-11-23 17:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 动态获取 updateUrl
|
|
|
|
|
function getUpdateUrl(collabrationServer, currentBranch, userid, username, gridkey) {
|
|
|
|
|
return `${collabrationServer}
|
|
|
|
|
${currentBranch === "master-alpha" ? "?" : "/luckysheet?"}
|
|
|
|
|
type=luckysheet&userid=${userid}&username=${username}&gridkey=${gridkey}`;
|
2025-11-23 17:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 根据协同与否,动态获取配置
|
|
|
|
|
function getOptions(
|
|
|
|
|
isCollabration,
|
|
|
|
|
requestHeaders = {},
|
|
|
|
|
serviceServer,
|
|
|
|
|
collabrationServer,
|
|
|
|
|
currentBranch,
|
|
|
|
|
userid,
|
|
|
|
|
username,
|
|
|
|
|
gridkey
|
|
|
|
|
) {
|
|
|
|
|
// 如果没有开启协同,则直接返回基础配置
|
|
|
|
|
if (!isCollabration) return Object.assign({}, commonOptions, { requestHeaders });
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
return Object.assign({}, commonOptions, {
|
|
|
|
|
// 如果是 master-vue 的话,还需要添加自定义请求头,请检查合并属性哈,不然容易遗漏属性
|
|
|
|
|
requestHeaders:
|
|
|
|
|
currentBranch === "master-vue"
|
|
|
|
|
? {
|
|
|
|
|
"enable-pass-token": true, // 是否允许跳过 token 验证
|
|
|
|
|
...requestHeaders,
|
|
|
|
|
}
|
|
|
|
|
: requestHeaders,
|
|
|
|
|
allowUpdate: true, // 配置协同功能
|
|
|
|
|
loadUrl: getLoadUrl(serviceServer, currentBranch, gridkey),
|
|
|
|
|
updateUrl: getUpdateUrl(collabrationServer, currentBranch, userid, username, gridkey), // 协同服务转发服务
|
2025-11-23 17:22:35 +08:00
|
|
|
|
2025-11-29 05:16:23 +08:00
|
|
|
// 如果配置了协同,请配置图片处理函数,避免base64图片过大导致图片无法显示
|
|
|
|
|
uploadImage: (file) => uploadImage(file, serviceServer),
|
|
|
|
|
imageUrlHandle: (url) => imageUrlHandle(url, serviceServer),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @description 页面初始化相关工作
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
$(function () {
|
|
|
|
|
/**
|
|
|
|
|
* -------------------------------------------------------
|
|
|
|
|
* ⚠️ 注意:请严格按照下列步骤进行配置,否则会导致无法协同 ⚠️
|
|
|
|
|
* -------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// 1. 请明确协同服务地址
|
|
|
|
|
const collabrationServer = "ws://localhost:9000";
|
|
|
|
|
|
|
|
|
|
// 2. 请明确业务服务地址
|
|
|
|
|
const serviceServer = "http://localhost:9000";
|
|
|
|
|
|
|
|
|
|
// 3. 请明确 `luckysheet-crdt` 项目目前所在的分支,因为 master-alpha 与 master-vue 分支所在的服务端不尽相同,`master-vue` 分支需要校验 token
|
|
|
|
|
const currentBranch = "master-alpha"; // "master-vue" | "master-alpha"
|
|
|
|
|
|
|
|
|
|
// 4. 定义 userid 内部 userid 可随机生成
|
|
|
|
|
const userid = Math.random().toString(16).slice(2, 8);
|
|
|
|
|
|
|
|
|
|
// 5. username 字段 仅用于显示 xxx正在编辑 (对中文进行编码传输,避免乱码)
|
|
|
|
|
const username = encodeURIComponent(`用户_${userid}`);
|
|
|
|
|
|
|
|
|
|
// 6. 这个是协同的文件 gridKey 请真实的设置为数据库的 key,不然会提示协同服务异常 是真实数据库表的 workerbooks gridKey 字段
|
|
|
|
|
const gridkey = "705abf334c946bf5545ce04f586eb42e";
|
|
|
|
|
|
|
|
|
|
// 7. 明确是否需要协同功能
|
|
|
|
|
const isCollabration = false;
|
|
|
|
|
|
|
|
|
|
// 8. 是否需要携带其他 request headers
|
|
|
|
|
const requestHeaders = {
|
|
|
|
|
// "Custom-userid": userid,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 9. 根据是否需要协同功能,动态获取配置项
|
|
|
|
|
const options = getOptions(
|
|
|
|
|
isCollabration,
|
|
|
|
|
requestHeaders,
|
|
|
|
|
serviceServer,
|
|
|
|
|
collabrationServer,
|
|
|
|
|
currentBranch,
|
|
|
|
|
userid,
|
|
|
|
|
username,
|
|
|
|
|
gridkey
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 10. 创建表格
|
|
|
|
|
luckysheet.create(options);
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|