Files
2025-08-11 15:56:29 +08:00

612 lines
24 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {app} from '../../../scripts/app.js'
import {api} from '../../../scripts/api.js'
import {ComfyWidgets} from '../../../scripts/widgets.js'
import {$el} from '../../../scripts/ui.js'
// 添加样式
const styleElement = document.createElement("style");
const cssCode = `
#msgDiv{
width:800px;
height: 200px;
text-align: center;
font-size: 30px;
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 40px;
color: var(--fg-color);
}
#qrCode{
display: block;
width:256px;
height:256px;
border-radius: 10px;
}
#qrBox{
display: block;
text-align: center;
display:flex;
flex-wrap: wrap;
justify-content: center;
width: 360px;
margin:auto;
}
#qrDesc{
display: block;
text-align: center;
margin-top: 20px;
color: #ffffff;
width: 360px;
}
.codeImg {
// display: block;
width:256px;
height:256px;
border-radius: 10px;
padding: 10px;
border: 2px solid #ffffff;
}
.codeDesc {
display: block;
text-align: center;
margin-top: 20px;
color: #ffffff;
width: 360px;
font-size: 16px;
}
.codeDiv {
color: #ffffff;
}
.codeBox {
display: flex;
text-align: center;
}
#directions {
margin-top: 10px;
width: 100%;
text-align: left;
color: #ffffff;
font-size: 8px;
}
.tech_button {
flex:1;
height:30px;
border-radius: 8px;
border: 2px solid var(--border-color);
font-size:11px;
background:var(--comfy-input-bg);
color:var(--error-text);
box-shadow:none;
cursor:pointer;
width: 1rem;
}
#tech_box {
max-height: 80px;
display:flex;
flex-wrap: wrap;
align-items: flex-start;
}
.uniqueid {
display: none;
}
#showMsgDiv {
width:800px;
padding: 60px 0;
text-align: center;
font-size: 30px;
color: var(--fg-color);
}
`
styleElement.innerHTML = cssCode
document.head.appendChild(styleElement);
var techsidkey = 'techsid' + window.location.port;
var loading = false;
const msgBox = $el("div.comfy-modal", {parent: document.body}, []);
const msgDiv = $el('div', {id: 'msgDiv'}, '');
msgBox.appendChild(msgDiv);
msgBox.style.display = "none";
msgBox.style.zIndex = 10001;
let manager_instance = null;
function setCookie(name, value, days = 1) {
var data = {
value: value,
expires: new Date(new Date().getTime() + (days * 24 * 60 * 60 * 1000))
};
localStorage.setItem(name, JSON.stringify(data));
}
function getCookie(name) {
var data = localStorage.getItem(name);
if (!data) {
return ''; // 未找到数据,返回空字符串
}
data = JSON.parse(data);
if (new Date(data.expires) > new Date()) {
return data.value; // 数据有效,返回存储的值
} else {
localStorage.removeItem(name); // 数据过期,删除项
return ''; // 数据过期,返回空字符串
}
}
function generateTimestampedRandomString() {
const timestamp = Date.now().toString(36);
const randomString = Array(3).fill(0).map(() => Math.random().toString(36).substring(2)).join('').substring(0, 18);
const timestampedRandomString = (timestamp + randomString).substring(0, 32);
return timestampedRandomString;
}
function showLoading(msg = '') {
hideLoading();
msgDiv.innerText = msg ? msg : '请稍后...';
msgBox.style.display = "block";
loading = true;
}
function hideLoading() {
msgBox.style.display = "none";
loading = false;
}
function showToast(msg = '', t = 0) {
t = t > 0 ? t : 2000;
msgDiv.innerText = msg ? msg : '谢谢';
msgBox.style.display = "block";
setTimeout(() => {
msgBox.style.display = "none";
}, t);
}
var serverUrl = window.location.href;
const qrCode = $el('img', {
id: 'qrCode', src: ``,
onerror: () => {
// console.log('参数错误');
}
})
const qrDesc = $el('div', {id: 'qrDesc'}, '')
const qrInnerHtml = $el('div', {id: 'qr-inner'}, '')
const qrBox = $el('div', {id: 'qrBox'}, [qrInnerHtml])
app.ui.dialog.element.style.zIndex = 10010;
function getMsgByEnglish(en_str){
var lang = getCookie('deploy_lang');
if (lang == 'en') {
return en_str;
}
const msgDict = {
'Please wait...': '请稍后...',
'There can only be one "DeployCash" node in a workflow': '工作流中只能有一个"DeployCash"节点',
'Please make sure that there is only one "SaveImgae", "DeployCash_saveImage" or "VHS_VideoCombine" node in the workflow.': '请确保工作流中只有一个"SaveImgae"、"DeployCash_saveImage"、"VHS_VideoCombine"或"SaveVideo"节点。',
'Instructions for use of works': '作品使用说明',
'"app_img1" can only connect "LoadImage" node': '"app_img1" 只能连接 "LoadImage" 节点',
'"app_img2" can only connect "LoadImage" node': '"app_img2" 只能连接 "LoadImage" 节点',
'"app_img3" can only connect "LoadImage" node': '"app_img3" 只能连接 "LoadImage" 节点',
'"custom_img1" can only connect "LoadImage" node': '"custom_img1"只能连接"LoadImage"节点',
'"custom_img2" can only connect "LoadImage" node': '"custom_img2"只能连接"LoadImage"节点',
'"custom_img3" can only connect "LoadImage" node': '"custom_img3"只能连接"LoadImage"节点',
'"custom_img4" can only connect "LoadImage" node': '"custom_img4"只能连接"LoadImage"节点',
'"custom_video1" can only connect "Load Video (Upload)" node': '"custom_video1" 只能连接"加载视频(上传)"节点',
'"custom_video2" can only connect "Load Video (Upload)" node': '"custom_video2" 只能连接"加载视频(上传)"节点',
'"custom_video3" can only connect "Load Video (Upload)" node': '"custom_video3" 只能连接"加载视频(上传)"节点',
'"custom_text1" can only connect "textInput" node': '"custom_text1"只能连接"textInput"节点',
'"custom_text2" can only connect "textInput" node': '"custom_text2"只能连接"textInput"节点',
'"custom_text3" can only connect "textInput" node': '"custom_text3"只能连接"textInput"节点',
'"app_title", Cannot be empty, please fill in the title of the work': '"app_title"不能为空,请填写作品标题',
'"app_desc", Cannot be empty, please fill in the function introduction of the work': '"app_desc"不能为空,请填写作品功能介绍',
'Please fill in the description of the work': '请填写作品描述',
'"app_fee" Cannot be less than 0 points, i.e. 0 $': '"app_fee"不能小于0积分,即0$',
'"free_times" Cannot be less than 0': '"free_times"不能小于0',
'Click here to transfer the workflow to the web/H5 and obtain the access address': '点此,工作流转小程序/H5,并获取访问地址',
'Processing, please wait...': '正在处理,请稍候...'
};
return en_str in msgDict ? msgDict[en_str] : '';
}
const showMsgDiv = $el('div', {id: 'showMsgDiv'}, getMsgByEnglish('Please wait...'));
function showCodeBox(html) {
app.ui.dialog.close();
var htmlBox = $el('div.codeBox', {}, '');
htmlBox.innerHTML = html;
app.ui.dialog.show(htmlBox);
}
function showQrBox(img, desc, html) {
app.ui.dialog.close();
// qrDesc.innerText = desc;
// qrCode.src = img;
qrInnerHtml.innerHTML = html;
// qrDesc.innerHTML = html;
qrBox.style.margin = 'auto';
app.ui.dialog.show(qrBox);
}
function hideCodeBox() {
app.ui.dialog.close();
}
function showMsg(msg) {
app.ui.dialog.close();
showMsgDiv.innerText = msg;
app.ui.dialog.show(showMsgDiv);
}
function hideMsg() {
app.ui.dialog.close();
}
function tech_alert(text) {
loading = false;
// alert(text);
showMsg(text);
}
function getPostData(prompt) {
const output = prompt['output'];
let HuiseNum = 0;
let HuiseO = {};
let HuiseN = {};
let postData = {};
let saveImageNodes = [];
for (const key in output) {
if (output[key].class_type == 'DeployCash') {
HuiseO = output[key].inputs;
HuiseNum++;
}
console.log(output[key].class_type)
console.log(output[key].class_type)
console.log(output[key].class_type)
console.log(output[key].class_type)
console.log(output[key].class_type)
if (output[key].class_type == 'SaveImage' || output[key].class_type == 'VHS_VideoCombine' || output[key].class_type == 'DeployCash_saveImage' || output[key].class_type == 'SaveGLB' || output[key].class_type == 'SaveAnimatedWEBP' || output[key].class_type == 'SaveVideo') {
output[key].res_node = key;
saveImageNodes.push(output[key]);
}
}
if (HuiseNum > 1) {
return getMsgByEnglish('There can only be one "DeployCash" node in a workflow');
}
if (saveImageNodes.length < 1) {
return (getMsgByEnglish('Please make sure that there is only one "SaveImgae", "DeployCash_saveImage" or "VHS_VideoCombine" node in the workflow.'));
} else if (saveImageNodes.length > 1) {
return (getMsgByEnglish('Please make sure that there is only one "SaveImgae", "DeployCash_saveImage" or "VHS_VideoCombine" node in the workflow.'));
} else {
postData['res_node'] = saveImageNodes[0].res_node;
}
if (HuiseO) {
HuiseN['zhutu1'] = HuiseO['app_img1(optional)'];
HuiseN['zhutu2'] = HuiseO['app_img2(optional)'];
HuiseN['zhutu3'] = HuiseO['app_img3(optional)'];
HuiseN['cs_img1'] = HuiseO['custom_img1(optional)'];
HuiseN['cs_img2'] = HuiseO['custom_img2(optional)'];
HuiseN['cs_img3'] = HuiseO['custom_img3(optional)'];
HuiseN['cs_img4'] = HuiseO['custom_img4(optional)'];
HuiseN['cs_video1'] = HuiseO['custom_video1(optional)'];
HuiseN['cs_video2'] = HuiseO['custom_video2(optional)'];
HuiseN['cs_video3'] = HuiseO['custom_video3(optional)'];
HuiseN['cs_text1'] = HuiseO['custom_text1(optional)'];
HuiseN['cs_text2'] = HuiseO['custom_text2(optional)'];
HuiseN['cs_text3'] = HuiseO['custom_text3(optional)'];
HuiseN['title'] = HuiseO['app_title'];
HuiseN['gn_desc'] = HuiseO['app_desc'];
HuiseN['sy_desc'] = getMsgByEnglish('Instructions for use of works');
HuiseN['server'] = serverUrl;
HuiseN['fee'] = HuiseO['app_fee'];
HuiseN['free_times'] = HuiseO['free_times'];
HuiseN['cs_img1_desc'] = HuiseO['custom_img1_desc'];
HuiseN['cs_img2_desc'] = HuiseO['custom_img2_desc'];
HuiseN['cs_img3_desc'] = HuiseO['custom_img3_desc'];
HuiseN['cs_img4_desc'] = HuiseO['custom_img4_desc'];
HuiseN['cs_video1_desc'] = HuiseO['custom_video1_desc'];
HuiseN['cs_video2_desc'] = HuiseO['custom_video2_desc'];
HuiseN['cs_video3_desc'] = HuiseO['custom_video3_desc'];
HuiseN['cs_text1_desc'] = HuiseO['custom_text1_desc'];
HuiseN['cs_text2_desc'] = HuiseO['custom_text2_desc'];
HuiseN['cs_text3_desc'] = HuiseO['custom_text3_desc'];
HuiseN['uniqueid'] = HuiseO['uniqueid'];
postData['mainImages'] = [];
if (HuiseN['zhutu1']) {
if (output[HuiseN['zhutu1'][0]].class_type == 'LoadImage') {
if (output[HuiseN['zhutu1'][0]].inputs.image) {
postData['mainImages'].push(output[HuiseN['zhutu1'][0]].inputs.image);
}
} else {
return getMsgByEnglish('"app_img1" can only connect "LoadImage" node');
}
}
if (HuiseN['zhutu2']) {
if (output[HuiseN['zhutu2'][0]].class_type == 'LoadImage') {
if (output[HuiseN['zhutu2'][0]].inputs.image) {
postData['mainImages'].push(output[HuiseN['zhutu2'][0]].inputs.image);
}
} else {
return getMsgByEnglish('"app_img2" can only connect "LoadImage" node');
}
}
if (HuiseN['zhutu3']) {
if (output[HuiseN['zhutu3'][0]].class_type == 'LoadImage') {
if (output[HuiseN['zhutu3'][0]].inputs.image) {
postData['mainImages'].push(output[HuiseN['zhutu3'][0]].inputs.image);
}
} else {
return getMsgByEnglish('"app_img3" can only connect "LoadImage" node');
}
}
postData['cs_img_nodes'] = [];
if (HuiseN['cs_img1']) {
if (output[HuiseN['cs_img1'][0]].class_type == 'LoadImage') {
postData['cs_img_nodes'].push({node: HuiseN['cs_img1'][0], desc: HuiseN['cs_img1_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_img1" can only connect "LoadImage" node');
}
}
if (HuiseN['cs_img2']) {
if (output[HuiseN['cs_img2'][0]].class_type == 'LoadImage') {
postData['cs_img_nodes'].push({node: HuiseN['cs_img2'][0], desc: HuiseN['cs_img2_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_img2" can only connect "LoadImage" node');
}
}
if (HuiseN['cs_img3']) {
if (output[HuiseN['cs_img3'][0]].class_type == 'LoadImage') {
postData['cs_img_nodes'].push({node: HuiseN['cs_img3'][0], desc: HuiseN['cs_img3_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_img3" can only connect "LoadImage" node');
}
}
if (HuiseN['cs_img4']) {
if (output[HuiseN['cs_img4'][0]].class_type == 'LoadImage') {
postData['cs_img_nodes'].push({node: HuiseN['cs_img4'][0], desc: HuiseN['cs_img4_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_img4" can only connect "LoadImage" node');
}
}
postData['cs_video_nodes'] = [];
if (HuiseN['cs_video1']) {
if (output[HuiseN['cs_video1'][0]].class_type == 'VHS_LoadVideo') {
postData['cs_video_nodes'].push({node: HuiseN['cs_video1'][0], desc: HuiseN['cs_video1_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_video1" can only connect "Load Video (Upload)" node');
}
}
if (HuiseN['cs_video2']) {
if (output[HuiseN['cs_video2'][0]].class_type == 'VHS_LoadVideo') {
postData['cs_video_nodes'].push({node: HuiseN['cs_video2'][0], desc: HuiseN['cs_video2_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_video2" can only connect "Load Video (Upload)" node');
}
}
if (HuiseN['cs_video3']) {
if (output[HuiseN['cs_video3'][0]].class_type == 'VHS_LoadVideo') {
postData['cs_video_nodes'].push({node: HuiseN['cs_video3'][0], desc: HuiseN['cs_video3_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_video3" can only connect "Load Video (Upload)" node');
}
}
postData['cs_text_nodes'] = [];
if (HuiseN['cs_text1']) {
if (output[HuiseN['cs_text1'][0]] && typeof output[HuiseN['cs_text1'][0]].inputs !== 'undefined' && typeof output[HuiseN['cs_text1'][0]].inputs.text !== 'undefined') {
postData['cs_text_nodes'].push({node: HuiseN['cs_text1'][0], desc: HuiseN['cs_text1_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_text1" can only connect "textInput" node');
}
}
if (HuiseN['cs_text2']) {
if (output[HuiseN['cs_text2'][0]] && typeof output[HuiseN['cs_text2'][0]].inputs !== 'undefined' && typeof output[HuiseN['cs_text2'][0]].inputs.text !== 'undefined') {
postData['cs_text_nodes'].push({node: HuiseN['cs_text2'][0], desc: HuiseN['cs_text2_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_text2" can only connect "textInput" node');
}
}
if (HuiseN['cs_text3']) {
if (output[HuiseN['cs_text3'][0]] && typeof output[HuiseN['cs_text3'][0]].inputs !== 'undefined' && typeof output[HuiseN['cs_text3'][0]].inputs.text !== 'undefined') {
postData['cs_text_nodes'].push({node: HuiseN['cs_text3'][0], desc: HuiseN['cs_text3_desc'], value: ''});
} else {
return getMsgByEnglish('"custom_text3" can only connect "textInput" node');
}
}
if (HuiseN['title']) {
postData['title'] = HuiseN['title'];
} else {
return getMsgByEnglish('"app_title", Cannot be empty, please fill in the title of the work');
}
if (HuiseN['gn_desc']) {
postData['gn_desc'] = HuiseN['gn_desc'];
} else {
return getMsgByEnglish('"app_desc", Cannot be empty, please fill in the function introduction of the work');
}
if (HuiseN['sy_desc']) {
postData['sy_desc'] = HuiseN['sy_desc'];
} else {
return getMsgByEnglish('Please fill in the description of the work');
}
if (HuiseN['fee'] >= 0) {
postData['fee'] = HuiseN['fee'];
} else {
return getMsgByEnglish('"app_fee" Cannot be less than 0 points, i.e. 0 $');
}
if (HuiseN['free_times'] >= 0) {
postData['free_times'] = HuiseN['free_times'];
} else {
return getMsgByEnglish('"free_times" Cannot be less than 0');
}
postData['uniqueid'] = HuiseN['uniqueid'];
postData['output'] = output;
postData['workflow'] = prompt['workflow']
return postData;
}
}
async function requestExe(r, postData) {
var techsid = getCookie(techsidkey);
const response = await api.fetchApi(`/manager/tech_main`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
r: r,
techsid: techsid,
postData: postData
})
});
if (!response.ok) {
setTimeout(() => {
showToast('Network connection error, please keep your computer connected to the Internet', 3000);
}, 300);
return;
}
const resdata = await response.json();
return resdata;
}
async function login(s_key) {
var techsid = getCookie(techsidkey);
if (techsid) {
return techsid;
}
let res = await requestExe('comfyui.apiv2.code', {s_key: s_key});
if (app.ui.dialog.element.style.display != 'none') {
if (res.data.data.techsid.length > 5) {
return res.data.data.techsid;
} else {
await new Promise(resolve => setTimeout(resolve, 2000));
return await login(s_key);
}
} else {
return;
}
}
async function request(r, postData) {
showLoading(getMsgByEnglish('Processing, please wait...'));
let resdata = await requestExe(r, postData);
if (resdata.errno == 41009) {
let resdata = await requestExe('comfyui.apiv2.code', {s_key: ''});
if (resdata) {
if (resdata.data.data.code == 1) {
hideLoading();
showQrBox(resdata.data.data.data, resdata.data.data.desc, resdata.data.data.html);
let techsid = await login(resdata.data.data.s_key);
setCookie(techsidkey, techsid, 7);
hideCodeBox();
if (techsid) {
postData['techsid'] = techsid;
return await request(r, postData);
} else {
return;
}
} else {
showToast(resdata.data.data.message);
return;
}
}
} else {
hideLoading();
return resdata;
}
}
app.registerExtension({
name: 'DeployCash',
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === 'DeployCash') {
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
const r = onNodeCreated ? onNodeCreated?.apply(this, arguments) : undefined;
const that = this;
const tech_button = $el('button.tech_button', {
textContent: getMsgByEnglish('Click here to transfer the workflow to the web/H5 and obtain the access address'), style: {},
onclick: async () => {
if (loading) return;
hideCodeBox();
try {
const prompt = await app.graphToPrompt();
let postData = getPostData(prompt);
if (postData['output']) {
try {
let resdata = await request('comfyui.apiv2.upload', postData);
if (resdata) {
if (resdata.data.data.code == 1) {
var lang = resdata.data.data.lang;
setCookie('deploy_lang', lang, 7);
showCodeBox(resdata.data.data.html);
} else {
// showToast(resdata.data.data.message);
showMsg(resdata.data.data.message);
}
}
} catch (error) {
hideLoading();
}
} else {
tech_alert(postData);
return;
}
} catch (error) {
tech_alert('获取api数据失败');
return;
}
}
}
)
const dstr1 = '1. Every time a new "DeployCash" node is created, it corresponds to a new work;';
const directions = $el(
'div',
{id: 'directions'},
['Special instructions:', $el('br'), dstr1,
// $el('br'), dstr2, $el('br'), dstr3
])
const tech_box = $el('div', {id: 'tech_box'}, [tech_button, directions])
this.addDOMWidget('select_styles', "btn", tech_box);
const inputEl = document.createElement("input");
inputEl.setAttribute("type", "text");
inputEl.setAttribute("list", "uedynamiclist");
inputEl.setAttribute("value", generateTimestampedRandomString());
inputEl.className = "uniqueid";
this.addDOMWidget('uniqueid', "input", inputEl, {
getValue() {
return inputEl.value;
},
setValue(v) {
inputEl.value = v;
},
});
setTimeout(() => {
this.setSize([420, 500]);
// if(serverUrl) {
// this.widgets[3].value = serverUrl;
// }
// if(this.widgets[16].value == '.*') {
// this.widgets[16].value = generateTimestampedRandomString();
// }
// console.log(this.widgets[16].value);
}, 200)
// console.log(that);
return r;
}
nodeType.prototype.onRemoved = function () {
// 你想在节点删除时执行的操作
// console.log("22Node removed:", this);
};
this.serialize_widgets = true //需要保存参数
}
}
})