image-prompt / index.html
willian166's picture
remove auth header
14188be verified
Raw
History Blame Contribute Delete
6.49 kB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>图提词</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:#0f172a;color:#e2e8f0;display:flex;justify-content:center;padding:2rem;min-height:100vh}
.c{max-width:800px;width:100%}
h1{font-size:1.8rem;text-align:center;margin-bottom:.3rem}
.st{text-align:center;color:#94a3b8;margin-bottom:1.2rem;font-size:.9rem}
.quota{text-align:center;color:#64748b;font-size:.75rem;margin-bottom:1rem}
.quota b{color:#60a5fa}
textarea{width:100%;padding:.75rem;border-radius:10px;border:1px solid #334155;background:#1e293b;color:#e2e8f0;font-size:.95rem;min-height:200px;resize:vertical;font-family:inherit;margin-bottom:.3rem}
textarea:focus{outline:none;border-color:#60a5fa}
.note{color:#64748b;font-size:.75rem;margin-bottom:1rem;text-align:right}
.btn{background:linear-gradient(135deg,#3b82f6,#8b5cf6);color:#fff;padding:.85rem 2rem;border:none;border-radius:10px;font-size:1rem;cursor:pointer;width:100%;font-weight:600}
.btn:disabled{opacity:.4;cursor:not-allowed}
.result{background:#1e293b;border-radius:12px;padding:1.5rem;margin-top:1.5rem;display:none}
.result.show{display:block}
.result pre{white-space:pre-wrap;font-family:inherit;font-size:.9rem;line-height:1.7;overflow-x:auto}
.actions{margin-top:1rem;display:flex;gap:.5rem}
.btn-sm{padding:.5rem 1rem;border-radius:6px;border:1px solid #475569;background:#334155;color:#e2e8f0;cursor:pointer;font-size:.85rem}
.loading{text-align:center;padding:2rem;display:none}
.loading.show{display:block}
.spinner{width:36px;height:36px;border:3px solid #334155;border-top-color:#60a5fa;border-radius:50%;animation:spin .8s linear infinite;margin:0 auto 1rem}
@keyframes spin{to{transform:rotate(360deg)}}
.error{background:#7f1d1d;border:1px solid #ef4444;border-radius:10px;padding:1rem;margin-top:1rem;display:none}
.error.show{display:block}
</style>
</head>
<body>
<div class="c">
<h1>图提词</h1>
<p class="st">粘贴文案,自动生成图片提示词</p>
<p class="quota" id="quota">加载中...</p>
<textarea id="inputText" placeholder="在此粘贴纯文字文案..."></textarea>
<p class="note" id="stats"></p>
<button class="btn" id="submitBtn" onclick="go()">生成图片提示词</button>
<div class="loading" id="loading"><div class="spinner"></div><p>正在分析文案并生成提示词...</p></div>
<div class="error" id="error"></div>
<div class="result" id="result"><pre id="rc"></pre>
<div class="actions"><button class="btn-sm" onclick="navigator.clipboard.writeText(document.getElementById('rc').textContent).then(()=>alert('已复制'))">复制</button><button class="btn-sm" onclick="dl()">下载 .md</button></div></div>
</div>
<script>
var API_KEY = '';
var API_URL = 'https://image-prompt-proxy.willian166.workers.dev';
var MODEL = 'THUDM/GLM-Z1-9B-0414';
var LIMIT = 10;
var SYS="你是「图提词」,从纯文字文案生成图片提示词。\n\n流程:\n1.提取纯文本,中文<10字回复[文案过短]\n2.并行提取:主题、核心信息、场景(季节/时间/室内外)、人物/物品/氛围。情绪词优先\n3.图片数量=ceil(中文字数/50),最小1\n4.场景人物按顺序排布,只按场景类型合并(室内/室外×白天/夜晚),不用主题/动作/情感合并\n5.兜底:不熟悉术语先理解再决定,敏感内容终止\n6.逐张生成五段式:主体+动作+环境+风格+技术参数。风格独立判断:情绪>环境>季节特性\n7.自检:对应段落、五段式完整、风格独立、可生图\n8.输出格式:\n# 图片提示词 — [主题]\n## 原文\n[原文]\n---\n## 图片N\n- 画面描述:[描述]\n- 风格:[风格及判断]\n- 提示词:[完整提示词]\n\n规则:不生图、不改原文、不处理非文字、敏感停止";
function getUsage(){try{var d=JSON.parse(localStorage.getItem('ttc_usage')||'{}');var h=new Date().getHours();var k=new Date().toDateString();if(d._date!==k){return{hits:0,_date:k}}if(d._hour!==h){return{hits:0,_date:k,_hour:h}}return d}catch(e){return{hits:0}}}
function saveUsage(u){u._hour=new Date().getHours();u._date=new Date().toDateString();localStorage.setItem('ttc_usage',JSON.stringify(u))}
function updateQuota(){var u=getUsage();var left=LIMIT-u.hits;var el=document.getElementById('quota');if(left<=0){el.innerHTML='今日已用完 <b>'+LIMIT+'</b> 次额度,请下个小时再来';document.getElementById('submitBtn').disabled=true}else{el.innerHTML='本小时剩余 <b>'+left+'</b> / '+LIMIT+' 次';document.getElementById('submitBtn').disabled=false}}
document.getElementById('inputText').addEventListener('input',function(){var c=(this.value.match(/[\u4e00-\u9fff]/g)||[]).length;document.getElementById('stats').innerHTML='中文: <b>'+c+'</b> 字 &rarr; 约 <b>'+Math.max(1,Math.ceil(c/50))+'</b> 张图'});
async function go(){
var t=document.getElementById('inputText').value.trim();
if(!t)return alert('请输入文案');
var u=getUsage();
if(u.hits>=LIMIT)return alert('本小时额度已用完,请稍后再试');
var l=document.getElementById('loading'),e=document.getElementById('error'),r=document.getElementById('result'),b=document.getElementById('submitBtn');
l.classList.add('show');e.classList.remove('show');r.classList.remove('show');b.disabled=true;
try{
var resp=await fetch(API_URL+'/chat/completions?v=2',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({model:MODEL,messages:[{role:'system',content:SYS},{role:'user',content:'请处理以下文案,生成图片提示词:\n\n'+t}],temperature:.7,max_tokens:4096})});
if(!resp.ok){var er=await resp.json().catch(()=>({}));var msg=er.error?.message||er.error||'HTTP '+resp.status;if(resp.status==503)msg+=' (模型加载中,请等30秒重试)';throw new Error(msg)}
var d=await resp.json();
document.getElementById('rc').textContent=d.choices[0].message.content;
r.classList.add('show');
u.hits++;saveUsage(u);updateQuota();
}catch(ex){e.textContent='失败: '+ex.message;e.classList.add('show')}
l.classList.remove('show');b.disabled=false
}
function dl(){var t=document.getElementById('rc').textContent,n=new Date().toISOString().replace('T',' ').slice(0,19),a=document.createElement('a');a.href=URL.createObjectURL(new Blob([t],{type:'text/markdown'}));a.download=n+'.md';a.click()}
updateQuota();
</script>
</body>
</html>