cardbuddy 0.14.1 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp.js +4 -0
- package/dist/preview-editor/assets/{index-DnXqKrCc.js → index-Cm0USikc.js} +23 -23
- package/dist/preview-editor/index.html +1 -1
- package/dist/standalone.js +5 -0
- package/dist/vendored/mcp/client.mjs +6 -0
- package/dist/vendored/server/core/ai-chat.js +4 -2
- package/dist/vendored/skills/dsl-card-generator/scripts/lib/paths.mjs +21 -1
- package/dist/vendored/skills/dsl-card-generator/scripts/lib/paths.py +23 -0
- package/dist/vendored/skills/dsl-card-generator/scripts/route_input.mjs +18 -13
- package/dist/vendored/skills/dsl-card-generator/scripts/slices_normalize.mjs +4 -5
- package/dist/vendored/skills/shared/finmall-config.mjs +11 -1
- package/dist/vendored/skills/sketch-spec-to-card/SKILL.md +1 -1
- package/dist/vendored/skills/sketch-spec-to-card/scripts/build_prompt.py +7 -2
- package/dist/vendored/skills/sketch-spec-to-card/scripts/parse_meaxure.py +14 -7
- package/package.json +3 -3
|
@@ -264,31 +264,31 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
264
264
|
`+u),Ae&&(u=jt(u)),T&&M?ne(u):u},t.setConfig=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};mt(e),Ne=!0,Pe=be,Fe=A},t.clearConfig=function(){dt=null,Ne=!1,Pe=null,Fe=null,T=D,E=``},t.isValidAttribute=function(e,t,n){dt||mt({});let r=ut(e),i=ut(t);return Ut(r,i,n)},t.addHook=function(e,t){typeof t==`function`&&bE(k,e)&&sE(k[e],t)},t.removeHook=function(e,t){if(bE(k,e)){if(t!==void 0){let n=aE(k[e],t);return n===-1?void 0:cE(k[e],n,1)[0]}return oE(k[e])}},t.removeHooks=function(e){bE(k,e)&&(k[e]=[])},t.removeAllHooks=function(){k=cD()},t}var fD=dD();(function(e){var t=`\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b`,n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:`punctuation`,inside:null},r={bash:n,environment:{pattern:RegExp(`\\$`+t),alias:`constant`},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp(`(\\{)`+t),lookbehind:!0,alias:`constant`}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:`important`},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:`function`},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:`function`}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:`variable`,lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp(`(^|[\\s;|&]|[<>]\\()`+t),lookbehind:!0,alias:`constant`}},alias:`variable`,lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:`variable`,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp(`\\$?`+t),alias:`constant`},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:`class-name`},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:`important`},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:`important`}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var i=[`comment`,`function-name`,`for-or-select`,`assign-left`,`parameter`,`string`,`environment`,`function`,`keyword`,`builtin`,`boolean`,`file-descriptor`,`operator`,`punctuation`,`number`],a=r.variable[1].inside,o=0;o<i.length;o++)a[i[o]]=e.languages.bash[i[o]];e.languages.sh=e.languages.bash,e.languages.shell=e.languages.bash})(Prism),(function(e){e.languages.typescript=e.languages.extend(`javascript`,{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript[`literal-property`];var t=e.languages.extend(`typescript`,{});delete t[`class-name`],e.languages.typescript[`class-name`].inside=t,e.languages.insertBefore(`typescript`,`function`,{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:`operator`},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:`class-name`,inside:t}}}}),e.languages.ts=e.languages.typescript})(Prism),(function(e){var t=e.util.clone(e.languages.javascript),n=`(?:\\s|\\/\\/.*(?!.)|\\/\\*(?:[^*]|\\*(?!\\/))\\*\\/)`,r=`(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})`,i=`(?:\\{<S>*\\.{3}(?:[^{}]|<BRACES>)*\\})`;function a(e,t){return e=e.replace(/<S>/g,function(){return n}).replace(/<BRACES>/g,function(){return r}).replace(/<SPREAD>/g,function(){return i}),RegExp(e,t)}i=a(i).source,e.languages.jsx=e.languages.extend(`markup`,t),e.languages.jsx.tag.pattern=a(`<\\/?(?:[\\w.:-]+(?:<S>+(?:[\\w.:$-]+(?:=(?:"(?:\\\\[\\s\\S]|[^\\\\"])*"|'(?:\\\\[\\s\\S]|[^\\\\'])*'|[^\\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\\/?)?>`),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside[`attr-value`].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside[`class-name`]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore(`inside`,`attr-name`,{spread:{pattern:a(`<SPREAD>`),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore(`inside`,`special-attr`,{script:{pattern:a(`=<BRACES>`),alias:`language-javascript`,inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:`punctuation`},rest:e.languages.jsx}}},e.languages.jsx.tag);var o=function(e){return e?typeof e==`string`?e:typeof e.content==`string`?e.content:e.content.map(o).join(``):``},s=function(t){for(var n=[],r=0;r<t.length;r++){var i=t[r],a=!1;if(typeof i!=`string`&&(i.type===`tag`&&i.content[0]&&i.content[0].type===`tag`?i.content[0].content[0].content===`</`?n.length>0&&n[n.length-1].tagName===o(i.content[0].content[1])&&n.pop():i.content[i.content.length-1].content===`/>`||n.push({tagName:o(i.content[0].content[1]),openedBraces:0}):n.length>0&&i.type===`punctuation`&&i.content===`{`?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&i.type===`punctuation`&&i.content===`}`?n[n.length-1].openedBraces--:a=!0),(a||typeof i==`string`)&&n.length>0&&n[n.length-1].openedBraces===0){var c=o(i);r<t.length-1&&(typeof t[r+1]==`string`||t[r+1].type===`plain-text`)&&(c+=o(t[r+1]),t.splice(r+1,1)),r>0&&(typeof t[r-1]==`string`||t[r-1].type===`plain-text`)&&(c=o(t[r-1])+c,t.splice(r-1,1),r--),t[r]=new e.Token(`plain-text`,c,null,c)}i.content&&typeof i.content!=`string`&&s(i.content)}};e.hooks.add(`after-tokenize`,function(e){(e.language===`jsx`||e.language===`tsx`)&&s(e.tokens)})})(Prism),zT.setOptions({gfm:!0,breaks:!0}),fD.addHook(`afterSanitizeAttributes`,e=>{e.tagName===`A`&&e.getAttribute(`href`)&&(e.setAttribute(`target`,`_blank`),e.setAttribute(`rel`,`noopener noreferrer`)),e.tagName===`IMG`&&(e.setAttribute(`loading`,`lazy`),e.setAttribute(`decoding`,`async`))});var pD={js:`javascript`,mjs:`javascript`,cjs:`javascript`,node:`javascript`,ts:`typescript`,sh:`bash`,shell:`bash`,zsh:`bash`,console:`bash`,html:`markup`,vue:`markup`,xml:`markup`,svg:`markup`,jsonc:`json`,json5:`json`,py:`python`,yml:`yaml`};function mD(e){let t=String(e||``).trim().toLowerCase();if(!t)return``;let n=pD[t]||t;return Yg.default.languages[n]?n:``}function hD(e){let t=String(e??``);if(!t.trim())return``;let n=``;try{n=zT.parse(t)}catch{n=`<p>${t.replace(/[&<>]/g,e=>({"&":`&`,"<":`<`,">":`>`})[e])}</p>`}return fD.sanitize(n,{ADD_ATTR:[`target`,`rel`]})}function gD(e){if(!(!e||!e.querySelectorAll))for(let t of e.querySelectorAll(`pre`)){let e=t.querySelector(`code`);if(!e)continue;let n=mD((e.className.match(/language-([\w+-]+)/)||[])[1]||``);if(n&&e.className.indexOf(`language-`)<0&&(e.className=`language-${n}`),n&&!e.dataset.mdHighlighted){try{Yg.default.highlightElement(e)}catch{}e.dataset.mdHighlighted=`1`}if(t.dataset.mdCode)continue;t.dataset.mdCode=`1`;let r=document.createElement(`div`);r.className=`md-code`;let i=document.createElement(`div`);i.className=`md-code__bar`;let a=document.createElement(`span`);a.className=`md-code__lang`,a.textContent=n||`text`;let o=document.createElement(`button`);o.type=`button`,o.className=`md-code__copy`,o.textContent=`复制`,o.addEventListener(`click`,async()=>{await op(e.textContent||``)?(o.textContent=`已复制`,o.classList.add(`is-ok`)):o.textContent=`复制失败`,setTimeout(()=>{o.textContent=`复制`,o.classList.remove(`is-ok`)},1600)}),i.append(a,o),t.parentNode?.insertBefore(r,t),r.append(i,t)}}function _D(e){if(!(!e||!e.querySelectorAll))for(let t of e.querySelectorAll(`pre code[data-md-highlighted]`))delete t.dataset.mdHighlighted}function vD(e){return e?e.nodeType===3?!e.textContent.trim():e.nodeType===1&&e.tagName===`BR`:!1}function yD(e){return e.length>1?`${e.length} 张图像`:(e[0].getAttribute(`alt`)||``).trim()||`1 张图像`}function bD(e){let t=document.createElement(`div`);t.className=`md-imggroup`,t.dataset.mdImggroup=`1`;let n=document.createElement(`button`);n.type=`button`,n.className=`md-imggroup__head`,n.setAttribute(`aria-expanded`,`false`),n.innerHTML=`<svg class="md-imggroup__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-images" /></svg><span class="md-imggroup__label"></span><svg class="md-imggroup__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><use href="#icon-chevron-right" /></svg>`,n.querySelector(`.md-imggroup__label`).textContent=yD(e);let r=document.createElement(`div`);return r.className=`md-imggroup__body`,r.hidden=!0,n.addEventListener(`click`,()=>{let e=r.hidden;r.hidden=!e,t.classList.toggle(`is-open`,e),n.setAttribute(`aria-expanded`,e?`true`:`false`)}),t.append(n,r),{group:t,body:r}}var xD=3;function SD(e){if(!(!e||!e.querySelectorAll))for(let t of e.querySelectorAll(`img`)){if(t.closest(`[data-md-imggroup]`))continue;let e=[t],n=t.nextSibling;for(;n;){if(vD(n)){n=n.nextSibling;continue}if(n.tagName===`IMG`&&!n.closest(`[data-md-imggroup]`)){e.push(n),n=n.nextSibling;continue}break}if(e.length<xD)continue;let{group:r,body:i}=bD(e);t.parentNode.insertBefore(r,t);for(let t of e)i.append(t)}}var CD={name:`MarkdownBody`,props:{source:{type:String,default:``},streaming:{type:Boolean,default:!1}},data(){return{html:``,_raf:0}},watch:{source:{immediate:!0,handler(){this.scheduleRender()}},streaming(e){e||this.renderNow()}},beforeUnmount(){this._raf&&cancelAnimationFrame(this._raf),this._raf=0},methods:{scheduleRender(){if(!this.streaming){this.renderNow();return}this._raf||=requestAnimationFrame(()=>{this._raf=0,this.renderNow()})},renderNow(){this._raf&&=(cancelAnimationFrame(this._raf),0),this.html=hD(this.source),this.$nextTick(()=>{let e=this.$refs.bodyEl;e&&(_D(e),gD(e),SD(e))})}}},wD=[`innerHTML`];function TD(e,t,n,r,i,a){return B(),V(z,null,[K(` 模型输出经 marked 解析 + DOMPurify 消毒后注入;代码块由 enhanceCodeBlocks 补高亮与复制按钮 `),U(`div`,{ref:`bodyEl`,class:`md-body`,innerHTML:i.html},null,8,wD)],2112)}var ED=X(CD,[[`render`,TD],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/MarkdownBody.vue`]]),DD={card_list:`列出卡片`,card_read:`读取卡片`,card_write:`写入卡片`,card_validate:`校验卡片`,card_render_status:`渲染状态`,card_node_models:`组件模型`,card_screenshot:`截图预览`,card_sync:`同步远端卡片`,card_save:`推送到远端`,card_slice_upload:`上传切图`,card_import_meta:`来源侧车`,card_route_input:`输入路由`,card_scaffold:`生成骨架`,card_add_component:`添加组件`,card_history:`编辑历史`,card_rollback:`回滚版本`,skill_read:`读技能文档`,skill_exec:`跑技能脚本`,card_grep:`定位卡片字段`,card_patch:`最小改写卡片`,fs_read:`读文件`,fs_list:`列目录`,fs_write:`写草稿文件`,fs_copy:`复制文件`,shell_exec:`本地命令`};function OD(e){return DD[e]||e||`工具`}function kD(e){let t=e&&e.args||{};return`${typeof t.script==`string`?t.script:``} ${Array.isArray(t.args)?t.args.join(` `):typeof t.command==`string`?t.command:``} ${typeof t.name==`string`?t.name:``}`.toLowerCase()}var AD=[{order:6,id:`S6`,label:`收尾门禁`,hit:(e,t)=>/check_fidelity/.test(t)||/iterate/.test(t)&&/--gate/.test(t)},{order:5,id:`S5`,label:`像素自循环`,hit:(e,t)=>/iterate|diff_bands/.test(t)||e===`card_screenshot`},{order:4,id:`S4`,label:`组件填充`,hit:e=>e===`card_add_component`||e===`card_patch`||e===`card_write`},{order:3,id:`S3`,label:`骨架落盘`,hit:(e,t)=>e===`card_scaffold`||/expand_ir/.test(t)||e===`fs_write`&&/\.ir\.json/.test(t)},{order:2,id:`S2`,label:`设计稿审计`,hit:(e,t)=>/spec_tree|sketch_spec|design_sample|audit_|slice_/.test(t)},{order:1,id:`S1`,label:`输入路由`,hit:e=>e===`card_route_input`}];function jD(e){let t=Math.max(0,Math.round(Number(e||0)/1e3));if(t<60)return`${t} 秒`;let n=Math.floor(t/60);return n<60?`${n} 分 ${t%60} 秒`:`${Math.floor(n/60)} 小时 ${n%60} 分`}function MD(e){let t=Number(e||0);if(!t)return``;let n=new Date(t),r=e=>String(e).padStart(2,`0`);return`${r(n.getHours())}:${r(n.getMinutes())}:${r(n.getSeconds())}`}function ND(e){let t=Number(e||0);return t>0?`+${jD(t)}`:``}function PD(e,t=0){let n=Number(e&&e.startedAt)||0;if(!n)return 0;let r=Number(e&&e.ms)||0;if(r>0)return n+r;let i=Number(t)||0;return i>n?i:0}function FD(e){let t=e&&e.toolName||``,n=kD(e);for(let e of AD)if(e.hit(t,n))return e;return null}var ID=new Set([`card_write`,`card_patch`,`card_scaffold`,`card_add_component`,`fs_write`,`fs_copy`,`card_save`,`card_sync`,`card_slice_upload`]),LD=new Set([`card_read`,`card_list`,`card_node_models`,`card_grep`,`card_history`,`card_validate`,`card_render_status`,`fs_read`,`fs_list`,`skill_read`]);function RD(e){let t=e&&e.toolName||``;return e&&e.error||ID.has(t)||t===`skill_exec`||t===`shell_exec`||t===`card_screenshot`?!0:!LD.has(t)}function zD(e){if(e==null||e===``)return null;if(typeof e==`object`)return e;let t=String(e);try{return JSON.parse(t)}catch{}let n=t.indexOf(`{`),r=t.lastIndexOf(`}`);if(n>=0&&r>n)try{return JSON.parse(t.slice(n,r+1))}catch{return null}return null}function BD(e){let t=kD(e);if(!/--gate|check_fidelity/.test(t))return null;let n=zD(e&&e.result),r=n&&typeof n==`object`?n.gate:null;if(r&&typeof r.passed==`boolean`)return{passed:r.passed,verdict:String(r.verdict||``)};let i=String(e&&e.result||``);if(!/"passed"\s*:/.test(i))return null;let a=/"passed"\s*:\s*(true|false)/.exec(i),o=/"verdict"\s*:\s*"((?:[^"\\]|\\.)*)"/.exec(i);return a?{passed:a[1]===`true`,verdict:o?o[1].replace(/\\n/g,` `):``}:null}var VD=/\s#([^\s#]+)\s*$/;function HD(e){let t=String(e??``),n=VD.exec(t);return n?{text:t.slice(0,n.index).trim(),cid:n[1]}:{text:t,cid:``}}var UD=12;function WD(e){let t=e&&e.toolName||``,n=zD(e&&e.result);if(!n||typeof n!=`object`)return null;let r=t===`card_validate`?n:n.verify&&n.verify.validate;if(!r||typeof r!=`object`||!Array.isArray(r.errors))return null;let i=Array.isArray(r.warnings)?r.warnings:[],a=[...r.errors.map(e=>({level:`error`,...HD(e)})),...i.map(e=>({level:`warn`,...HD(e)}))].slice(0,UD);return{ok:r.ok!==!1&&r.errors.length===0,errors:r.errors.length,warnings:i.length,issues:a}}function GD(e){let t=Array.isArray(e)?e:[],n=0,r=0,i=0,a=0,o=null,s=null;for(let e of t){e.error&&a++,ID.has(e.toolName)&&(e.error?r++:n++),e.toolName===`card_screenshot`&&!e.error&&i++;let t=WD(e);t&&(o=t);let c=BD(e);c&&(s=c)}return{total:t.length,writes:n,writeFails:r,shots:i,failed:a,validate:o,gate:s}}var KD={length:`单次输出上限截断:调高「单次输出上限」,或要求 AI 走紧凑 IR 路线(fs_write 写 IR → expand_ir 展开)`,stall:`上游长时间静默:多为网关 / 网络抖动。上下文与已落盘产物都在,重试本轮即可接着做`,empty:`网关连续返回空响应:重试本轮,或检查网关额度 / 换个时间段`,context:`上下文超出网关窗口:后端已自动压缩重试仍失败,建议新开一轮或清理对话记录`,network:`连不上网关:检查网络与 Base URL 后重试本轮`,"rate-limit":`网关限流或额度不足:稍后重试,或换一个 API Key`,auth:`API Key 无效或权限不足:到设置里更新 Key 再重试`,"wrap-failed":`熔断收尾的进度汇总也没拿到:上下文已保留,回复「继续」接着做`,aborted:`本轮已中止:已执行的写入都保留,可从中断处继续`,unknown:`未归类的失败:复制错误原文排查,或换个说法重试本轮`};function qD(e){return{hint:KD[e]||``,action:e===`length`||e===`auth`?`settings`:e===`wrap-failed`||e===`aborted`?`continue`:`retry`}}var JD={name:`ChatToolRow`,components:{MarkdownBody:ED},props:{tc:{type:Object,required:!0},turnTs:{type:Number,default:0},nowTs:{type:Number,default:0}},emits:[`approval`],data(){return{opened:null}},computed:{state(){return this.tc.error?`error`:this.tc.result!==void 0&&this.tc.result!==null?`done`:this.tc.pending?`pending`:`running`},open(){return this.opened===null?!!this.tc.error:this.opened},msText(){let e=this.tc.ms;return e?e<1e3?`${e}ms`:`${(e/1e3).toFixed(1)}s`:``},stampText(){return MD(this.tc.startedAt)},cumText(){let e=PD(this.tc,this.nowTs);return e&&this.turnTs?ND(e-this.turnTs):``},clockText(){return[this.stampText,this.cumText].filter(Boolean).join(` · `)},clockTitle(){let e=[];return this.stampText&&e.push(`开始于 ${this.stampText}`),this.cumText&&e.push(`距本轮开始 ${this.cumText.slice(1)}`),this.msText&&e.push(`本步耗时 ${this.msText}`),e.join(` · `)},approvalCommand(){if(this.tc.command)return String(this.tc.command);let e=this.tc.args||{};return typeof e.command==`string`&&e.command?e.command:this.tc.toolName===`skill_exec`?[e.script,Array.isArray(e.args)?e.args.join(` `):``].filter(Boolean).join(` `):JSON.stringify(e)},argSummary(){if(this.tc.toolName===`skill_exec`&&this.tc.args?.script){let e=Array.isArray(this.tc.args.args)?this.tc.args.args.join(` `):``,t=[String(this.tc.args.script).replace(/^skills\//,``),e].filter(Boolean).join(` `);return t.length>96?`${t.slice(0,96)}…`:t}let e=this.tc.args||{},t=[];for(let[n,r]of Object.entries(e)){if(r==null||r===``)continue;let e=typeof r==`object`?JSON.stringify(r):String(r);if(t.push(`${n}=${e.length>28?`${e.slice(0,28)}…`:e}`),t.join(` `).length>56)break}let n=t.join(` `);return n.length>72?`${n.slice(0,72)}…`:n},argsSource(){let e=this.tc.args||{};if(!Object.keys(e).length)return``;let t=``;try{t=JSON.stringify(e,null,2)}catch{t=String(e)}return`\`\`\`json\n${t}\n\`\`\``},resultSource(){let e=this.tc.result;if(e==null||e===``)return``;let t=typeof e==`string`?e:JSON.stringify(e);try{t=JSON.stringify(JSON.parse(t),null,2)}catch{}t.length>4e3&&(t=`${t.slice(0,4e3)}\n…(已截断)`);let n=`\`\`\`json\n${t}\n\`\`\``;return this.tc.truncated?`${n}\n\n> 结果过长,面板只显示前 4000 字;喂给模型的上下文另有额度,不受此限。`:n}},methods:{toolLabel:OD,toggle(){this.opened=!this.open}}},YD=[`aria-expanded`],XD={key:0,class:`aitool__spin`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},ZD={key:1,class:`aitool__status`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},QD={key:2,class:`aitool__status`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},$D={class:`aitool__name`},eO={class:`aitool__args`},tO=[`title`],nO=[`title`],rO={key:0,class:`aitool__approve`},iO=[`title`],aO={class:`aitool__approve-hint`},oO={class:`aitool__approve-hint`},sO=[`title`],cO={class:`aitool__body`},lO=[`src`],uO={key:2,class:`aitool__error`};function dO(e,t,n,r,i,a){let o=L(`MarkdownBody`);return B(),V(z,null,[K(` 单次工具调用:一行摘要,可展开看参数 / 结果 / 截图。
|
|
265
265
|
抽成独立组件的原因:ChatMessage 要把「连续同名调用」折叠成分组行,
|
|
266
266
|
分组展开后的成员行与平铺行走的是同一份标记,复制两遍必然漂移 `),U(`div`,{class:j([`aitool`,[`aitool--${a.state}`,{"is-open":a.open}]])},[U(`button`,{type:`button`,class:`aitool__head`,"aria-expanded":a.open?`true`:`false`,onClick:t[0]||=(...e)=>a.toggle&&a.toggle(...e)},[t[7]||=U(`svg`,{class:`aitool__chev`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron-right`})],-1),a.state===`running`||a.state===`pending`?(B(),V(`svg`,XD,[...t[4]||=[U(`use`,{href:`#icon-loading`},null,-1)]])):a.state===`error`?(B(),V(`svg`,ZD,[...t[5]||=[U(`use`,{href:`#icon-alert-triangle`},null,-1)]])):(B(),V(`svg`,QD,[...t[6]||=[U(`use`,{href:`#icon-check`},null,-1)]])),U(`span`,$D,M(a.toolLabel(n.tc.toolName)),1),U(`code`,eO,M(n.tc.pending?`参数生成中…`:a.argSummary),1),K(` 时间三件套:这一步什么时候开始(墙钟)· 距回合起点多久(累计)· 自身耗时。
|
|
267
|
-
长任务里「卡在哪一步、卡了多久」全靠这三个数互相对齐 `),a.clockText?(B(),V(`span`,{key:3,class:`aitool__clock`,title:a.clockTitle},M(a.clockText),9,tO)):K(`v-if`,!0),a.msText?(B(),V(`span`,{key:4,class:`aitool__ms`,title:`本步耗时 ${a.msText}`},M(a.msText),9,nO)):K(`v-if`,!0)],8,YD),K(` 高危执行逐次确认:命令原文 + 允许一次 / 本回合不再询问 / 拒绝(Codex 审批的同款交互) `),n.tc.needsApproval?(B(),V(`div`,rO,[t[8]||=U(`svg`,{class:`aitool__approve-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`code`,{class:`aitool__approve-cmd`,title:a.approvalCommand},M(a.approvalCommand),9,iO),U(`span`,aO,M(n.tc.toolName===`skill_exec`?`技能脚本,需要你确认`:`本地命令,需要你确认`),1),U(`button`,{type:`button`,class:`aitool__approve-btn`,onClick:t[1]||=q(t=>e.$emit(`approval`,{tc:n.tc,ok:!0,scope:`once`}),[`stop`])},`允许一次`),U(`button`,{type:`button`,class:`aitool__approve-btn aitool__approve-btn--ghost`,onClick:t[2]||=q(t=>e.$emit(`approval`,{tc:n.tc,ok:!0,scope:`turn`}),[`stop`])},`本回合不再询问`),U(`button`,{type:`button`,class:`aitool__approve-btn aitool__approve-btn--deny`,onClick:t[3]||=q(t=>e.$emit(`approval`,{tc:n.tc,ok:!1}),[`stop`])},`拒绝`)])):n.tc.approvalNote?(B(),V(z,{key:1},[K(` 免确认策略命中:没有审批条,但照样把「跑了什么命令」摆出来,免确认不等于无痕迹 `),U(`div`,{class:j([`aitool__approve-note`,{"is-auto":n.tc.autoApproved}])},[U(`span`,oO,M(n.tc.approvalNote),1),n.tc.autoApproved&&n.tc.command?(B(),V(`code`,{key:0,class:`aitool__approve-cmd`,title:n.tc.command},M(n.tc.command),9,sO)):K(`v-if`,!0)],2)],2112)):K(`v-if`,!0),I(U(`div`,cO,[a.argsSource?(B(),H(o,{key:0,source:a.argsSource},null,8,[`source`])):K(`v-if`,!0),n.tc.image?(B(),V(`img`,{key:1,class:`aitool__shot`,src:`data:${n.tc.image.mime||`image/png`};base64,${n.tc.image.base64}`,alt:`卡片截图`},null,8,lO)):K(`v-if`,!0),n.tc.error?(B(),V(`div`,uO,M(n.tc.error),1)):a.resultSource?(B(),H(o,{key:3,source:a.resultSource},null,8,[`source`])):K(`v-if`,!0)],512),[[Sc,a.open]])],2)],2112)}var fO=X(JD,[[`render`,dO],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatToolRow.vue`]]);function pO(e){return`${Fl()||``}/__ai/fs/raw?path=${encodeURIComponent(e)}`}async function mO(e){let t=await e.json().catch(()=>({}));if(!e.ok){let n=``;try{n=new URL(e.url).pathname}catch{}let r=(e.status===404||e.status===405)&&n.startsWith(`/__ai/`)?`本地开发服务仍在运行改造前的旧代码(缺少该接口),请重启 npm run dev(cardbuddy)后重试`:t.message||t.error||`HTTP ${e.status}`,i=Error(r);throw i.code=t.error,i.payload=t,i}return t}async function hO(e=!1){return mO(await J(`/__ai/config${e?`?reveal=1`:``}`))}async function gO(e){return mO(await J(`/__ai/config`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}))}async function _O(){return mO(await J(`/__ai/models`))}async function vO(){return mO(await J(`/__ai/cc-switch-providers`))}async function yO(e,t=!1){return mO(await J(`/__ai/models/${encodeURIComponent(e)}${t?`?reveal=1`:``}`))}async function bO(e){return mO(await J(`/__ai/models`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}))}async function xO(e,t){return mO(await J(`/__ai/models/${encodeURIComponent(e)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}))}async function SO(e){return mO(await J(`/__ai/models/${encodeURIComponent(e)}`,{method:`DELETE`}))}async function CO(e){return mO(await J(`/__ai/models/${encodeURIComponent(e)}/activate`,{method:`POST`}))}async function wO(e={}){let{baseUrl:t=``,apiKey:n=``,model:r=``}=e||{};return mO(await J(`/__ai/probe-maxtokens`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({baseUrl:t,apiKey:n,model:r})}))}async function TO(e){return mO(await J(`/__ai/ping`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}))}async function EO(e=`image`){return mO(await J(`/__ai/fs/pick`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({kind:e,multiple:!0})}))}async function DO(e){return mO(await J(`/__ai/fs/stat?path=${encodeURIComponent(e)}`))}async function OO({name:e,relPath:t,size:n}){return mO(await J(`/__ai/fs/locate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:e,relPath:t,size:n})}))}async function
|
|
268
|
-
`);i=n.pop()||``;for(let e of n){let n=e.trim();if(!n.startsWith(`data:`))continue;let r=n.slice(5).trim();if(!r)continue;let i;try{i=JSON.parse(r)}catch{continue}if(t(i)===!0)return!0}return!1};try{for(;;){let{done:e,value:t}=await n.read();if(e||a(r.decode(t,{stream:!0})))break}a(r.decode())}finally{try{n.releaseLock?.()}catch{}}}async function
|
|
269
|
-
`).map(e=>{if(
|
|
270
|
-
`)}var
|
|
271
|
-
`).map(e=>e.trim()).filter(Boolean),t=e[e.length-1]||``;return t.length>72?`${t.slice(0,72)}…`:t}},watch:{streaming:{immediate:!0,handler(e){e?this.startTick():this.stopTick()}},thinking(e){e||this.stopTick()}},beforeUnmount(){this.stopTick()},updated(){let e=this.$refs.thinkPre;e&&this.thinkOpen&&this.thinking&&(e.scrollTop=e.scrollHeight)},methods:{startTick(){this.stopTick(),this.elapsed=0,this._tick=setInterval(()=>{this.elapsed+=250},250)},stopTick(){this._tick&&clearInterval(this._tick),this._tick=0},fmtStamp:MD,fmtClock:jD,evOff(e){let t=Number(e&&e.ts)||0;return t>this.msgTs?ND(t-this.msgTs):``},groupClock(e){let t=PD(e[e.length-1],this.nowTs),n=t>this.msgTs?ND(t-this.msgTs):``;return[MD(e[0]&&e[0].startedAt),n].filter(Boolean).join(` · `)},fileUrl(e){return pO(e)},attSub(e){return e.exists===!1?`路径不可读`:e.isDir?`${e.entryCount??e.entries?.length??0} 项`:this.formatSize(e.size)},formatSize(e){let t=Number(e||0);return t?t<1024?`${t} B`:t<1048576?`${(t/1024).toFixed(1)} KB`:`${(t/1024/1024).toFixed(1)} MB`:`0 B`},toolLabel:OD,msText(e){let t=Number(e)||0;return t?t<1e3?`${t}ms`:`${(t/1e3).toFixed(1)}s`:``},groupOpen(e){let t=this.openGroups[e.key];if(t!==void 0)return t;if(e.failed)return!0;let n=e.rows[e.rows.length-1];return!!(n&&n.result===void 0&&!n.error)},toggleGroup(e){this.openGroups={...this.openGroups,[e.key]:!this.groupOpen(e)}},onApproval(e){this.$emit(`approval`,e)},async copyError(){await op(`${this.msg.errorCode?`[${this.msg.errorCode}] `:``}${String(this.msg.error||``)}`)&&(this.errorCopied=!0,setTimeout(()=>{this.errorCopied=!1},1600))},async copyText(){await op(String(this.msg.content||``))&&(this.copied=!0,setTimeout(()=>{this.copied=!1},1600))}}},
|
|
272
|
-
行标记抽到 ChatToolRow:分组内成员与平铺行走同一份模板,两处不会漂移 `),(B(!0),V(z,null,R(a.toolGroups,e=>(B(),V(z,{key:e.key},[e.kind===`row`?(B(),H(o,{key:0,tc:e.tc,"turn-ts":a.msgTs,"now-ts":n.nowTs,onApproval:a.onApproval},null,8,[`tc`,`turn-ts`,`now-ts`,`onApproval`])):(B(),V(`div`,{key:1,class:j([`aitool aitool--group`,[e.failed?`aitool--error`:`aitool--done`,{"is-open":a.groupOpen(e)}]])},[U(`button`,{type:`button`,class:`aitool__head`,"aria-expanded":a.groupOpen(e)?`true`:`false`,onClick:t=>a.toggleGroup(e)},[t[16]||=U(`svg`,{class:`aitool__chev`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron-right`})],-1),(B(),V(`svg`,
|
|
273
|
-
「上下文折叠过几次 / 自动续跑过几次 / 网关重试过没有」这些线索全靠这里留存 `),a.events.length?(B(),V(`div`,{key:3,class:j([`aiev`,{"is-open":a.eventsExpanded}])},[U(`button`,{type:`button`,class:`aiev__head`,"aria-expanded":a.eventsExpanded?`true`:`false`,onClick:t[2]||=e=>i.eventsOpen=!a.eventsExpanded},[t[18]||=U(`svg`,{class:`aiev__chev`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron-right`})],-1),(B(),V(`svg`,
|
|
274
|
-
所以重开面板、刷新之后这条摘要依然在,而不是只在当轮可见 `),a.showSummary?(B(),V(`div`,
|
|
275
|
-
组件结构里选中那个节点——不用再照着一句 "at depth 1[0]" 自己去树里翻 `),a.validateIssues.length?(B(),V(`div`,
|
|
276
|
-
此前只有熔断收尾(budget)分支有按钮,手滑终止后用户只能自己打字 `),n.msg.status===`aborted`?(B(),V(`div`,Xk,[t[24]||=U(`span`,{class:`aimsg__aborted-text`},`已终止生成`,-1),a.turnClock.endStamp?(B(),V(`span`,Zk,M(a.turnClock.endStamp)+` 终止 · 已用 `+M(a.turnClock.total),1)):K(`v-if`,!0),n.canRegenerate&&!n.streaming?(B(),V(`button`,{key:1,type:`button`,class:`aimsg__budget-go`,onClick:t[8]||=t=>e.$emit(`continue`)},`从中断处继续`)):K(`v-if`,!0)])):n.msg.budget?.message?(B(),V(`div`,{key:8,class:`aimsg__budget`,title:a.budgetHint},[t[25]||=U(`svg`,{class:`aimsg__budget-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`span`,$k,[U(`strong`,null,M(a.budgetLabel),1),G(`:`+M(n.msg.budget.message)+`(上下文已保留)`,1)]),n.canRegenerate&&!n.streaming?(B(),V(`button`,{key:0,type:`button`,class:`aimsg__budget-go`,onClick:t[9]||=t=>e.$emit(`continue`)},`继续这轮`)):K(`v-if`,!0)],8,Qk)):K(`v-if`,!0),K(` 悬停操作:复制 / 重新生成(仅最后一条助手消息可重发) `),n.msg.content||n.msg.error?(B(),V(`footer`,eA,[U(`button`,{type:`button`,class:`aimsg__act`,title:i.copied?`已复制`:`复制回答`,onClick:t[10]||=(...e)=>a.copyText&&a.copyText(...e)},[(B(),V(`svg`,nA,[U(`use`,{href:i.copied?`#icon-check`:`#icon-copy-sm`},null,8,rA)])),U(`span`,null,M(i.copied?`已复制`:`复制`),1)],8,tA),n.canRegenerate&&!n.streaming?(B(),V(`button`,{key:0,type:`button`,class:`aimsg__act`,title:`丢弃这次回答并重新生成`,onClick:t[11]||=t=>e.$emit(`regenerate`,n.msg)},[...t[26]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-reset`})],-1),U(`span`,null,`重新生成`,-1)]])):K(`v-if`,!0)])):K(`v-if`,!0)],64))],2)}var aA=X(XO,[[`render`,iA],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatMessage.vue`]]),oA=106,sA=.5,cA=`cardbuddy:ai-composer-height`,lA={name:`ChatComposer`,props:{busy:{type:Boolean,default:!1},model:{type:String,default:``},attachments:{type:Array,default:()=>[]},placeholder:{type:String,default:`描述你要改的卡片,Enter 发送 / Shift+Enter 换行`},context:{type:Object,default:null}},emits:[`send`,`stop`,`pick`,`add-path`,`remove-attachment`,`drop-files`,`paste-image`,`escape`],data(){return{text:``,attachOpen:!1,pathInputOpen:!1,pathText:``,dragOver:!1,heightPx:0,resizing:!1,compArmed:!1,_compTimer:null,_outside:null,_onWinResize:null}},computed:{canSend(){return!!(this.text.trim()||this.attachments.some(e=>!e.pending&&e.exists!==!1))},compStyle(){return this.heightPx>0?{height:`${this.heightPx}px`}:null},ctx(){let e=this.context;if(!e)return null;let t=Number(e.window)>0?Number(e.window):Number(e.total)>0?Number(e.total):0,n=Math.max(0,Number(e.used)||0);if(!(t>0))return null;let r=Math.min(1,n/t),i=2*Math.PI*8;return{pct:r,arc:(i*r).toFixed(2),circ:i.toFixed(2),pctLabel:`${Math.round(r*100)}%`,level:r>=.85?`danger`:r>=.6?`warn`:`ok`,used:n,total:t}},ctxTitle(){let e=this.ctx;if(!e)return``;let t=e=>e>=1e3?`${(e/1e3).toFixed(1)}k`:String(Math.round(e)),n=Number(this.context?.window)>0?` · 网关窗口 ${t(Number(this.context.window))}`:``;return`上下文占用 ${t(e.used)} / ${t(e.total)} token(${e.pctLabel})${n};接近上限时后端会自动折叠早期工具结果`}},mounted(){this._outside=e=>{let t=this.$refs.attachEl;t&&!t.contains(e.target)&&(this.attachOpen=!1)},document.addEventListener(`mousedown`,this._outside),this.loadHeight(),this._onWinResize=()=>this.clampHeight(),window.addEventListener(`resize`,this._onWinResize),this.autoGrow()},beforeUnmount(){this._outside&&document.removeEventListener(`mousedown`,this._outside),this._onWinResize&&window.removeEventListener(`resize`,this._onWinResize)},methods:{focus(){this.$nextTick(()=>this.$refs.taEl?.focus())},setText(e){this.text=e,this.focus(),this.autoGrow()},fileUrl(e){return pO(e)},chipSub(e){if(e.exists===!1)return`不可读`;if(e.isDir)return`${e.entryCount??e.entries?.length??0} 项`;let t=Number(e.size||0);return t?t<1024?`${t} B`:t<1048576?`${(t/1024).toFixed(0)} KB`:`${(t/1024/1024).toFixed(1)} MB`:``},autoGrow(){let e=this.$refs.taEl;if(e){if(this.heightPx>0){e.style.height=``;return}e.style.height=`auto`,e.style.height=`${Math.min(e.scrollHeight,168)}px`}},heightLimits(){let e=this.$el?.closest(`.aichat`)?.clientHeight||window.innerHeight;return{min:oA,max:Math.max(oA,Math.floor(e*sA))}},clampHeight(){if(!this.heightPx)return;let{min:e,max:t}=this.heightLimits();this.heightPx=Math.max(e,Math.min(t,this.heightPx))},loadHeight(){try{let e=localStorage.getItem(cA),t=e==null?0:parseInt(e,10);!Number.isNaN(t)&&t>=oA&&(this.heightPx=t)}catch{}this.clampHeight()},saveHeight(){try{this.heightPx?localStorage.setItem(cA,String(Math.round(this.heightPx))):localStorage.removeItem(cA)}catch{}},armComp(){clearTimeout(this._compTimer),this._compTimer=setTimeout(()=>{this.compArmed=!0},300)},disarmComp(){clearTimeout(this._compTimer),this._compTimer=null,!this.resizing&&(this.compArmed=!1)},startResize(e){let t=e&&e.currentTarget;if(!t||!this.compArmed)return;this.resizing=!0,document.body.style.cursor=`row-resize`,document.body.style.userSelect=`none`;let n=e.pointerId;try{t.setPointerCapture(n)}catch{}let r=this.$el.getBoundingClientRect().bottom,i=e=>{let{min:t,max:n}=this.heightLimits();this.heightPx=Math.max(t,Math.min(n,Math.round(r-e.clientY)))},a=()=>{t.removeEventListener(`pointermove`,i),t.removeEventListener(`pointerup`,a),t.removeEventListener(`pointercancel`,a),window.removeEventListener(`blur`,a);try{t.hasPointerCapture?.(n)&&t.releasePointerCapture(n)}catch{}this.resizing=!1,document.body.style.cursor=``,document.body.style.userSelect=``,this.saveHeight()};t.addEventListener(`pointermove`,i),t.addEventListener(`pointerup`,a),t.addEventListener(`pointercancel`,a),window.addEventListener(`blur`,a)},resetHeight(){this.heightPx=0,this.saveHeight(),this.$nextTick(this.autoGrow)},onKeydown(e){if(e.key===`Escape`){e.preventDefault(),this.$emit(`escape`);return}e.key===`Enter`&&(e.isComposing||e.keyCode===229||e.shiftKey||(e.preventDefault(),this.busy||this.submit()))},submit(){if(this.busy||!this.canSend)return;let e={text:this.text.trim(),attachments:this.attachments.filter(e=>!e.pending&&e.exists!==!1)};this.text=``,this.attachOpen=!1,this.$nextTick(this.autoGrow),this.$emit(`send`,e)},toggleAttach(){this.attachOpen=!this.attachOpen},pick(e){this.attachOpen=!1,this.$emit(`pick`,e)},openPathInput(){this.attachOpen=!1,this.pathInputOpen=!0,this.pathText=``,this.$nextTick(()=>this.$refs.pathEl?.focus())},closePathInput(){this.pathInputOpen=!1,this.pathText=``},confirmPath(){let e=this.pathText.trim();e&&(this.$emit(`add-path`,e),this.closePathInput())},onDragEnter(){this.dragOver=!0},onDragOver(){this.dragOver=!0},onDragLeave(){this.dragOver=!1},onDrop(e){this.dragOver=!1;let t=e.dataTransfer;t&&this.$emit(`drop-files`,t)},async onPaste(e){let t=e.clipboardData?.items;if(t){for(let n of t)if(n.type&&n.type.indexOf(`image/`)===0){let t=n.getAsFile();if(!t)continue;e.preventDefault();let r=await new Promise(e=>{let n=new FileReader;n.onload=()=>e(String(n.result||``)),n.onerror=()=>e(``),n.readAsDataURL(t)});r&&this.$emit(`paste-image`,r);return}}}}},uA={key:0,class:`aicomp__files`},dA=[`title`],fA=[`src`,`alt`],pA={key:1,class:`aichip__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},mA=[`href`],hA={class:`aichip__name`},gA={key:2,class:`aichip__sub`},_A=[`onClick`],vA={key:1,class:`aicomp__path`},yA=[`disabled`],bA=[`placeholder`],xA={class:`aicomp__bar`},SA={class:`aicomp__tools`},CA={class:`aicomp__attach`,ref:`attachEl`},wA={key:0,class:`aicomp__menu`,role:`menu`},TA={class:`aicomp__right`},EA=[`title`],DA={class:`aicomp__ctx-ring`,viewBox:`0 0 20 20`,"aria-hidden":`true`},OA=[`stroke-dasharray`],kA={class:`aicomp__ctx-pct`},AA=[`title`],jA=[`disabled`,`title`];function MA(e,t,n,r,i,a){return B(),V(`div`,{class:j([`aicomp`,{"is-busy":n.busy,"is-drag":i.dragOver,"is-manual":i.heightPx>0,"is-resizing":i.resizing}]),style:A(a.compStyle)},[K(` 上缘拖拽把手:调输入区高度(106px ~ 面板高度 50%,双击恢复自适应),与面板宽度把手同一套交互 `),U(`div`,{class:j([`aicomp__grip`,{"is-dragging":i.resizing,"is-armed":i.compArmed}]),title:`拖拽调整输入区高度(双击恢复自适应)`,onMouseenter:t[0]||=(...e)=>a.armComp&&a.armComp(...e),onMouseleave:t[1]||=(...e)=>a.disarmComp&&a.disarmComp(...e),onPointerdown:t[2]||=q((...e)=>a.startResize&&a.startResize(...e),[`prevent`]),onDblclick:t[3]||=q((...e)=>a.resetHeight&&a.resetHeight(...e),[`prevent`])},null,34),K(` 已挂载的本地文件:只预览 + 传路径,不上传 `),n.attachments.length?(B(),V(`div`,uA,[(B(!0),V(z,null,R(n.attachments,n=>(B(),V(`div`,{key:n.path,class:j([`aichip`,{"aichip--dir":n.isDir,"aichip--pending":n.pending,"aichip--missing":n.exists===!1}]),title:n.path},[n.isImage&&!n.pending?(B(),V(`img`,{key:0,class:`aichip__thumb`,src:a.fileUrl(n.path),alt:n.name,loading:`lazy`},null,8,fA)):(B(),V(`svg`,pA,[U(`use`,{href:n.pending?`#icon-loading`:n.isDir?`#icon-folder-plus`:n.isImage?`#icon-image`:`#icon-file-text`},null,8,mA)])),U(`span`,hA,M(n.pending?`解析路径中…`:n.name),1),n.pending?K(`v-if`,!0):(B(),V(`span`,gA,M(a.chipSub(n)),1)),U(`button`,{type:`button`,class:`aichip__rm`,title:`移除`,onClick:t=>e.$emit(`remove-attachment`,n.path)},[...t[24]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]],8,_A)],10,dA))),128))])):K(`v-if`,!0),K(` 粘贴绝对路径(非 macOS / 拖拽反查失败时的兜底入口) `),i.pathInputOpen?(B(),V(`div`,vA,[I(U(`input`,{ref:`pathEl`,"onUpdate:modelValue":t[4]||=e=>i.pathText=e,class:`aicomp__path-input`,type:`text`,placeholder:`粘贴本地图片或文件夹的绝对路径,回车确认`,spellcheck:`false`,onKeydown:[t[5]||=vl(q((...e)=>a.confirmPath&&a.confirmPath(...e),[`prevent`]),[`enter`]),t[6]||=vl(q((...e)=>a.closePathInput&&a.closePathInput(...e),[`stop`,`prevent`]),[`esc`])]},null,544),[[il,i.pathText]]),U(`button`,{type:`button`,class:`aicomp__path-ok`,disabled:!i.pathText.trim(),onClick:t[7]||=(...e)=>a.confirmPath&&a.confirmPath(...e)},`添加`,8,yA),U(`button`,{type:`button`,class:`aicomp__path-no`,onClick:t[8]||=(...e)=>a.closePathInput&&a.closePathInput(...e)},`取消`)])):K(`v-if`,!0),U(`div`,{class:`aicomp__box`,onDragenter:t[20]||=q((...e)=>a.onDragEnter&&a.onDragEnter(...e),[`prevent`]),onDragover:t[21]||=q((...e)=>a.onDragOver&&a.onDragOver(...e),[`prevent`]),onDragleave:t[22]||=q((...e)=>a.onDragLeave&&a.onDragLeave(...e),[`prevent`]),onDrop:t[23]||=q((...e)=>a.onDrop&&a.onDrop(...e),[`prevent`])},[I(U(`textarea`,{ref:`taEl`,"onUpdate:modelValue":t[9]||=e=>i.text=e,class:`aicomp__ta`,placeholder:n.placeholder,rows:`1`,onInput:t[10]||=(...e)=>a.autoGrow&&a.autoGrow(...e),onKeydown:t[11]||=(...e)=>a.onKeydown&&a.onKeydown(...e),onPaste:t[12]||=(...e)=>a.onPaste&&a.onPaste(...e)},null,40,bA),[[il,i.text]]),U(`div`,xA,[U(`div`,SA,[U(`div`,CA,[U(`button`,{type:`button`,class:j([`aicomp__iconbtn`,{"is-open":i.attachOpen}]),title:`挂载本地图片 / 文件 / 文件夹`,onClick:t[13]||=(...e)=>a.toggleAttach&&a.toggleAttach(...e)},[...t[25]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-paperclip`})],-1)]],2),i.attachOpen?(B(),V(`div`,wA,[U(`button`,{type:`button`,role:`menuitem`,onClick:t[14]||=e=>a.pick(`image`)},[...t[26]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-image`})],-1),G(` 本地图片… `,-1)]]),U(`button`,{type:`button`,role:`menuitem`,onClick:t[15]||=e=>a.pick(`file`)},[...t[27]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-file-text`})],-1),G(` 本地文件… `,-1)]]),U(`button`,{type:`button`,role:`menuitem`,onClick:t[16]||=e=>a.pick(`folder`)},[...t[28]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-folder-plus`})],-1),G(` 本地文件夹… `,-1)]]),t[30]||=U(`div`,{class:`aicomp__menu-sep`},null,-1),U(`button`,{type:`button`,role:`menuitem`,onClick:t[17]||=(...e)=>a.openPathInput&&a.openPathInput(...e)},[...t[29]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-link`})],-1),G(` 粘贴路径… `,-1)]])])):K(`v-if`,!0)],512),t[31]||=U(`span`,{class:`aicomp__hint`},`拖拽文件 / 文件夹到此,或直接 ⌘V 粘贴截图`,-1)]),U(`div`,TA,[a.ctx?(B(),V(`span`,{key:0,class:j([`aicomp__ctx`,`is-${a.ctx.level}`]),title:a.ctxTitle},[(B(),V(`svg`,DA,[t[32]||=U(`circle`,{class:`aicomp__ctx-track`,cx:`10`,cy:`10`,r:`8`},null,-1),U(`circle`,{class:`aicomp__ctx-arc`,cx:`10`,cy:`10`,r:`8`,"stroke-dasharray":`${a.ctx.arc} ${a.ctx.circ}`,transform:`rotate(-90 10 10)`},null,8,OA)])),U(`span`,kA,M(a.ctx.pctLabel),1)],10,EA)):K(`v-if`,!0),n.model?(B(),V(`span`,{key:1,class:`aicomp__model`,title:`当前模型:${n.model}`},M(n.model),9,AA)):K(`v-if`,!0),n.busy?(B(),V(`button`,{key:2,type:`button`,class:`aicomp__send aicomp__send--stop`,title:`终止生成(Esc)`,onClick:t[18]||=t=>e.$emit(`stop`)},[...t[33]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"aria-hidden":`true`},[U(`use`,{href:`#icon-stop`})],-1)]])):(B(),V(`button`,{key:3,type:`button`,class:`aicomp__send`,disabled:!a.canSend,title:a.canSend?`发送(Enter)`:`输入内容后发送`,onClick:t[19]||=(...e)=>a.submit&&a.submit(...e)},[...t[34]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-send`})],-1)]],8,jA))])])],32)],6)}var NA=X(lA,[[`render`,MA],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatComposer.vue`]]),PA={name:`AiSettings`,components:{NumberStepper:Ag,Switch:ZC},props:{config:{type:Object,default:()=>({baseUrl:``,model:``,hasKey:!1,apiKeyMasked:``})},modelId:{type:String,default:null},initialModel:{type:Object,default:null}},emits:[`close`,`saved`],data(){let e=this.modelId&&this.initialModel||{};return{form:{name:e.name||``,baseUrl:e.baseUrl||``,model:e.model||``,apiKey:``,thinking:e.thinking!==!1,vision:e.vision===!0,maxTokens:e.maxTokensAuto?0:Number(e.maxTokens)>0?Number(e.maxTokens):0},reveal:!1,saving:!1,testing:!1,probing:!1,ping:null,help:null,keyLoaded:!1,submitted:!1,touched:{}}},computed:{title(){return this.modelId?`编辑模型`:`添加模型`},errors(){let e={},t=this.form.baseUrl.trim(),n=this.form.model.trim();return t?/^https?:\/\/[^\s]+$/i.test(t)||(e.baseUrl=`Base URL 需以 http:// 或 https:// 开头`):e.baseUrl=`请填写 Base URL`,n||(e.model=`请填写模型名`),!this.keyLoaded&&!this.form.apiKey.trim()&&(e.apiKey=`请填写 API Key`),e},isValid(){return Object.keys(this.errors).length===0},knownCapLimit(){return(Number(this.config.maxTokensCap)>0?Number(this.config.maxTokensCap):0)||(Number(this.config.maxTokensWindow)>0?Number(this.config.maxTokensWindow):0)},maxTokensOver(){return this.knownCapLimit>0&&this.form.maxTokens>this.knownCapLimit},maxTokensPlaceholder(){let e=Number(this.config.maxTokens)>0?Number(this.config.maxTokens):0;return e>0?`留空 = 自动(当前按 ${e})`:`留空 = 自动`},keyPlaceholder(){return this.keyLoaded?this.form.apiKey?``:`已保存的密钥为空,请填写新密钥`:this.config.hasKey?`已保存(${this.config.apiKeyMasked||`••••`}),回显失败:留空沿用、填写覆盖`:`sk-…`}},created(){this.loadKey()},mounted(){document.addEventListener(`click`,this.onDocClick,!0),document.addEventListener(`keydown`,this.onKeydown)},beforeUnmount(){document.removeEventListener(`click`,this.onDocClick,!0),document.removeEventListener(`keydown`,this.onKeydown)},methods:{toggleHelp(e){this.help=this.help===e?null:e},showError(e){return!!this.errors[e]&&(this.submitted||this.touched[e])},markTouched(e){this.$set(this.touched,e,!0)},onDocClick(e){if(!this.help)return;let t=e.target;t instanceof Element&&t.closest(`.aiset__pop, .aiset__help`)||(this.help=null)},onKeydown(e){e.key===`Escape`&&this.help&&(e.stopPropagation(),this.help=null)},onMaxTokens(e){let t=Number(String(e).trim());this.form.maxTokens=Number.isFinite(t)&&t>=0?Math.round(t):0},async probe(){let e=[];if(this.form.baseUrl.trim()||e.push(`Base URL`),this.form.apiKey.trim()||e.push(`API Key`),this.form.model.trim()||e.push(`模型名`),e.length){this.ping={ok:!1,text:`探测前请先填写:${e.join(` / `)}`};return}this.probing=!0,this.ping=null;try{let e=await wO({baseUrl:this.form.baseUrl,apiKey:this.form.apiKey,model:this.form.model}),t=Number(e.window)>0?Number(e.window):0,n=Number(e.cap)>0?Number(e.cap):0;if(n>0){this.form.maxTokens=n;let r=e.source===`models-meta`?`模型元数据`:e.source===`probe`?`二分试探`:e.source===`halved`?`减半回写`:e.source||`探测`,i=[`接受单次输出上限 ${n}`];t>0&&i.push(`上下文窗口 ${t}`),this.ping={ok:!0,text:`网关${i.join(`、`)}(来源:${r})→ 已填入 ${n};留空则走自动(取 min(上限, ${Number(e.ceiling)>0?e.ceiling:32768}) = ${Number(e.autoMax)>0?e.autoMax:n})`}}else{let n=[];t>0&&n.push(`上下文窗口 ${t}`),e.source===`fallback`?n.push(`网关未接受任何档位(可能是地址 / 密钥 / 模型名有误,或该网关不暴露上限)`):n.push(`未探到网关接受的单次输出上限`),this.ping={ok:!1,text:`${n.join(`;`)}。建议留空走自动:后端按默认值开跑,被网关拒绝时自动减半并记下真实上限`}}}catch(e){this.ping={ok:!1,text:`探测失败:${e.message||e}`}}finally{this.probing=!1}},async loadKey(){if(this.modelId)try{let e=await yO(this.modelId,!0),t=typeof e.apiKey==`string`?e.apiKey:``;t&&(this.form.apiKey=t,this.keyLoaded=!0),typeof e.name==`string`&&(this.form.name=e.name),typeof e.baseUrl==`string`&&(this.form.baseUrl=e.baseUrl),typeof e.model==`string`&&(this.form.model=e.model),this.form.maxTokens=e.maxTokensAuto||!(Number(e.maxTokens)>0)?0:Number(e.maxTokens),e.thinking!==void 0&&(this.form.thinking=e.thinking!==!1),e.vision!==void 0&&(this.form.vision=e.vision===!0)}catch{}},payload(){let e={name:this.form.name.trim(),baseUrl:this.form.baseUrl.trim(),model:this.form.model.trim(),thinking:!!this.form.thinking,vision:!!this.form.vision,maxTokens:Number(this.form.maxTokens)>0?Number(this.form.maxTokens):0};return(this.keyLoaded||this.form.apiKey.trim())&&(e.apiKey=this.form.apiKey.trim()),e},async test(){if(!this.isValid){this.submitted=!0,this.help=null,this.ping={ok:!1,text:`请先补全必填项(Base URL / 模型名 / API Key)再测试连接`};return}this.testing=!0,this.ping=null;try{let e=await TO(this.payload());this.ping=e.ok?{ok:!0,text:`连接正常 · ${e.model||this.form.model} · ${e.latencyMs}ms`}:{ok:!1,text:`连接失败${e.status?`(HTTP ${e.status})`:``}:${e.message||`未知错误`}`}}catch(e){this.ping={ok:!1,text:`测试失败:${e.message||e}`}}finally{this.testing=!1}},async save(){if(this.submitted=!0,!this.isValid){this.help=null;let e={baseUrl:`aiset-baseurl`,model:`aiset-model`,apiKey:`aiset-key`},t=Object.keys(this.errors)[0],n=t?this.$el.querySelector(`#${e[t]}`):null;n&&typeof n.focus==`function`&&n.focus(),this.ping={ok:!1,text:`请先补全必填项(Base URL / 模型名 / API Key)`};return}this.saving=!0;try{let e=this.modelId?await xO(this.modelId,this.payload()):await bO(this.payload());this.$emit(`saved`,e)}catch(e){this.ping={ok:!1,text:`保存失败:${e.message||e}`}}finally{this.saving=!1}}}},FA={class:`aiset__mask`},IA={class:`aiset`,role:`dialog`,"aria-modal":`true`,"aria-label":`AI 模型设置`},LA={class:`aiset__head`},RA={class:`aiset__title`},zA={class:`aiset__body`},BA={class:`aiset__field`},VA={class:`aiset__field`},HA={class:`aiset__labelrow`},UA=[`aria-expanded`],WA=[`aria-invalid`],GA={key:0,class:`aiset__errline`},KA={key:1,class:`aiset__pop`},qA={class:`aiset__field`},JA={class:`aiset__labelrow`},YA=[`aria-expanded`],XA=[`aria-invalid`],ZA={key:0,class:`aiset__errline`},QA={key:1,class:`aiset__pop`},$A={class:`aiset__field`},ej={class:`aiset__labelrow`},tj=[`aria-expanded`],nj={class:`aiset__keywrap`},rj=[`type`,`placeholder`,`aria-invalid`],ij=[`title`,`aria-pressed`],aj={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},oj=[`href`],sj={key:0,class:`aiset__errline`},cj={key:1,class:`aiset__pop`},lj={class:`aiset__field`},uj={class:`aiset__labelrow`},dj=[`aria-expanded`],fj={class:`aiset__stepperrow`},pj=[`disabled`],mj={key:0,class:`aiset__warnline`},hj={key:1,class:`aiset__pop`},gj={class:`aiset__field`},_j={class:`aiset__labelrow`},vj=[`aria-expanded`],yj={key:0,class:`aiset__pop`},bj={class:`aiset__field`},xj={class:`aiset__labelrow`},Sj=[`aria-expanded`],Cj={key:0,class:`aiset__pop`},wj={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},Tj=[`href`],Ej={class:`aiset__foot`},Dj=[`disabled`],Oj={class:`aiset__btn-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},kj=[`href`],Aj=[`disabled`],jj=[`disabled`];function Mj(e,t,n,r,i,a){let o=L(`NumberStepper`),s=L(`Switch`);return B(),V(`div`,FA,[U(`section`,IA,[U(`header`,LA,[t[22]||=U(`svg`,{class:`aiset__head-icon is-solid-icon`,viewBox:`0 0 1024 1024`,"aria-hidden":`true`},[U(`use`,{href:`#icon-model`})],-1),U(`span`,RA,M(a.title),1),U(`button`,{type:`button`,class:`aiset__x`,title:`关闭`,onClick:t[0]||=t=>e.$emit(`close`)},[...t[21]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])]),K(` 字段说明一律收进「?」浮层:面板只留标签 + 控件,需要时点开看详情 `),U(`div`,zA,[U(`div`,BA,[t[23]||=U(`div`,{class:`aiset__labelrow`},[U(`label`,{class:`aiset__label`,for:`aiset-name`},`名称`)],-1),I(U(`input`,{id:`aiset-name`,"onUpdate:modelValue":t[1]||=e=>i.form.name=e,class:`aiset__input`,type:`text`,placeholder:`模型显示名(如 GPT-4o / 我的 GLM)`,spellcheck:`false`,autocomplete:`off`},null,512),[[il,i.form.name]])]),U(`div`,VA,[U(`div`,HA,[t[25]||=U(`label`,{class:`aiset__label`,for:`aiset-baseurl`},[G(`Base URL`),U(`i`,{class:`aiset__req`,"aria-hidden":`true`},`*`)],-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`baseUrl`}]),"aria-expanded":i.help===`baseUrl`,title:`查看说明`,onClick:t[2]||=q(e=>a.toggleHelp(`baseUrl`),[`stop`])},[...t[24]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,UA)]),I(U(`input`,{id:`aiset-baseurl`,"onUpdate:modelValue":t[3]||=e=>i.form.baseUrl=e,class:j([`aiset__input`,{"is-invalid":a.showError(`baseUrl`)}]),type:`text`,placeholder:`https://api.example.com/v1`,spellcheck:`false`,autocomplete:`off`,"aria-invalid":a.showError(`baseUrl`)?`true`:`false`,onBlur:t[4]||=e=>a.markTouched(`baseUrl`)},null,42,WA),[[il,i.form.baseUrl]]),a.showError(`baseUrl`)?(B(),V(`p`,GA,M(a.errors.baseUrl),1)):K(`v-if`,!0),i.help===`baseUrl`?(B(),V(`p`,KA,[...t[26]||=[G(`OpenAI 兼容网关的基址,`,-1),U(`strong`,null,`不含`,-1),G(),U(`code`,null,`/chat/completions`,-1),G(` 后缀(后端会自己拼)。例:`,-1),U(`code`,null,`https://api.openai.com/v1`,-1),G(`。`,-1)]])):K(`v-if`,!0)]),U(`div`,qA,[U(`div`,JA,[t[28]||=U(`label`,{class:`aiset__label`,for:`aiset-model`},[G(`模型名`),U(`i`,{class:`aiset__req`,"aria-hidden":`true`},`*`)],-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`model`}]),"aria-expanded":i.help===`model`,title:`查看说明`,onClick:t[5]||=q(e=>a.toggleHelp(`model`),[`stop`])},[...t[27]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,YA)]),I(U(`input`,{id:`aiset-model`,"onUpdate:modelValue":t[6]||=e=>i.form.model=e,class:j([`aiset__input`,{"is-invalid":a.showError(`model`)}]),type:`text`,placeholder:`gpt-4o / GLM-4.6 / deepseek-chat`,spellcheck:`false`,autocomplete:`off`,"aria-invalid":a.showError(`model`)?`true`:`false`,onBlur:t[7]||=e=>a.markTouched(`model`)},null,42,XA),[[il,i.form.model]]),a.showError(`model`)?(B(),V(`p`,ZA,M(a.errors.model),1)):K(`v-if`,!0),i.help===`model`?(B(),V(`p`,QA,`必须与网关侧的模型标识完全一致。建卡这类多步工具调用建议用支持 function calling 的模型。`)):K(`v-if`,!0)]),U(`div`,$A,[U(`div`,ej,[t[30]||=U(`label`,{class:`aiset__label`,for:`aiset-key`},[G(`API Key`),U(`i`,{class:`aiset__req`,"aria-hidden":`true`},`*`)],-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`apiKey`}]),"aria-expanded":i.help===`apiKey`,title:`查看说明`,onClick:t[8]||=q(e=>a.toggleHelp(`apiKey`),[`stop`])},[...t[29]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,tj)]),U(`div`,nj,[I(U(`input`,{id:`aiset-key`,"onUpdate:modelValue":t[9]||=e=>i.form.apiKey=e,class:j([`aiset__input aiset__input--key`,{"is-invalid":a.showError(`apiKey`)}]),type:i.reveal?`text`:`password`,placeholder:a.keyPlaceholder,spellcheck:`false`,autocomplete:`off`,"aria-invalid":a.showError(`apiKey`)?`true`:`false`,onBlur:t[10]||=e=>a.markTouched(`apiKey`)},null,42,rj),[[fl,i.form.apiKey]]),U(`button`,{type:`button`,class:`aiset__eye`,title:i.reveal?`掩码显示密钥`:`明文显示密钥`,"aria-pressed":i.reveal,onClick:t[11]||=e=>i.reveal=!i.reveal},[(B(),V(`svg`,aj,[U(`use`,{href:i.reveal?`#icon-eye-off`:`#icon-eye`},null,8,oj)]))],8,ij)]),a.showError(`apiKey`)?(B(),V(`p`,sj,M(a.errors.apiKey),1)):K(`v-if`,!0),i.help===`apiKey`?(B(),V(`p`,cj,[...t[31]||=[G(` 密钥保存在项目根 `,-1),U(`code`,null,`.env.cb.local`,-1),G(`(个人覆盖层,已被 .gitignore 忽略,不会进版本库)。 打开面板自动回填已保存的密钥(默认掩码),点输入框尾部小眼睛切换明文;`,-1),U(`strong`,null,`清空后保存即删除`,-1),G(`已保存的密钥。 `,-1)]])):K(`v-if`,!0)]),U(`div`,lj,[U(`div`,uj,[t[33]||=U(`label`,{class:`aiset__label`},`单次输出上限`,-1),t[34]||=U(`span`,{class:`aiset__unit`},`max_tokens`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`maxTokens`}]),"aria-expanded":i.help===`maxTokens`,title:`查看说明`,onClick:t[12]||=q(e=>a.toggleHelp(`maxTokens`),[`stop`])},[...t[32]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,dj)]),U(`div`,fj,[W(o,{id:`aiset-maxtok`,class:`aiset__stepper`,value:i.form.maxTokens>0?String(i.form.maxTokens):``,step:1024,min:0,max:262144,placeholder:a.maxTokensPlaceholder,onInput:a.onMaxTokens},null,8,[`value`,`placeholder`,`onInput`]),U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.probing||i.saving||i.testing,onClick:t[13]||=(...e)=>a.probe&&a.probe(...e)},M(i.probing?`探测中…`:`探测`),9,pj)]),a.maxTokensOver?(B(),V(`p`,mj,` 超过网关已知上限 `+M(a.knownCapLimit)+`:对话时会主动夹取到该值,建议留空走自动 `,1)):K(`v-if`,!0),i.help===`maxTokens`?(B(),V(`p`,hj,[t[35]||=U(`strong`,null,`普通用户不用管这一项:留空 = 自动`,-1),t[36]||=G(`。后端自己协商:先读网关 `,-1),t[37]||=U(`code`,null,`/v1/models`,-1),t[38]||=G(` 的上下文窗口(免费、毫秒级,最多等 2 秒,超时先用默认 24576 开跑), 拿到后取 `,-1),t[39]||=U(`code`,null,`min(窗口, 32768)`,-1),t[40]||=G(` 当作单次输出上限(输出预算 ≠ 上下文窗口,建卡一轮 32k 足够)。 读不到元数据也不会偷偷发试探请求;想知道窗口多大就点「探测」做一次二分试探(会产生一次真实补全,约十几秒)。 手填值超过网关接受上限时,对话开跑前会主动夹取并说明;真被 400 拒绝才会自动减半重试, 减半成功的值记为「接受上限」(**不是窗口**:窗口与输出上限是两回事,有网关窗口 262144 但 max_tokens 硬上限 131072)。 只有某轮明确报「被单次输出上限截断」才需要手填更大值。注意:推理模型的思考过程也算进这个上限。 `,-1),t[41]||=U(`br`,null,null,-1),t[42]||=U(`strong`,null,[G(`注意:`),U(`code`,null,`32768`),G(` 是自动模式的「封顶假设值」,不是网关能力上限。`)],-1),t[43]||=G(` 真实上限只能实测得到,请以「接受的单次输出上限」为准(如 qwen-max 实测仅 8192)。 `,-1),t[44]||=U(`br`,null,null,-1),t[45]||=G(`当前自动生效值:`,-1),U(`strong`,null,M(n.config.maxTokens>0?n.config.maxTokens:24576),1),G(`; 网关上下文窗口:`+M(n.config.maxTokensWindow>0?n.config.maxTokensWindow:`未拿到(网关可能不提供元数据)`)+`; 接受的单次输出上限:`+M(n.config.maxTokensCap>0?n.config.maxTokensCap:`未知(点「探测」,或撞过一次 400 后自动回写)`)+`。 `,1)])):K(`v-if`,!0)]),U(`div`,gj,[K(` 仅「勾选框 + 标题」包进 label:点说明 / 问号不应误触开关 `),U(`div`,_j,[t[47]||=U(`span`,{class:`aiset__label`},`深度思考`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`thinking`}]),"aria-expanded":i.help===`thinking`,title:`查看说明`,onClick:t[14]||=q(e=>a.toggleHelp(`thinking`),[`stop`])},[...t[46]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,vj),W(s,{modelValue:i.form.thinking,"onUpdate:modelValue":t[15]||=e=>i.form.thinking=e,class:`aiset__switch`},null,8,[`modelValue`])]),i.help===`thinking`?(B(),V(`p`,yj,[...t[48]||=[G(` 开启:模型先长篇推理再动手,规划更稳但慢很多、更费 token。关闭:直接出结果,实测同一网关快数倍。 关闭依赖网关支持 `,-1),U(`code`,null,`chat_template_kwargs.enable_thinking`,-1),G(`(vLLM / SGLang 系);网关不认时后端会自动回退成带思考并在对话里提示一次。 另外,`,-1),U(`strong`,null,`某一轮思考超时`,-1),G(`时后端会自动只在那一轮关闭深度思考并重试,逼出结果。 `,-1)]])):K(`v-if`,!0)]),U(`div`,bj,[U(`div`,xj,[t[50]||=U(`span`,{class:`aiset__label`},`多模态视觉`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`vision`}]),"aria-expanded":i.help===`vision`,title:`查看说明`,onClick:t[16]||=q(e=>a.toggleHelp(`vision`),[`stop`])},[...t[49]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,Sj),W(s,{modelValue:i.form.vision,"onUpdate:modelValue":t[17]||=e=>i.form.vision=e,class:`aiset__switch`},null,8,[`modelValue`])]),i.help===`vision`?(B(),V(`p`,Cj,[...t[51]||=[G(` 开启后首轮对话会`,-1),U(`strong`,null,`自动探测`,-1),G(`网关是否真支持图像(比较带图 / 不带图的 prompt_tokens):支持则把渲染截图、设计稿 vs 渲染并排对比图、你挂载的图片注入上下文,AI 可直接读图找差异; 不支持会自动降级为数值闭环(pixelDiff.match)并在对话里提示一次。注入前降采样到长边 ≤ 1024px / ≤ 900KB,每轮最多 2 张;对话记录落盘不含图像。 `,-1)]])):K(`v-if`,!0)]),i.ping?(B(),V(`div`,{key:0,class:j([`aiset__ping`,i.ping.ok?`is-ok`:`is-bad`])},[(B(),V(`svg`,wj,[U(`use`,{href:i.ping.ok?`#icon-check`:`#icon-alert-triangle`},null,8,Tj)])),U(`span`,null,M(i.ping.text),1)],2)):K(`v-if`,!0)]),U(`footer`,Ej,[U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.testing||i.saving,onClick:t[18]||=(...e)=>a.test&&a.test(...e)},[(B(),V(`svg`,Oj,[U(`use`,{href:i.testing?`#icon-loading`:`#icon-activity`},null,8,kj)])),U(`span`,null,M(i.testing?`测试中…`:`测试连接`),1)],8,Dj),t[52]||=U(`span`,{class:`aiset__foot-gap`},null,-1),U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.saving,onClick:t[19]||=t=>e.$emit(`close`)},`取消`,8,Aj),U(`button`,{type:`button`,class:`aiset__btn aiset__btn--primary`,disabled:i.saving||i.testing,onClick:t[20]||=(...e)=>a.save&&a.save(...e)},M(i.saving?`保存中…`:`保存`),9,jj)])])])}var Nj=X(PA,[[`render`,Mj],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/AiSettings.vue`]]),Pj={name:`ModelList`,props:{models:{type:Array,default:()=>[]},activeId:{type:String,default:null},turnRunning:{type:Boolean,default:!1}},emits:[`add`,`edit`,`delete`,`activate`,`close`,`open-common`,`import-ccswitch`],methods:{locked(e){return!!(this.turnRunning&&e&&e.id===this.activeId)},hostOf(e){let t=String(e||``).trim();if(!t)return`未填地址`;try{return new URL(t).host}catch{return t.replace(/^https?:\/\//,``).replace(/\/+$/,``)||t}}}},Fj={class:`aiset__mask`},Ij={class:`aiset modellist`,role:`dialog`,"aria-modal":`true`,"aria-label":`模型选择`},Lj={class:`aiset__head`},Rj={class:`aiset__body ml__body`},zj={class:`ml__toolbar`},Bj={key:0,class:`ml__lock`,role:`status`},Vj={key:1,class:`empty-state`},Hj={class:`ml__list`},Uj=[`aria-disabled`,`onClick`],Wj={key:0,viewBox:`0 0 16 16`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},Gj={class:`ml__info`},Kj={class:`ml__name`},qj={class:`ml__meta`},Jj={class:`ml__model`},Yj={class:`ml__host`},Xj={key:0,class:`ml__key`,title:`已配置密钥`},Zj={key:1,class:`ml__key ml__key--off`,title:`未配置密钥`},Qj={key:2,class:`ml__key ml__key--lock`,title:`对话进行中,正在使用的模型已锁定`},$j={class:`ml__actions`},eM=[`disabled`,`title`,`onClick`],tM=[`disabled`,`title`,`onClick`],nM={class:`ml__foot`},rM={class:`ml__hint`};function iM(e,t,n,r,i,a){return B(),V(`div`,Fj,[U(`section`,Ij,[U(`header`,Lj,[t[5]||=U(`svg`,{class:`aiset__head-icon is-solid-icon`,viewBox:`0 0 1024 1024`,"aria-hidden":`true`},[U(`use`,{href:`#icon-model`})],-1),t[6]||=U(`span`,{class:`aiset__title`},`模型`,-1),U(`button`,{type:`button`,class:`aiset__x`,title:`关闭`,onClick:t[0]||=t=>e.$emit(`close`)},[...t[4]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])]),U(`div`,Rj,[K(` 操作工具条:添加模型 / 从 cc-switch 导入,靠右对齐 `),U(`div`,zj,[U(`button`,{type:`button`,class:`ml__import`,title:`从 cc-switch 导入`,onClick:t[1]||=t=>e.$emit(`import-ccswitch`)},[...t[7]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-download`})],-1),U(`span`,null,`导入`,-1)]]),U(`button`,{type:`button`,class:`ml__add`,title:`添加模型`,onClick:t[2]||=t=>e.$emit(`add`)},[...t[8]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-plus`})],-1),U(`span`,null,`添加模型`,-1)]])]),K(` 对话进行中:正在使用的模型被锁,说明原因与解除方式,避免用户反复点却没反应 `),n.turnRunning?(B(),V(`div`,Bj,[...t[9]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`span`,null,`有对话正在进行:正在使用的模型已锁定,本轮结束后可切换或修改。其他模型仍可编辑。`,-1)]])):K(`v-if`,!0),K(` 空状态:与其他面板占位(图标 + 文字)同一语言 `),n.models.length?(B(),V(z,{key:2},[K(` 模型列表:参考 cc-switch 的 provider 列表——每条可编辑 / 删除,当前生效项高亮 `),U(`ul`,Hj,[(B(!0),V(z,null,R(n.models,r=>(B(),V(`li`,{key:r.id,class:j([`ml__item`,{"is-active":r.id===n.activeId,"is-locked":a.locked(r)}]),"aria-disabled":a.locked(r)?`true`:`false`,onClick:t=>e.$emit(`activate`,r)},[U(`span`,{class:j([`ml__check`,{"is-on":r.id===n.activeId}]),"aria-hidden":`true`},[r.id===n.activeId?(B(),V(`svg`,Wj,[...t[11]||=[U(`use`,{href:`#icon-check`},null,-1)]])):K(`v-if`,!0)],2),U(`span`,Gj,[U(`span`,Kj,M(r.name||r.model||`未命名模型`),1),U(`span`,qj,[U(`span`,Jj,M(r.model||`未填模型名`),1),t[12]||=U(`span`,{class:`ml__dot`},`·`,-1),U(`span`,Yj,M(a.hostOf(r.baseUrl)),1),r.hasKey?(B(),V(`span`,Xj,`已配密钥`)):(B(),V(`span`,Zj,`无密钥`)),a.locked(r)?(B(),V(`span`,Qj,`运行中 · 锁定`)):K(`v-if`,!0)])]),U(`span`,$j,[U(`button`,{type:`button`,class:`ml__btn`,disabled:a.locked(r),title:a.locked(r)?`对话进行中,正在使用的模型不可编辑`:`编辑`,onClick:q(t=>e.$emit(`edit`,r),[`stop`])},[...t[13]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-edit`})],-1)]],8,eM),U(`button`,{type:`button`,class:`ml__btn ml__btn--danger`,disabled:a.locked(r),title:a.locked(r)?`对话进行中,正在使用的模型不可删除`:`删除`,onClick:q(t=>e.$emit(`delete`,r),[`stop`])},[...t[14]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-trash`})],-1)]],8,tM)])],10,Uj))),128))])],2112)):(B(),V(`div`,Vj,[...t[10]||=[as(`<span class="empty-state__badge" aria-hidden="true"><svg class="is-solid-icon" viewBox="0 0 1024 1024"><use href="#icon-model"></use></svg></span><p class="debug__empty">还没有模型</p><p class="empty-state__hint">点上方「添加模型」配置第一个 AI 模型(Base URL / API Key / 模型名),或「导入」从 cc-switch 拉取已有的 Codex 供应商。配置保存在项目根 .env.cb.local,不进版本库。</p>`,3)]]))]),U(`footer`,nM,[U(`span`,rM,M(n.turnRunning?`对话进行中:正在使用的模型已锁定,无法切换`:`点击任意模型即可切换为当前生效模型`),1),U(`button`,{type:`button`,class:`ml__common`,title:`通用设置(执行策略 / 环境参数,所有模型共享)`,onClick:t[3]||=t=>e.$emit(`open-common`)},[...t[15]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-settings`})],-1),U(`span`,null,`通用设置`,-1)]])])])])}var aM=X(Pj,[[`render`,iM],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ModelList.vue`]]),oM=6e4,sM={name:`AiCommonSettings`,components:{NumberStepper:Ag,Switch:ZC},emits:[`close`,`saved`],data(){return{form:{allowShell:!0,autoApprove:`all`,maxSteps:0,turnTimeoutMin:60,stallTimeoutMin:120,stallRetries:-1,reasoningTimeoutMin:600,autoContinueMax:-1},saving:!1,ping:null,help:null,adv:!1,approveOptions:[{value:`none`,label:`逐次确认`},{value:`skill`,label:`免技能`},{value:`all`,label:`全免确认`}]}},created(){this.loadConfig()},mounted(){document.addEventListener(`click`,this.onDocClick,!0),document.addEventListener(`keydown`,this.onKeydown)},beforeUnmount(){document.removeEventListener(`click`,this.onDocClick,!0),document.removeEventListener(`keydown`,this.onKeydown)},methods:{toggleHelp(e){this.help=this.help===e?null:e},onDocClick(e){if(!this.help)return;let t=e.target;t instanceof Element&&t.closest(`.aiset__pop, .aiset__help`)||(this.help=null)},onKeydown(e){e.key===`Escape`&&this.help&&(e.stopPropagation(),this.help=null)},onInt(e,t){let n=String(t).trim();if(!n){this.form[e]=e===`stallRetries`||e===`autoContinueMax`?-1:0;return}let r=Number(n);this.form[e]=Number.isFinite(r)?Math.round(r):0},async loadConfig(){try{let e=await hO();e.shellEnabled!==void 0&&(this.form.allowShell=e.shellEnabled!==!1),e.autoApprove&&(this.form.autoApprove=e.autoApprove),Number(e.maxSteps)>0&&(this.form.maxSteps=Number(e.maxSteps)),Number(e.turnTimeoutMs)>0&&(this.form.turnTimeoutMin=Math.round(Number(e.turnTimeoutMs)/oM)),Number(e.stallTimeoutMs)>0&&(this.form.stallTimeoutMin=Math.round(Number(e.stallTimeoutMs)/oM)),e.stallRetries!==void 0&&e.stallRetries>=0&&(this.form.stallRetries=Number(e.stallRetries)),Number(e.reasoningTimeoutMs)>0&&(this.form.reasoningTimeoutMin=Math.round(Number(e.reasoningTimeoutMs)/oM)),e.autoContinueMax!==void 0&&e.autoContinueMax>=0&&(this.form.autoContinueMax=Number(e.autoContinueMax))}catch{}},async save(){this.saving=!0,this.ping=null;try{let e=await gO({allowShell:!!this.form.allowShell,autoApprove:this.form.autoApprove,maxSteps:Number(this.form.maxSteps)>0?Number(this.form.maxSteps):0,turnTimeoutMs:Number(this.form.turnTimeoutMin)>0?Number(this.form.turnTimeoutMin)*oM:0,stallTimeoutMs:Number(this.form.stallTimeoutMin)>0?Number(this.form.stallTimeoutMin)*oM:0,stallRetries:Number(this.form.stallRetries)>=0?Number(this.form.stallRetries):-1,reasoningTimeoutMs:Number(this.form.reasoningTimeoutMin)>0?Number(this.form.reasoningTimeoutMin)*oM:0,autoContinueMax:Number(this.form.autoContinueMax)>=0?Number(this.form.autoContinueMax):-1});this.$emit(`saved`,e)}catch(e){this.ping={ok:!1,text:`保存失败:${e.message||e}`}}finally{this.saving=!1}}}},cM={class:`aiset__mask`},lM={class:`aiset`,role:`dialog`,"aria-modal":`true`,"aria-label":`AI 通用设置`},uM={class:`aiset__head`},dM={class:`aiset__body`},fM={class:`aiset__field`},pM={class:`aiset__labelrow`},mM=[`aria-expanded`],hM={key:0,class:`aiset__pop`},gM={class:`aiset__field`},_M={class:`aiset__labelrow`},vM=[`aria-expanded`],yM={class:`aiset__seg`},bM=[`onClick`],xM={key:0,class:`aiset__pop`},SM={class:`aiset__adv`},CM=[`aria-expanded`],wM={class:`aiset__adv-hint`},TM={key:0,class:`aiset__adv-body`},EM={class:`aiset__field`},DM={class:`aiset__labelrow`},OM=[`aria-expanded`],kM={class:`aiset__stepperrow`},AM={key:0,class:`aiset__pop`},jM={class:`aiset__field`},MM={class:`aiset__labelrow`},NM=[`aria-expanded`],PM={class:`aiset__stepperrow`},FM={key:0,class:`aiset__pop`},IM={class:`aiset__field`},LM={class:`aiset__labelrow`},RM=[`aria-expanded`],zM={class:`aiset__stepperrow`},BM={key:0,class:`aiset__pop`},VM={class:`aiset__field`},HM={class:`aiset__labelrow`},UM=[`aria-expanded`],WM={class:`aiset__stepperrow`},GM={key:0,class:`aiset__pop`},KM={class:`aiset__field`},qM={class:`aiset__labelrow`},JM=[`aria-expanded`],YM={class:`aiset__stepperrow`},XM={key:0,class:`aiset__pop`},ZM={class:`aiset__field`},QM={class:`aiset__labelrow`},$M=[`aria-expanded`],eN={class:`aiset__stepperrow`},tN={key:0,class:`aiset__pop`},nN={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},rN=[`href`],iN={class:`aiset__foot`},aN=[`disabled`],oN=[`disabled`];function sN(e,t,n,r,i,a){let o=L(`Switch`),s=L(`NumberStepper`);return B(),V(`div`,cM,[U(`section`,lM,[U(`header`,uM,[t[20]||=U(`svg`,{class:`aiset__head-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-settings`})],-1),t[21]||=U(`span`,{class:`aiset__title`},`通用设置`,-1),U(`button`,{type:`button`,class:`aiset__x`,title:`关闭`,onClick:t[0]||=t=>e.$emit(`close`)},[...t[19]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])]),U(`div`,dM,[t[51]||=U(`p`,{class:`aiset__note`},[G(`以下为`),U(`strong`,null,`所有模型共享`),G(`的执行策略 / 环境参数,与具体模型无关,故不放在每个模型条目里。`)],-1),U(`div`,fM,[U(`div`,pM,[t[23]||=U(`span`,{class:`aiset__label`},`本地命令执行`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`allowShell`}]),"aria-expanded":i.help===`allowShell`,title:`查看说明`,onClick:t[1]||=q(e=>a.toggleHelp(`allowShell`),[`stop`])},[...t[22]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,mM),W(o,{modelValue:i.form.allowShell,"onUpdate:modelValue":t[2]||=e=>i.form.allowShell=e,class:`aiset__switch`},null,8,[`modelValue`])]),i.help===`allowShell`?(B(),V(`p`,hM,[...t[24]||=[G(` 是否注册 `,-1),U(`code`,null,`shell_exec`,-1),G(` 本地命令执行。默认开(工具只监听 127.0.0.1,命令过白名单 + 全量审计)。 关掉后 AI 不能跑本地命令,但仍可执行技能脚本(由 `,-1),U(`code`,null,`autoApprove`,-1),G(` 控制是否逐次确认)。 `,-1)]])):K(`v-if`,!0)]),U(`div`,gM,[U(`div`,_M,[t[26]||=U(`span`,{class:`aiset__label`},`免确认执行策略`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`autoApprove`}]),"aria-expanded":i.help===`autoApprove`,title:`查看说明`,onClick:t[3]||=q(e=>a.toggleHelp(`autoApprove`),[`stop`])},[...t[25]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,vM)]),U(`div`,yM,[(B(!0),V(z,null,R(i.approveOptions,e=>(B(),V(`button`,{key:e.value,type:`button`,class:j([`aiset__seg-btn`,{"is-on":i.form.autoApprove===e.value}]),onClick:t=>i.form.autoApprove=e.value},M(e.label),11,bM))),128))]),i.help===`autoApprove`?(B(),V(`p`,xM,[...t[27]||=[U(`code`,null,`none`,-1),G(`=逐次弹审批;`,-1),U(`code`,null,`skill`,-1),G(`=只免技能脚本;`,-1),U(`code`,null,`all`,-1),G(`=技能脚本 + 本地命令都免确认(默认)。 建卡管线连跑十几次脚本 / 命令,`,-1),U(`code`,null,`all`,-1),G(` 避免每次等用户点「允许」。 `,-1)]])):K(`v-if`,!0)]),K(` 保活 / 预算阈值:实测调优出来的值,改只会变坏,故默认收起。
|
|
277
|
-
全部有代码默认值,留空即走默认;折叠区保留可写入口,真要调时不用去翻 .env `),U(`div`,SM,[U(`button`,{type:`button`,class:`aiset__adv-head`,"aria-expanded":i.adv,onClick:t[4]||=e=>i.adv=!i.adv},[(B(),V(`svg`,{class:j([`aiset__adv-caret`,{"is-open":i.adv}]),viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[...t[28]||=[U(`use`,{href:`#icon-chevron-right`},null,-1)]],2)),t[29]||=U(`span`,{class:`aiset__adv-title`},`高级:保活与预算阈值`,-1),U(`span`,wM,M(i.adv?``:`默认值经实测调优,不建议修改`),1)],8,CM),i.adv?(B(),V(`div`,TM,[t[50]||=U(`p`,{class:`aiset__adv-note`},[G(` 这几项是长程任务的`),U(`strong`,null,`熔断与保活阈值`),G(`,数值由实测调优得出(如纯思考预算从 90s 放宽到 600s,因 240s 会误伤正常轮次)。 留空即走默认,`),U(`strong`,null,`没有明确理由不建议改动`),G(`。 `)],-1),U(`div`,EM,[U(`div`,DM,[t[31]||=U(`span`,{class:`aiset__label`},`单轮步数上限`,-1),t[32]||=U(`span`,{class:`aiset__unit`},`0 / 留空 = 不限`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`maxSteps`}]),"aria-expanded":i.help===`maxSteps`,title:`查看说明`,onClick:t[5]||=q(e=>a.toggleHelp(`maxSteps`),[`stop`])},[...t[30]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,OM)]),U(`div`,kM,[W(s,{id:`common-maxsteps`,class:`aiset__stepper`,value:i.form.maxSteps>0?String(i.form.maxSteps):``,step:8,min:0,max:1e3,placeholder:`留空 = 不限(推荐)`,onInput:t[6]||=e=>a.onInt(`maxSteps`,e)},null,8,[`value`])]),i.help===`maxSteps`?(B(),V(`p`,AM,[...t[33]||=[U(`strong`,null,`普通用户不用管:留空 = 不限`,-1),G(`。失控由三道精准熔断兜住(同参打转跳过 / 单轮墙钟到点收尾 / 每 24 步提醒)。 只有想硬性控成本时才填(>0 即恢复旧硬顶行为)。 `,-1)]])):K(`v-if`,!0)]),U(`div`,jM,[U(`div`,MM,[t[35]||=U(`span`,{class:`aiset__label`},`单轮墙钟上限`,-1),t[36]||=U(`span`,{class:`aiset__unit`},`分钟`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`turnTimeout`}]),"aria-expanded":i.help===`turnTimeout`,title:`查看说明`,onClick:t[7]||=q(e=>a.toggleHelp(`turnTimeout`),[`stop`])},[...t[34]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,NM)]),U(`div`,PM,[W(s,{id:`common-turn`,class:`aiset__stepper`,value:i.form.turnTimeoutMin>0?String(i.form.turnTimeoutMin):``,step:5,min:0,max:240,placeholder:`留空 = 60`,onInput:t[8]||=e=>a.onInt(`turnTimeoutMin`,e)},null,8,[`value`])]),i.help===`turnTimeout`?(B(),V(`p`,FM,` 单轮允许跑的最长时间(分钟)。到点收尾汇报、上下文不丢,回复「继续」接着做。默认 60 分钟,不限步数后的唯一兜底闸门。 `)):K(`v-if`,!0)]),U(`div`,IM,[U(`div`,LM,[t[38]||=U(`span`,{class:`aiset__label`},`网关静默阈值`,-1),t[39]||=U(`span`,{class:`aiset__unit`},`分钟`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`stall`}]),"aria-expanded":i.help===`stall`,title:`查看说明`,onClick:t[9]||=q(e=>a.toggleHelp(`stall`),[`stop`])},[...t[37]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,RM)]),U(`div`,zM,[W(s,{id:`common-stall`,class:`aiset__stepper`,value:i.form.stallTimeoutMin>0?String(i.form.stallTimeoutMin):``,step:1,min:0,max:120,placeholder:`留空 = 2`,onInput:t[10]||=e=>a.onInt(`stallTimeoutMin`,e)},null,8,[`value`])]),i.help===`stall`?(B(),V(`p`,BM,` 上游多少分钟不回任何字节算「网关静默」;静默自动重试本步而非整轮报废。默认 2 分钟(120 秒)。 `)):K(`v-if`,!0)]),U(`div`,VM,[U(`div`,HM,[t[41]||=U(`span`,{class:`aiset__label`},`静默重试次数`,-1),t[42]||=U(`span`,{class:`aiset__unit`},`-1 = 默认`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`stallRetries`}]),"aria-expanded":i.help===`stallRetries`,title:`查看说明`,onClick:t[11]||=q(e=>a.toggleHelp(`stallRetries`),[`stop`])},[...t[40]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,UM)]),U(`div`,WM,[W(s,{id:`common-stallretries`,class:`aiset__stepper`,value:i.form.stallRetries>=0?String(i.form.stallRetries):``,step:1,min:-1,max:20,placeholder:`留空 / -1 = 3`,onInput:t[12]||=e=>a.onInt(`stallRetries`,e)},null,8,[`value`])]),i.help===`stallRetries`?(B(),V(`p`,GM,` 网关静默后的自动重试次数。0 = 回到「一次静默即报错」的旧行为;留空 / -1 = 用默认 3 次。 `)):K(`v-if`,!0)]),U(`div`,KM,[U(`div`,qM,[t[44]||=U(`span`,{class:`aiset__label`},`纯思考预算`,-1),t[45]||=U(`span`,{class:`aiset__unit`},`分钟`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`reasoning`}]),"aria-expanded":i.help===`reasoning`,title:`查看说明`,onClick:t[13]||=q(e=>a.toggleHelp(`reasoning`),[`stop`])},[...t[43]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,JM)]),U(`div`,YM,[W(s,{id:`common-reasoning`,class:`aiset__stepper`,value:i.form.reasoningTimeoutMin>0?String(i.form.reasoningTimeoutMin):``,step:1,min:0,max:300,placeholder:`留空 = 10`,onInput:t[14]||=e=>a.onInt(`reasoningTimeoutMin`,e)},null,8,[`value`])]),i.help===`reasoning`?(B(),V(`p`,XM,` 单轮「纯思考」(不调工具)的预算(分钟)。到点催促 + 关深度思考重试;催 3 次仍无产出则停该熔断,改墙钟兜底。默认 10 分钟(600 秒)。 `)):K(`v-if`,!0)]),U(`div`,ZM,[U(`div`,QM,[t[47]||=U(`span`,{class:`aiset__label`},`自动续跑上限`,-1),t[48]||=U(`span`,{class:`aiset__unit`},`-1 = 默认`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`autoContinue`}]),"aria-expanded":i.help===`autoContinue`,title:`查看说明`,onClick:t[15]||=q(e=>a.toggleHelp(`autoContinue`),[`stop`])},[...t[46]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,$M)]),U(`div`,eN,[W(s,{id:`common-autocont`,class:`aiset__stepper`,value:i.form.autoContinueMax>=0?String(i.form.autoContinueMax):``,step:1,min:-1,max:200,placeholder:`留空 / -1 = 12`,onInput:t[16]||=e=>a.onInt(`autoContinueMax`,e)},null,8,[`value`])]),i.help===`autoContinue`?(B(),V(`p`,tN,[...t[49]||=[G(` 模型没给收尾标记(`,-1),U(`code`,null,`[任务完成]`,-1),G(` / `,-1),U(`code`,null,`[需用户确认]`,-1),G(`)就停手时的自动续跑次数上限。0 = 关闭(等你手打「继续」);留空 / -1 = 用默认 12。 `,-1)]])):K(`v-if`,!0)])])):K(`v-if`,!0)]),i.ping?(B(),V(`div`,{key:0,class:j([`aiset__ping`,i.ping.ok?`is-ok`:`is-bad`])},[(B(),V(`svg`,nN,[U(`use`,{href:i.ping.ok?`#icon-check`:`#icon-alert-triangle`},null,8,rN)])),U(`span`,null,M(i.ping.text),1)],2)):K(`v-if`,!0)]),U(`footer`,iN,[t[52]||=U(`span`,{class:`aiset__foot-gap`},null,-1),U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.saving,onClick:t[17]||=t=>e.$emit(`close`)},`取消`,8,aN),U(`button`,{type:`button`,class:`aiset__btn aiset__btn--primary`,disabled:i.saving,onClick:t[18]||=(...e)=>a.save&&a.save(...e)},M(i.saving?`保存中…`:`保存`),9,oN)])])])}var cN=X(sM,[[`render`,sN],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/AiCommonSettings.vue`]]),lN=2e3;function uN(e){try{let t=JSON.stringify(e);return t==null?0:t.length}catch{return 1/0}}function dN(e,t){let n=typeof e==`string`?e:e==null?``:JSON.stringify(e);return n.length<=t?e:`${n.slice(0,t)}\n…(历史归档已裁剪,完整内容以卡片与落盘产物为准)`}function fN(e,t){if(!e||typeof e!=`object`)return e;let n={};for(let[r,i]of Object.entries(e))n[r]=typeof i==`string`||typeof i==`object`&&i?dN(i,t):i;return n}function pN(e,t=!1){let n=Array.isArray(e)?e:[],r=t?400:lN;return n.map(e=>{if(!e||!Array.isArray(e.toolCalls)||!e.toolCalls.length)return e;let n=!1,i=e.toolCalls.map(e=>{if(!e||typeof e!=`object`)return e;let i=fN(e.args,r),a=t?e.result==null||e.result===``?e.result:`[历史归档已裁剪]`:dN(e.result,r);return(JSON.stringify(i)!==JSON.stringify(e.args)||String(a)!==String(e.result))&&(n=!0),{...e,args:i,result:a}});return n?{...e,toolCalls:i,trimmedArchive:!0}:e})}var mN=12e3,hN={pick:{id:`pick`,label:`选一张已有的卡`,hint:`从顶栏下拉里挑`,icon:`#icon-search`,weight:`read`,text:`列出仓库里现有的卡片,按用途分组,帮我挑一张适合修改的。`},scaffold:{id:`scaffold`,label:`新建一张卡`,hint:`从空白骨架开始`,icon:`#icon-folder-plus`,weight:`write`,text:`帮我新建一张卡片:先用 card_scaffold 生成骨架,再按我的需求补齐结构与示例内容,最后自检。`},spec:{id:`spec`,label:`按设计稿标注建卡`,hint:`先拖入 MeaXure 目录`,icon:`#icon-image-upload`,weight:`write`,attach:!0,text:`我会挂载一份 Sketch MeaXure 标注导出目录,请按标注生成卡片 schema 并自检。`},fromimage:{id:`fromimage`,label:`从参考图建卡`,hint:`拖一张设计图进来`,icon:`#icon-image`,weight:`write`,attach:!0,text:`我会拖入一张参考设计图(本机路径),请按图生成卡片 schema 并截图自检还原度。`},learn:{id:`learn`,label:`看已有卡学写法`,hint:`只读,不改卡`,icon:`#icon-search`,weight:`read`,text:`列出仓库里结构最完整的几张卡片,读 1-2 张的关键片段,说明本仓库的建卡约定与常用范式。`},component:{id:`component`,label:`加一个常用组件`,hint:`列表 / 按钮 / 金额卡`,icon:`#icon-plus`,weight:`write`,text:`帮我给这张卡加一个常用组件(列表 / 按钮组 / 金额统计卡),按仓库范式写并自检。`},explain:{id:`explain`,label:`解释结构与数据来源`,hint:`只读,不改卡`,icon:`#icon-search`,weight:`read`,text:`读取当前卡片 schema,用中文解释它的结构、关键绑定与数据来源,指出可能的问题。`},bind:{id:`bind`,label:`把写死文案抽成变量`,hint:`绑定 data.json`,icon:`#icon-link`,weight:`write`,text:`把当前卡片里写死的动态值(金额 / 日期 / 名称等)抽成变量并绑定 data.json,保持展示文案与设计稿一致。`},fix:{id:`fix`,label:`校验并修复`,hint:`会改动卡片`,icon:`#icon-wrench`,weight:`write`,text:`对当前卡片执行校验,列出全部错误并按规则修复,修完再校验一次确认清零。`},shot:{id:`shot`,label:`截图自检还原度`,hint:`多尺寸预览比对`,icon:`#icon-images`,weight:`read`,text:`给当前卡片截图,检查布局、字号、间距与配色是否协调,指出需要调整的地方。`},interact:{id:`interact`,label:`加按钮点击行为`,hint:`customAction / 发消息`,icon:`#icon-send`,weight:`write`,text:`给当前卡片里的主按钮加点击行为(customAction 或发送一条消息),参照现有卡片的写法。`},diagnose:{id:`diagnose`,label:`定位并修复刚才的报错`,hint:`接上一轮`,icon:`#icon-alert-triangle`,weight:`write`,text:`上一轮失败了,请读取错误信息与上下文,定位原因并修复,修完再校验一次。`},resume:{id:`resume`,label:`从中断处继续`,hint:`不重做已完成部分`,icon:`#icon-redo`,weight:`write`,text:`上一轮被中断了,请按上下文里的中断标记从中断处继续,不要从零重做。`},rollback:{id:`rollback`,label:`回滚上一轮改动`,hint:`恢复到改动前`,icon:`#icon-undo`,weight:`write`,text:`把上一轮对卡片做的改动回滚到改动前,并说明回滚了什么。`}},gN={nocare:[`pick`,`scaffold`,`spec`,`learn`,`component`],empty:[`spec`,`fromimage`,`scaffold`,`component`,`learn`],card:[`explain`,`bind`,`fix`,`shot`,`interact`],error:[`diagnose`,`resume`,`rollback`,`explain`,`fix`]},_N={nocare:{title:`选择或新建一张卡`,desc:`先从顶栏选一张卡,或让 AI 新建一张;也可以把设计稿标注目录、参考图拖进来,只传本机路径不上传。`},empty:{title:`把这张空卡搭起来`,desc:`描述想要的效果,或拖入设计稿标注目录 / 参考图,AI 会按标注生成卡片并截图自检。`},error:{title:`接着上一轮往下做`,desc:`上一轮失败或被中断了:可以接着修、从中断处继续,或回滚到改动前。`},card:{title:`让 AI 直接改这张卡`,desc:`描述需求即可,AI 会调用卡片工具读改校验并截图自检;也可以把设计稿标注目录、参考图拖进来,只传本机路径不上传。`}};function vN(e){let t=Array.isArray(e)?e:[];for(let e=t.length-1;e>=0;--e){let n=t[e];if(n&&n.role===`assistant`)return n.status||`done`}return``}function yN({cardId:e,cardEmpty:t,messages:n}={}){if(!e)return`nocare`;if(t)return`empty`;let r=vN(n);return r===`error`||r===`aborted`?`error`:`card`}function bN(e){return(gN[e]||gN.card).map(e=>hN[e]).filter(Boolean)}function xN(e,t,n=4){let r=Array.isArray(e)?e:[];if(r.length<=n)return r.slice();let i=r.length,a=((Number(t)||0)%i+i)%i;return[...r.slice(a),...r.slice(0,a)].slice(0,n)}function SN(e,t=4){return(Array.isArray(e)?e:[]).slice(0,t)}var CN=`cardbuddy:ai-panel-width`,wN=`cardbuddy:ai-compact-steps`,TN=380,EN=.5,DN=.33,ON=0;function kN(e=`m`){return ON+=1,`${e}${Date.now().toString(36)}-${ON}`}var AN=`有对话正在进行,无法修改正在使用的模型:请先等这一轮结束,或在输入区点「停止」`,jN={name:`ChatPanel`,components:{ChatMessage:aA,ChatComposer:NA,AiSettings:Nj,ModelList:aM,AiCommonSettings:cN,ConfirmDialog:_p},props:{visible:{type:Boolean,default:!1},cardId:{type:String,default:``},cardName:{type:String,default:``},cardEmpty:{type:Boolean,default:!1}},emits:[`close`,`busy`,`turn-progress`,`turn-finished`,`rollback-turn`,`locate-node`],data(){return{messages:[],draftAttachments:[],busy:!1,loadingHistory:!1,modelListOpen:!1,models:[],activeId:null,turnRunning:!1,modelEditOpen:!1,editModelId:null,editInitialModel:null,confirmDeleteModel:null,ccSwitchOpen:!1,ccSwitchProviders:[],ccSwitchLoading:!1,ccSwitchReason:``,ccSwitchSelected:{},commonOpen:!1,confirmClear:!1,notice:null,config:{baseUrl:``,model:``,hasKey:!1,apiKeyMasked:``},widthPx:0,winW:typeof window<`u`?window.innerWidth:1280,resizing:!1,gripArmed:!1,_gripTimer:null,listH:0,pinned:!0,contextUsage:null,compactSteps:!1,archiveTrimmed:!1,suggestOffset:0,suggestStats:{},confirmStop:!1,turnStep:0,turnStage:null,turnToolLabel:``,turnStartedAt:0,lastByteAt:0,turnId:``,lastSeq:0,_resumeProbe:!1,nowTs:0,_abort:null,_saveTimer:0,_loadedCard:``,_cardRenamedTo:``,_saving:!1,_liveTicker:0,_turnPersistTimer:0}},computed:{suggestBatchKey(){return yN({cardId:this.cardId,cardEmpty:this.cardEmpty,messages:this.messages})},suggestBatch(){return bN(this.suggestBatchKey)},suggestions(){return xN(this.suggestBatch,this.suggestOffset)},canShuffle(){return this.suggestBatch.length>4},quickChips(){return SN(this.suggestBatch)},emptyTitle(){return(_N[this.suggestBatchKey]||_N.card).title},emptyDesc(){return(_N[this.suggestBatchKey]||_N.card).desc},ccSwitchCheckedCount(){let e=this.ccSwitchSelected||{};return Object.keys(e).filter(t=>e[t]).length},ccSwitchDupCount(){return(this.ccSwitchProviders||[]).filter(e=>e.duplicate).length},configReady(){return!!(this.config.baseUrl&&this.config.model&&this.config.hasKey)},panelWidth(){let e=this.winW||1280,t=Math.max(TN,Math.floor(e*EN)),n=Math.round(e*DN),r=this.widthPx||n;return Math.max(TN,Math.min(t,r))},panelStyle(){let e={width:`${this.panelWidth}px`};return this.listH>0&&(e[`--ai-list-h`]=`${this.listH}px`),e},stallLimitMs(){let e=Number(this.config.stallTimeoutMs)>0?Number(this.config.stallTimeoutMs):12e4;return Math.round(e*1.5)},idleMs(){return this.lastByteAt?Math.max(0,(this.nowTs||Date.now())-this.lastByteAt):0},stalled(){return!!(this.busy&&this.idleMs>this.stallLimitMs)},liveText(){if(!this.busy)return``;let e=[];return this.turnStartedAt&&e.push(`${MD(this.turnStartedAt)} 开始`),this.turnStep>0&&e.push(`第 ${this.turnStep} 步`),e.push(`已用 ${this.fmtClock(this.nowTs-this.turnStartedAt)}`),this.turnStage?e.push(`${this.turnStage.id} ${this.turnStage.label}`):this.turnToolLabel&&e.push(this.turnToolLabel),this.stalled?`${Math.round(this.idleMs/1e3)} 秒没收到任何数据,连接可能已中断(${e.join(` · `)})`:(e.push(`最近数据 ${Math.round(this.idleMs/1e3)} 秒前`),e.join(` · `))}},watch:{suggestBatchKey(){this.suggestOffset=0},visible(e){e?(this.refreshConfig(),this.ensureHistory().then(()=>this.checkResumableTurn()),this.$nextTick(()=>{this.scrollToBottom(!0),this.$refs.composerEl?.focus()})):this.busy&&this.flushHistory()},cardId(e,t){if(this._cardRenamedTo&&this._cardRenamedTo===e){this._cardRenamedTo=``,this._dirtyFor===t&&(this._dirtyFor=e),this._loadedCard===t?(this._loadedCard=e,this._dirtyFor===e&&this.flushHistory(e)):(this._loadedCard=``,this.ensureHistory());return}this._saveTimer&&=(clearTimeout(this._saveTimer),0);let n=this._dirtyFor===t?this.serialize():null;this._dirtyFor=null,this.draftAttachments=[],this.messages=[],n&&t&&this.flushHistory(t,n),this.ensureHistory()}},mounted(){this.loadWidth(),this.loadCompact(),window.addEventListener(`resize`,this.onWinResize),window.addEventListener(`pagehide`,this.onPagehide),this.observeListHeight(),this.refreshConfig(),this.ensureHistory()},beforeUnmount(){window.removeEventListener(`resize`,this.onWinResize),window.removeEventListener(`pagehide`,this.onPagehide),this._stopListObserve&&this._stopListObserve(),this.stopTurnTimers(),this.stopTickers(),this.flushHistory(),this._abort&&this._abort.abort()},methods:{onWinResize(){this.winW=window.innerWidth},onImageClick(e){let t=e.target&&e.target.closest?e.target.closest(`img`):null;if(!t||t.dataset.noZoom===`1`)return;let n=Array.from(this.$el.querySelectorAll(`img`)).filter(e=>e.dataset.noZoom!==`1`),r=n.indexOf(t);r<0||DS(n.map(e=>({src:e.currentSrc||e.src,alt:e.alt||``,title:e.getAttribute(`title`)||e.closest(`[title]`)?.getAttribute(`title`)||``})),r)},observeListHeight(){let e=this.$refs.listEl;if(!e)return;let t=()=>{let t=Math.round(e.clientHeight||0);t>0&&t!==this.listH&&(this.listH=t)};if(t(),typeof ResizeObserver>`u`){this._stopListObserve=()=>window.removeEventListener(`resize`,t),window.addEventListener(`resize`,t);return}let n=new ResizeObserver(e=>{let n=Math.round(e?.[0]?.contentRect?.height||0);n>0&&n!==this.listH?this.listH=n:t()});n.observe(e),this._stopListObserve=()=>n.disconnect()},loadWidth(){try{let e=localStorage.getItem(CN);if(e!=null){let t=parseInt(e,10);!Number.isNaN(t)&&t>=TN&&(this.widthPx=t)}}catch{}},saveWidth(){try{this.widthPx?localStorage.setItem(CN,String(Math.round(this.panelWidth))):localStorage.removeItem(CN)}catch{}},armGrip(){clearTimeout(this._gripTimer),this._gripTimer=setTimeout(()=>{this.gripArmed=!0},300)},disarmGrip(){clearTimeout(this._gripTimer),this._gripTimer=null,!this.resizing&&(this.gripArmed=!1)},startResize(e){let t=e&&e.currentTarget;if(!t||!this.gripArmed)return;this.resizing=!0,document.body.style.cursor=`col-resize`,document.body.style.userSelect=`none`;let n=e.pointerId;try{t.setPointerCapture(n)}catch{}let r=e=>{let t=Math.max(TN,Math.floor(window.innerWidth*EN));this.widthPx=Math.max(TN,Math.min(t,Math.round(window.innerWidth-e.clientX)))},i=()=>{t.removeEventListener(`pointermove`,r),t.removeEventListener(`pointerup`,i),t.removeEventListener(`pointercancel`,i),window.removeEventListener(`blur`,i);try{t.hasPointerCapture?.(n)&&t.releasePointerCapture(n)}catch{}this.resizing=!1,document.body.style.cursor=``,document.body.style.userSelect=``,this.saveWidth()};t.addEventListener(`pointermove`,r),t.addEventListener(`pointerup`,i),t.addEventListener(`pointercancel`,i),window.addEventListener(`blur`,i)},resetWidth(){this.widthPx=0,this.saveWidth()},async refreshConfig(){try{let e=await hO();this.config={...e,hasKey:!!(e.hasKey||e.apiKey)},e.turnRunning!==void 0&&(this.turnRunning=e.turnRunning===!0)}catch{this.config={baseUrl:``,model:``,hasKey:!1,apiKeyMasked:``}}},async loadModels(){try{let e=await _O();this.models=Array.isArray(e.models)?e.models:[],this.activeId=e.activeId||null,this.turnRunning=e.turnRunning===!0}catch{this.models=[],this.activeId=null}},openModelList(){this.modelListOpen=!0,this.loadModels(),this.refreshConfig()},closeModelList(){this.modelListOpen=!1},onModelAdd(){this.modelListOpen=!1,this.editModelId=null,this.editInitialModel=null,this.modelEditOpen=!0},onModelEdit(e){if(this.turnRunning&&e&&e.id===this.activeId)return this.notify(`warn`,AN);this.modelListOpen=!1,this.editModelId=e&&e.id?e.id:null,this.editInitialModel=e||null,this.modelEditOpen=!0},onModelEditClose(){this.modelEditOpen=!1,this.modelListOpen=!0},async onModelSaved(){this.modelEditOpen=!1,this.modelListOpen=!0,await this.loadModels(),await this.refreshConfig()},async onModelActivate(e){if(!(!e||!e.id)){if(this.turnRunning&&e.id!==this.activeId)return this.notify(`warn`,AN);try{await CO(e.id)}catch(e){this.notify(`warn`,`切换模型失败:${e.message||e}`)}await this.loadModels(),await this.refreshConfig()}},onModelDelete(e){if(!(!e||!e.id)){if(this.turnRunning&&e.id===this.activeId)return this.notify(`warn`,AN);this.confirmDeleteModel=e}},async doDeleteModel(){let e=this.confirmDeleteModel;if(this.confirmDeleteModel=null,!(!e||!e.id)){try{await SO(e.id)}catch(e){this.notify(`warn`,`删除失败:${e.message||e}`);return}await this.loadModels(),await this.refreshConfig(),this.notify(`ok`,`已删除模型「${e.name||e.model||e.id}」`)}},get deleteModelMessage(){let e=this.confirmDeleteModel;return`确定删除模型「${e?e.name||e.model||e.id:``}」吗?此操作不可撤销,配置将从 .env.cb.local 移除${e&&e.id===this.activeId?`。该模型当前为生效模型,删除后会自动回落到剩余模型中的第一条(若已无模型则需重新添加)。`:`。`}`},async onImportCcSwitch(){this.ccSwitchOpen=!0,this.ccSwitchLoading=!0,this.ccSwitchProviders=[],this.ccSwitchReason=``,this.ccSwitchSelected={};try{let e=await vO(),t=Array.isArray(e.providers)?e.providers:[],n=this.models.map(e=>e.model).filter(Boolean);t.forEach(e=>{e.duplicate=n.includes(e.model)}),this.ccSwitchProviders=t,t.length||(this.ccSwitchReason=e.reason||`cc-switch 中没有可导入的 Codex 类供应商`)}catch(e){this.ccSwitchReason=`读取 cc-switch 失败:${e&&e.message||e}`}finally{this.ccSwitchLoading=!1}},toggleCcSwitchItem(e){if(!e||e.duplicate)return;let t={...this.ccSwitchSelected};t[e.id]?delete t[e.id]:t[e.id]=!0,this.ccSwitchSelected=t},async confirmImportCcSwitch(){let e=this.ccSwitchProviders.filter(e=>this.ccSwitchSelected[e.id]&&!e.duplicate);if(!e.length)return;let t=0,n=0;for(let r of e)try{await bO({name:r.name||r.model,baseUrl:r.baseUrl,apiKey:r.apiKey||``,model:r.model,maxTokens:0,thinking:!1,vision:!1}),t++}catch(e){n++,console.error(`[cc-switch 导入失败]`,r.name,e)}this.ccSwitchOpen=!1,await this.loadModels(),await this.refreshConfig(),n?this.notify(`warn`,`导入完成:成功 ${t} 个、失败 ${n} 个`):this.notify(`ok`,`已从 cc-switch 导入 ${t} 个模型`)},openCommon(){this.modelListOpen=!1,this.commonOpen=!0},async onCommonSaved(){this.commonOpen=!1,await this.refreshConfig(),this.notify(`ok`,`通用设置已保存`)},async ensureHistory(){let e=this.cardId;if(!(!e||this._loadedCard===e)){this._loadedCard=e,this.loadingHistory=!0;try{let t=await jO(e);if(this.cardId!==e)return;let n=this.busy?this.turnId:``,r=(t.messages||[]).map(e=>this.revive(e)).filter(e=>!(n&&e.role===`assistant`&&e.turnId===n));this.archiveTrimmed=r.some(e=>e.trimmedArchive===!0);let i=new Set(r.map(e=>e.id)),a=this.messages.filter(e=>!i.has(e.id));this.messages=[...r,...a],this.contextUsage=null,this._dirtyFor=null,this.checkResumableTurn(),this.$nextTick(()=>this.scrollToBottom(!0))}catch{this.cardId===e&&(this.messages=[]),this._dirtyFor=null}finally{this.cardId===e&&(this.loadingHistory=!1)}}},serialize(){return this.messages.map(e=>{let t={id:e.id,role:e.role,content:e.content||``,ts:e.ts};return e.role===`assistant`?(t.reasoning=e.reasoning||``,t.reasoningMs=e.reasoningMs||0,t.error=e.error||``,e.errorCode&&(t.errorCode=e.errorCode),e.events?.length&&(t.events=e.events.map(e=>({ts:e.ts||0,level:e.level||`warn`,code:e.code||``,message:e.message||``}))),t.elapsedMs=e.elapsedMs||0,t.status=e.status===`streaming`?`aborted`:e.status||`done`,e.turnId&&(t.turnId=e.turnId),e.serverAuthored&&(t.serverAuthored=!0),e.budget?.message&&(t.budget={reason:e.budget.reason||``,message:e.budget.message}),e.usage&&(t.usage=e.usage),e.toolCalls?.length&&(t.toolCalls=e.toolCalls.map(e=>({toolCallId:e.toolCallId,toolName:e.toolName,args:e.args||{},result:e.result,error:e.error||``,ms:e.ms||0,startedAt:e.startedAt||0,command:e.command||``,approvalNote:e.approvalNote||``,autoApproved:!!e.autoApproved})))):e.attachments?.length&&(t.attachments=e.attachments.map(e=>({path:e.path,name:e.name,isDir:!!e.isDir,isImage:!!e.isImage,size:e.size||0,entryCount:e.entryCount||0,exists:e.exists!==!1}))),t})},revive(e){return{id:e.id||kN(),role:e.role===`user`?`user`:`assistant`,content:e.content||``,reasoning:e.reasoning||``,reasoningMs:e.reasoningMs||0,elapsedMs:Number(e.elapsedMs)||0,toolCalls:Array.isArray(e.toolCalls)?e.toolCalls.map(t=>(e.status===`aborted`||e.status===`streaming`)&&t&&!t.error&&t.result==null?{...t,error:`已终止:该调用未拿到结果(轮次被中断)`}:t):[],attachments:Array.isArray(e.attachments)?e.attachments:[],events:Array.isArray(e.events)?e.events:[],error:e.error||``,errorCode:e.errorCode||``,trimmedArchive:e.trimmedArchive===!0,status:e.status||`done`,turnId:e.turnId||``,serverAuthored:e.serverAuthored===!0,budget:e.budget?.message?{reason:e.budget.reason||``,message:e.budget.message}:void 0,ts:e.ts||0}},persist(){this.cardId&&(this._dirtyFor=this.cardId,this._saveTimer&&clearTimeout(this._saveTimer),this._saveTimer=setTimeout(()=>this.flushHistory(),500))},fitArchive(e){if(uN(e)<=4e6)return e;let t=pN(e,!1);return uN(t)>4e6&&(t=pN(t,!0)),this.archiveTrimmed=!0,t},async flushHistory(e=this.cardId,t=null){if(this._saveTimer&&=(clearTimeout(this._saveTimer),0),e){if(this._saving){this._saveTimer=setTimeout(()=>this.flushHistory(e,t),800);return}this._saving=!0;try{await MO(e,this.fitArchive(t||this.serialize())),this._dirtyFor===e&&(this._dirtyFor=null)}catch(e){this.notify(`warn`,`对话记录保存失败:${e.message||e}`)}finally{this._saving=!1}}},migrateCard(e,t){!e||!t||e===t||this.cardId===e&&(this._saveTimer&&=(clearTimeout(this._saveTimer),0),this._cardRenamedTo=t,this._dirtyFor===e&&(this._dirtyFor=t))},discardCard(e){e&&(this._saveTimer&&=(clearTimeout(this._saveTimer),0),this._dirtyFor===e&&(this._dirtyFor=null),(this._loadedCard===e||this.cardId===e)&&(this.busy&&this._abort&&this._abort.abort(),this.messages=[],this.draftAttachments=[],this.contextUsage=null,this._loadedCard=``))},askClear(){this.messages.length&&(this.confirmClear=!0)},async doClear(){this.confirmClear=!1;let e=this.cardId;this.messages=[],this.contextUsage=null,this._loadedCard=e,this._dirtyFor=null,this._saveTimer&&=(clearTimeout(this._saveTimer),0);try{await NO(e),this.notify(`ok`,`已清空本卡片的对话记录`)}catch(e){this.notify(`warn`,`清空失败:${e.message||e}`)}},async onPick(e){try{let t=await EO(e);if(t.cancelled)return;for(let e of t.items||[])this.pushAttachment(e);t.items?.length||this.notify(`warn`,`未选到可用文件`)}catch(e){this.notify(`warn`,e.message||`无法调起系统选择器,可改用拖拽或粘贴路径`)}},async onAddPath(e){try{let t=await DO(e);this.pushAttachment(t)}catch(t){this.notify(`warn`,`路径不可用:${e}(${t.message||t})`)}},async onPasteImage(e){try{let t=await kO(e);this.pushAttachment(t,`粘贴的截图已存到本机 .cache/ai-attachments/`)}catch(e){this.notify(`warn`,`截图保存失败:${e.message||e}`)}},async onDropFiles(e){let t=Array.from(e.items||[]).map(e=>e.webkitGetAsEntry?e.webkitGetAsEntry():null).filter(Boolean),n=Array.from(e.files||[]),r=[];if(t.length)for(let e of t)r.push(this.resolveEntry(e));else for(let e of n)r.push(this.resolveFile(e));if(!r.length){this.notify(`warn`,`没有识别到可挂载的文件`);return}let i=(await Promise.all(r)).filter(e=>!e).length;i&&this.notify(`warn`,`${i} 项未能定位本机路径,可改用「粘贴路径」添加`)},async resolveEntry(e){if(e.isDirectory){let t=await this.firstFileInDir(e);return this.resolveByName(e.name,e.fullPath||e.name,t?.size??-1)}let t=await this.entryToFile(e);return t?this.resolveFile(t):this.resolveByName(e.name,e.fullPath||e.name,-1)},async resolveFile(e){return this.resolveByName(e.name,e.webkitRelativePath||e.name,e.size)},async resolveByName(e,t,n){let r={path:``,name:e,isDir:!1,isImage:!1,pending:!0};this.draftAttachments=[...this.draftAttachments,r];try{let i=await OO({name:e,relPath:t,size:n});return this.draftAttachments=this.draftAttachments.filter(e=>e!==r),this.pushAttachment(i),i}catch{return this.draftAttachments=this.draftAttachments.filter(e=>e!==r),null}},entryToFile(e){return new Promise(t=>{try{e.file(e=>t(e),()=>t(null))}catch{t(null)}})},firstFileInDir(e){return new Promise(t=>{try{e.createReader().readEntries(async e=>{for(let n of e||[])if(!n.isDirectory){let e=await this.entryToFile(n);if(e)return t(e)}t(null)},()=>t(null))}catch{t(null)}})},pushAttachment(e,t){e?.path&&(this.draftAttachments.some(t=>t.path===e.path)||(this.draftAttachments=[...this.draftAttachments,{...e,note:t}],t&&this.notify(`ok`,t)))},removeAttachment(e){this.draftAttachments=this.draftAttachments.filter(t=>t.path!==e||t.pending)},useSuggestion(e){this.$refs.composerEl?.setText(e.text),this.trackSuggest(e)},shuffleSuggestions(){let e=this.suggestBatch.length;e&&(this.suggestOffset=(this.suggestOffset+4)%e)},trackSuggest(e){if(!(!e||!e.id)){this.suggestStats[e.id]=(this.suggestStats[e.id]||0)+1;try{window.dispatchEvent(new CustomEvent(`cardbuddy:suggest`,{detail:{id:e.id,label:e.label,weight:e.weight,batch:this.suggestBatchKey}}))}catch{}}},async onSend({text:e,attachments:t}){if(this.busy||!await this.ensureConfig())return;this.notice=null;let n={id:kN(`u`),role:`user`,content:e,attachments:t.map(e=>({...e})),ts:Date.now()};this.messages.push(n),this.draftAttachments=[],this.pinned=!0,await this.runTurn({retractMsgId:n.id,draft:{text:e,attachments:n.attachments}})},async ensureConfig(){return await this.refreshConfig(),this.configReady?!0:(this.modelListOpen=!0,this.loadModels(),this.notify(`warn`,`请先在模型库中添加并配置模型(Base URL / API Key / 模型名)`),!1)},onContinue(){this.busy||this.onSend({text:`继续`,attachments:[]})},async regenerate(e){if(this.busy)return;let t=this.messages.findIndex(t=>t.id===e.id);t>0&&(this.messages=this.messages.slice(0,t)),await this.runTurn()},async runTurn(e={}){this.messages.push({id:kN(`a`),role:`assistant`,content:``,reasoning:``,reasoningMs:0,toolCalls:[],events:[],error:``,status:`streaming`,ts:Date.now()});let t=this.messages[this.messages.length-1],n=t.id;this.busy=!0,this.pinned=!0,this.startTurn();let r=new AbortController;this._abort=r;let i=!1,a=Date.now(),o=()=>{t.reasoning&&!t.reasoningMs&&(t.reasoningMs=Date.now()-a)};try{await FO({messages:this.toWire(this.messages.filter(e=>e.id!==n)),cardContext:this.cardId?{id:this.cardId}:void 0,attachments:this.lastAttachments(),signal:r.signal,onEvent:e=>this.onEvent(e,t,o)}),t.status===`streaming`&&(t.status=`done`)}catch(a){let s=r.signal.aborted||/abort/i.test(String(a?.message||a));o(),a?.code===`turn-in-flight`?(i=!0,this.messages=this.messages.filter(t=>t.id!==n&&t.id!==e.retractMsgId),e.draft&&(this.draftAttachments=(e.draft.attachments||[]).map(e=>({...e})),this.$refs.composerEl?.setText(e.draft.text||``)),this.notify(`warn`,String(a?.message||`这张卡片已有一个回合在跑:请先终止或等它结束,再发新消息`)),this.$nextTick(()=>this.checkResumableTurn())):s?t.status=`aborted`:await this.reattachAfterDrop(t,o)?this.pushEvent(t,{level:`info`,code:`stream-resumed`,message:`已接回本回合,继续跟随进度`}):(t.error=String(a?.message||a),t.errorCode=String(a?.code||``),t.status=`error`)}finally{o(),this.endTurn(t,{rejected:i})}},endTurn(e,{rejected:t=!1}={}){e.status===`streaming`&&(e.status=`done`),t||(e.elapsedMs=Math.max(0,Date.now()-this.turnStartedAt)),this.busy=!1,this._abort=null,this.stopTurnTimers(),this.persist(),this.$emit(`busy`,!1),t||this.$emit(`turn-finished`,{status:e.status,error:e.error||``,steps:this.turnStep,ms:Date.now()-this.turnStartedAt,startedAt:this.turnStartedAt,finishedAt:Date.now(),turnId:this.turnId||e.turnId||``}),this.$nextTick(()=>this.scrollToBottom())},async checkResumableTurn(){let e=this.cardId;if(!(!e||this.busy||this._resumeProbe)){this._resumeProbe=!0;try{let t;try{t=await IO(e)}catch{return}let n=t&&t.active;if(!n||!n.turnId||this.cardId!==e||this.busy)return;await this.attachToTurn({cardId:e,turnId:String(n.turnId),startedAt:Number(n.startedAt)||0,afterSeq:0,note:n.detached?`接回一个仍在服务端运行的回合(上次连接已中断,进度与已落盘产物都在)`:`接回本回合的实时进度`})}finally{this._resumeProbe=!1}}},async attachToTurn({cardId:e,turnId:t,startedAt:n=0,afterSeq:r=0,note:i=``}){let a=this.messages.find(e=>e.role===`assistant`&&e.turnId===t);a||=(this.messages.push({id:kN(`a`),role:`assistant`,content:``,reasoning:``,reasoningMs:0,toolCalls:[],events:[],error:``,status:`streaming`,ts:n||Date.now(),turnId:t}),this.messages[this.messages.length-1]),a.content=``,a.reasoning=``,a.reasoningMs=0,a.toolCalls=[],a.events=[],a.error=``,a.errorCode=``,a.budget=void 0,a.status=`streaming`,a.turnId=t,this.busy=!0,this.pinned=!0,this.startTurn(),this.turnId=t,this.lastSeq=Number(r)||0,n&&(this.turnStartedAt=n,a.ts=n);let o=new AbortController;this._abort=o;let s=n||Date.now(),c=()=>{a.reasoning&&!a.reasoningMs&&(a.reasoningMs=Date.now()-s)};i&&this.notify(`warn`,i);try{this.lastSeq=await RO({cardId:e,turnId:t,afterSeq:this.lastSeq,signal:o.signal,onEvent:e=>this.onEvent(e,a,c)})}catch(e){o.signal.aborted||/abort/i.test(String(e?.message||e))||(a.error=String(e?.message||e),a.errorCode=String(e?.code||``),a.status=`error`)}finally{c(),this.endTurn(a)}},async reattachAfterDrop(e,t){let n=this.cardId,r=this.turnId||e.turnId,i=this._abort;if(!n||!r||!i||i.signal.aborted)return!1;try{return this.pushEvent(e,{level:`warn`,code:`stream-dropped`,message:`连接中断:正在按断点续订本回合(服务端仍在跑,已执行的写入不受影响)`}),this.lastSeq=await RO({cardId:n,turnId:r,afterSeq:this.lastSeq,signal:i.signal,onEvent:n=>this.onEvent(n,e,t)}),!0}catch{return!1}},onEvent(e,t,n){this.lastByteAt=Date.now();let r=Number(e.seq)||0;switch(r>this.lastSeq&&(this.lastSeq=r),e.type){case`turn-start`:e.turnId&&(this.turnId=String(e.turnId),t.turnId=String(e.turnId)),Number(e.startedAt)&&(this.turnStartedAt=Number(e.startedAt),t.ts=Number(e.startedAt));break;case`client-detached`:this.pushEvent(t,{level:`info`,code:`client-detached`,message:`连接曾中断,回合在服务端继续跑(事件已全部落日志)`});break;case`turn-end`:(e.status===`aborted`||e.status===`error`)&&(t.status=e.status),e.usage&&this.applyUsage(t,e.usage);break;case`usage`:this.applyUsage(t,e);break;case`reasoning-delta`:t.reasoning+=e.text||``;break;case`text-delta`:n(),t.content+=e.text||``;break;case`tool-call-start`:n(),this.findToolRow(t,e)||t.toolCalls.push({toolCallId:e.toolCallId||kN(`tc`),toolName:e.toolName,args:{},pending:!0,result:void 0,error:``,startedAt:Date.now(),ms:0});break;case`tool-call`:{n();let r=this.findToolRow(t,e);r?(e.toolCallId&&(r.toolCallId=e.toolCallId),e.toolName&&(r.toolName=e.toolName),r.args=e.args||{},r.pending=!1):t.toolCalls.push({toolCallId:e.toolCallId||kN(`tc`),toolName:e.toolName,args:e.args||{},result:void 0,error:``,startedAt:Date.now(),ms:0});break}case`tool-result`:{let n=t.toolCalls.find(t=>t.toolCallId===e.toolCallId||!e.toolCallId&&t.toolName===e.toolName&&t.result===void 0);n&&(n.result=e.result??``,n.truncated=!!e.truncated,e.error&&(n.error=String(e.error)),e.image&&(n.image=e.image),n.ms=Date.now()-(n.startedAt||Date.now())),this.persist();break}case`approval-request`:{let n=this.findToolRow(t,e)||t.toolCalls[t.toolCalls.length-1];n&&n.toolName===e.toolName&&n.result===void 0?(n.approvalId=e.approvalId,e.command&&(n.command=e.command),n.needsApproval=!0):t.toolCalls.push({toolCallId:e.toolCallId||kN(`tc`),toolName:e.toolName,args:e.args||{},command:e.command||``,approvalId:e.approvalId,needsApproval:!0,result:void 0,error:``,startedAt:Date.now(),ms:0});break}case`approval-decided`:{let n=(t.toolCalls||[]).find(t=>t.approvalId===e.approvalId);n&&(n.needsApproval=!1,n.approvalNote=e.ok?e.scope===`turn`?`已允许,本回合后续同类执行不再询问…`:`已允许,执行中…`:e.reason||`已拒绝执行`);break}case`approval-auto`:{let n=this.findToolRow(t,e)||[...t.toolCalls||[]].reverse().find(t=>t.toolName===e.toolName&&t.result===void 0);n&&(e.command&&(n.command=e.command),n.autoApproved=!0,n.approvalNote=`按设置免确认执行`);break}case`notice`:{let n=e.level===`info`||e.level===`error`?e.level:`warn`;this.pushEvent(t,{level:n,code:e.code||``,message:e.message||``}),n!==`info`&&this.notify(n===`error`?`danger`:`warn`,e.message||``);break}case`round-retry`:{let n=Number(e.dropReasoning)||0,r=Number(e.dropText)||0,i=Number(e.dropTools)||0;n>0&&(t.reasoning=t.reasoning.slice(0,Math.max(0,t.reasoning.length-n))),r>0&&(t.content=t.content.slice(0,Math.max(0,t.content.length-r))),i>0&&t.toolCalls.splice(Math.max(0,t.toolCalls.length-i),i),t.reasoning||(t.reasoningMs=0),this.pushEvent(t,{level:`warn`,code:`retry-${e.reason||`unknown`}`,message:e.message||``}),this.notify(`warn`,e.message||``);break}case`context-usage`:this.contextUsage={used:Number(e.used)||0,total:Number(e.total)||0,window:Number(e.window)||0};break;case`turn-ended`:t.budget={reason:String(e.reason||``),message:String(e.message||``)};break;case`error`:t.error=t.error?`${t.error}\n${e.message}`:String(e.message||``),e.code&&(t.errorCode=String(e.code)),t.status=`error`;break;case`aborted`:t.status=`aborted`}let i=t.toolCalls||[];this.turnStep=i.length;let a=i[i.length-1];if(a){this.turnToolLabel=`正在${OD(a.toolName)}…`;let e=FD(a);e&&(!this.turnStage||e.order>this.turnStage.order)&&(this.turnStage=e)}this.$nextTick(()=>this.scrollToBottom())},async onApproval({tc:e,ok:t,scope:n=`once`}){if(e?.approvalId){e.needsApproval=!1,e.approvalNote=t?n===`turn`?`已允许,本回合后续同类执行不再询问…`:`已允许,执行中…`:`已拒绝执行`;try{await AO({approvalId:e.approvalId,ok:t,scope:n})}catch(e){this.notify(`warn`,`审批提交失败:${e.message}`)}}},findToolRow(e,t){let n=e.toolCalls||[];if(t.toolCallId){let e=n.find(e=>e.toolCallId===t.toolCallId);if(e)return e}return n.find(e=>e.pending&&e.toolName===t.toolName)||null},stop(){this.confirmStop=!1;let e=this._abort,t=this.cardId,n=this.turnId||``;t&&n&&LO(t).catch(e=>{e?.code!==`no-turn`&&this.notify(`warn`,`终止请求未送达:${e.message}`)}),e&&(e.abort(),this.notify(`ok`,`已终止本次生成`))},doStop(){this.stop()},onEscape(){if(this.confirmStop){this.confirmStop=!1;return}if(this.confirmDeleteModel){this.confirmDeleteModel=null;return}if(this.commonOpen){this.commonOpen=!1;return}if(this.modelListOpen||this.modelEditOpen){this.modelListOpen=!1,this.modelEditOpen=!1;return}if(this.busy){this.confirmStop=!0;return}this.$emit(`close`)},lastAttachments(){for(let e=this.messages.length-1;e>=0;e--){let t=this.messages[e];if(t.role===`user`)return(t.attachments||[]).map(e=>({path:e.path,name:e.name,isDir:e.isDir,isImage:e.isImage}))}return[]},toWire(e){return e.map(e=>{if(e.role===`user`){let t=e.attachments||[],n=e.content||``;if(t.length){let e=t.map(e=>`- ${e.isDir?`文件夹`:e.isImage?`图片`:`文件`}:${e.path}`);n=`${n}${n?`
|
|
267
|
+
长任务里「卡在哪一步、卡了多久」全靠这三个数互相对齐 `),a.clockText?(B(),V(`span`,{key:3,class:`aitool__clock`,title:a.clockTitle},M(a.clockText),9,tO)):K(`v-if`,!0),a.msText?(B(),V(`span`,{key:4,class:`aitool__ms`,title:`本步耗时 ${a.msText}`},M(a.msText),9,nO)):K(`v-if`,!0)],8,YD),K(` 高危执行逐次确认:命令原文 + 允许一次 / 本回合不再询问 / 拒绝(Codex 审批的同款交互) `),n.tc.needsApproval?(B(),V(`div`,rO,[t[8]||=U(`svg`,{class:`aitool__approve-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`code`,{class:`aitool__approve-cmd`,title:a.approvalCommand},M(a.approvalCommand),9,iO),U(`span`,aO,M(n.tc.toolName===`skill_exec`?`技能脚本,需要你确认`:`本地命令,需要你确认`),1),U(`button`,{type:`button`,class:`aitool__approve-btn`,onClick:t[1]||=q(t=>e.$emit(`approval`,{tc:n.tc,ok:!0,scope:`once`}),[`stop`])},`允许一次`),U(`button`,{type:`button`,class:`aitool__approve-btn aitool__approve-btn--ghost`,onClick:t[2]||=q(t=>e.$emit(`approval`,{tc:n.tc,ok:!0,scope:`turn`}),[`stop`])},`本回合不再询问`),U(`button`,{type:`button`,class:`aitool__approve-btn aitool__approve-btn--deny`,onClick:t[3]||=q(t=>e.$emit(`approval`,{tc:n.tc,ok:!1}),[`stop`])},`拒绝`)])):n.tc.approvalNote?(B(),V(z,{key:1},[K(` 免确认策略命中:没有审批条,但照样把「跑了什么命令」摆出来,免确认不等于无痕迹 `),U(`div`,{class:j([`aitool__approve-note`,{"is-auto":n.tc.autoApproved}])},[U(`span`,oO,M(n.tc.approvalNote),1),n.tc.autoApproved&&n.tc.command?(B(),V(`code`,{key:0,class:`aitool__approve-cmd`,title:n.tc.command},M(n.tc.command),9,sO)):K(`v-if`,!0)],2)],2112)):K(`v-if`,!0),I(U(`div`,cO,[a.argsSource?(B(),H(o,{key:0,source:a.argsSource},null,8,[`source`])):K(`v-if`,!0),n.tc.image?(B(),V(`img`,{key:1,class:`aitool__shot`,src:`data:${n.tc.image.mime||`image/png`};base64,${n.tc.image.base64}`,alt:`卡片截图`},null,8,lO)):K(`v-if`,!0),n.tc.error?(B(),V(`div`,uO,M(n.tc.error),1)):a.resultSource?(B(),H(o,{key:3,source:a.resultSource},null,8,[`source`])):K(`v-if`,!0)],512),[[Sc,a.open]])],2)],2112)}var fO=X(JD,[[`render`,dO],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatToolRow.vue`]]);function pO(e){return`${Fl()||``}/__ai/fs/raw?path=${encodeURIComponent(e)}`}async function mO(e){let t=await e.json().catch(()=>({}));if(!e.ok){let n=``;try{n=new URL(e.url).pathname}catch{}let r=(e.status===404||e.status===405)&&n.startsWith(`/__ai/`)?`本地开发服务仍在运行改造前的旧代码(缺少该接口),请重启 npm run dev(cardbuddy)后重试`:t.message||t.error||`HTTP ${e.status}`,i=Error(r);throw i.code=t.error,i.payload=t,i}return t}async function hO(e=!1){return mO(await J(`/__ai/config${e?`?reveal=1`:``}`))}async function gO(e){return mO(await J(`/__ai/config`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}))}async function _O(){return mO(await J(`/__ai/models`))}async function vO(){return mO(await J(`/__ai/cc-switch-providers`))}async function yO(e,t=!1){return mO(await J(`/__ai/models/${encodeURIComponent(e)}${t?`?reveal=1`:``}`))}async function bO(e){return mO(await J(`/__ai/models`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}))}async function xO(e,t){return mO(await J(`/__ai/models/${encodeURIComponent(e)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)}))}async function SO(e){return mO(await J(`/__ai/models/${encodeURIComponent(e)}`,{method:`DELETE`}))}async function CO(e){return mO(await J(`/__ai/models/${encodeURIComponent(e)}/activate`,{method:`POST`}))}async function wO(e={}){let{baseUrl:t=``,apiKey:n=``,model:r=``}=e||{};return mO(await J(`/__ai/probe-maxtokens`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({baseUrl:t,apiKey:n,model:r})}))}async function TO(e){return mO(await J(`/__ai/ping`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)}))}async function EO(e=`image`){return mO(await J(`/__ai/fs/pick`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({kind:e,multiple:!0})}))}async function DO(e){return mO(await J(`/__ai/fs/stat?path=${encodeURIComponent(e)}`))}async function OO({name:e,relPath:t,size:n}){return mO(await J(`/__ai/fs/locate`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:e,relPath:t,size:n})}))}function kO(e,t,n=`request`){return new Promise((r,i)=>{let a=setTimeout(()=>{let e=Error(`${n}-timeout`);e.code=`timeout`,i(e)},t);e.then(e=>{clearTimeout(a),r(e)},e=>{clearTimeout(a),i(e)})})}async function AO(e){return mO(await J(`/__ai/fs/stash`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({dataUrl:e})}))}async function jO({approvalId:e,ok:t,scope:n=`once`}){return mO(await J(`/__ai/approve`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({approvalId:e,ok:t,scope:n})}))}async function MO(e){return e?mO(await J(`/__ai/history?cardId=${encodeURIComponent(e)}`)):{cardId:``,messages:[],updatedAt:0}}async function NO(e,t,n={}){return e?mO(await J(`/__ai/history`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({cardId:e,messages:t}),keepalive:n.keepalive===!0})):{ok:!1,error:`missing-card-id`}}async function PO(e){return e?mO(await J(`/__ai/history?cardId=${encodeURIComponent(e)}`,{method:`DELETE`})):{ok:!1,error:`missing-card-id`}}async function FO(e,t){let n=e.body.getReader(),r=new TextDecoder,i=``,a=e=>{i+=e;let n=i.split(`
|
|
268
|
+
`);i=n.pop()||``;for(let e of n){let n=e.trim();if(!n.startsWith(`data:`))continue;let r=n.slice(5).trim();if(!r)continue;let i;try{i=JSON.parse(r)}catch{continue}if(t(i)===!0)return!0}return!1};try{for(;;){let{done:e,value:t}=await n.read();if(e||a(r.decode(t,{stream:!0})))break}a(r.decode())}finally{try{n.releaseLock?.()}catch{}}}async function IO({messages:e,cardContext:t,attachments:n=[],config:r={},signal:i,onEvent:a}){let o=await J(`/__ai/chat`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({messages:e,cardContext:t,attachments:n,config:r}),signal:i});if(!o.ok||!o.body){let e=await o.json().catch(()=>({})),t=Error(e.message||e.error||`HTTP ${o.status}`);throw t.code=e.error||`http-${o.status}`,t.status=o.status,t.payload=e,t}await FO(o,e=>(a(e),e.type===`done`))}async function LO(e){return e?mO(await J(`/__ai/turns?cardId=${encodeURIComponent(e)}`)):{cardId:``,active:null,recent:[]}}async function RO(e){return e?mO(await J(`/__ai/stop`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({cardId:e})})):{ok:!1,error:`missing-card-id`}}async function zO({cardId:e,afterSeq:t=0,turnId:n=``,signal:r,onEvent:i}){if(!e){let e=Error(`缺少 cardId,无法续订回合`);throw e.code=`missing-card-id`,e}let a=new URLSearchParams({cardId:e,afterSeq:String(Number(t)||0)});n&&a.set(`turnId`,String(n));let o=await J(`/__ai/turn?${a}`,{signal:r});if(!o.ok||!o.body){let e=await o.json().catch(()=>({})),t=Error(e.message||e.error||`HTTP ${o.status}`);throw t.code=e.error||`http-${o.status}`,t.status=o.status,t}let s=Number(t)||0;return await FO(o,e=>{let t=Number(e.seq)||0;return t>s&&(s=t),i(e),!1}),s}var BO=`png|jpe?g|gif|webp|bmp|svg|avif|ico|tiff?`,VO=RegExp(`^(\\s*(?:[-*+]\\s+|\\d+[.)]\\s+)?)(?:(?:图|图片|预览图|预览|截图|设计稿|整图|效果图|封面|原图|缩略图|路径|image|img|preview|screenshot|pic|photo|file|path)\\s*[::]\\s*)?(\\/.+?\\.(?:${BO}))\\s*$`,`i`),HO=RegExp(`(^|[\\s(「『【>])((?:\\/(?!\\s))[^\`"'<>()\\[\\]{}\\s()「」『』【】,。;、!?:…·]+?\\.(?:${BO}))(?=\$|[\\s))」』】.,;:!?,。;、!?])`,`gi`),UO=/^\s*(?:```|~~~)/,WO=RegExp(`\\.(?:${BO})`,`i`),GO=RegExp(`(!\\[[^\\]]*\\]\\()\\s*(\\/(?!\\/)(?:[^\\s?#()]|\\([^\\s()]*\\))+?\\.(?:${BO}))(?=\\s*(?:"[^"]*"|'[^']*')?\\s*\\))`,`gi`);function KO(e){return(String(e).split(`/`).pop()||``).replace(/[[\]!]/g,``).trim().slice(0,120)||`预览图`}function qO(e){return String(e).replace(/"/g,`'`)}function JO(e){return String(e).replace(/\(/g,`%28`).replace(/\)/g,`%29`).replace(/ /g,`%20`)}function YO(e){let t=String(e);if(!t.includes(`%`))return t;try{return decodeURIComponent(t)}catch{return t}}function XO(e,t){let n=``;try{n=t(YO(e))}catch{return null}return n?JO(n):null}function ZO(e,t){let n=``;try{n=t(e)}catch{return null}if(!n)return null;let r=JO(n);return`}")`}function QO(e,t){let n=String(e??``);if(!n||typeof t!=`function`||!WO.test(n))return n;let r=!1;return n.split(`
|
|
269
|
+
`).map(e=>{if(UO.test(e))return r=!r,e;if(r||!WO.test(e))return e;let n=e.match(VO);if(n){let r=ZO(n[2],t);return r===null?e:n[1]+r}return e.replace(GO,(e,n,r)=>n+(XO(r,t)??r)).replace(HO,(e,n,r)=>n+(ZO(r,t)??r))}).join(`
|
|
270
|
+
`)}var $O=3,ek={name:`ChatMessage`,components:{MarkdownBody:ED,ChatToolRow:fO},props:{msg:{type:Object,required:!0},streaming:{type:Boolean,default:!1},compact:{type:Boolean,default:!1},canRollback:{type:Boolean,default:!1},nowTs:{type:Number,default:0},canRegenerate:{type:Boolean,default:!1}},emits:[`regenerate`,`approval`,`continue`,`rollback`,`open-settings`,`show-all-steps`,`locate-node`],data(){return{thinkOpen:!1,eventsOpen:null,copied:!1,elapsed:0,openGroups:Object.create(null),errorCopied:!1,_tick:0}},computed:{budgetLabel(){return{loop:`死循环熔断`,timeout:`墙钟熔断`,steps:`步数硬顶`}[this.msg.budget?.reason]||`本轮收尾`},budgetHint(){return{loop:`连续多轮同工具同参数 = 拿不到新信息。回复「继续」前最好补一句新思路(换证据链 / 指定要改的字段),否则大概率原地再转一次。`,timeout:`本轮跑到墙钟上限(AI_TURN_TIMEOUT_MS 可调)。回复「继续」会带着完整上下文从中断处接着做。`,steps:`你在设置里配了「单轮步数上限」。留空即不限步数,失控由死循环 / 墙钟熔断兜住。`}[this.msg.budget?.reason]||`上下文已保留,回复「继续」可接着做。`},attachments(){return Array.isArray(this.msg.attachments)?this.msg.attachments:[]},toolCalls(){return Array.isArray(this.msg.toolCalls)?this.msg.toolCalls:[]},msgTs(){return Number(this.msg.ts)||0},turnClock(){let e=this.msgTs,t=Number(this.msg.elapsedMs)||0,n=e&&t>0?e+t:0;if(!n)for(let e of this.toolCalls)n=Math.max(n,PD(e,this.nowTs));return{stamp:MD(e),endStamp:n>e?MD(n):``,total:n>e?jD(n-e):``}},toolGroups(){let e=[],t=[],n=()=>{if(t.length>=$O)e.push({kind:`group`,key:`g-${t[0].toolCallId||e.length}`,toolName:t[0].toolName,rows:t.slice(),ms:t.reduce((e,t)=>e+(Number(t.ms)||0),0),failed:t.filter(e=>e.error).length,clock:this.groupClock(t)});else for(let n of t)e.push({kind:`row`,key:n.toolCallId||`r-${e.length}`,tc:n});t=[]};for(let e of this.toolCalls)if(!(this.compact&&!RD(e))){if(t.length&&t[0].toolName===e.toolName){t.push(e);continue}n(),t=[e]}return n(),e},hiddenSteps(){return this.compact?this.toolCalls.filter(e=>!RD(e)).length:0},summary(){return GD(this.toolCalls)},showSummary(){if(this.streaming)return!1;let e=this.summary;return!!(e.writes||e.writeFails||e.gate||e.validate||e.failed||this.cacheBadge)},cacheBadge(){let e=this.msg.usage;if(!e||!Number(e.promptTokens))return null;let t=Number(e.promptTokens)||0,n=Number(e.cachedTokens)||0,r=Number(e.steps)||0,i=e=>e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e);if(!e.reported)return{label:`缓存未提供`,ok:!1,title:`本回合累计输入 ${i(t)} token(${r} 步):该网关未回缓存命中字段,无法统计命中率`};let a=Number(e.hitRate)||0;return{label:`缓存命中 ${a}%`,ok:a>=50,title:`本回合累计输入 ${i(t)} token(${r} 步,命中 ${i(n)} / 未命中 ${i(t-n)}):命中量按网关的 64 token 块对齐,未命中部分多为本轮新增的工具结果与收尾提示`}},validateIssues(){let e=this.summary.validate;return e&&Array.isArray(e.issues)?e.issues:[]},validateMore(){let e=this.summary.validate;return e?Math.max(0,(e.errors||0)+(e.warnings||0)-this.validateIssues.length):0},advice(){return this.msg.error?qD(this.msg.errorCode||``):{hint:``,action:``}},errorHint(){return this.advice.hint},errorAction(){return this.advice.action},events(){return Array.isArray(this.msg.events)?this.msg.events:[]},hasErrorEvent(){return this.events.some(e=>e.level===`error`)},eventsExpanded(){return this.eventsOpen===null?this.hasErrorEvent:this.eventsOpen},eventsLabel(){let e=this.events.filter(e=>e.level!==`info`).length;return e?`过程事件 ${this.events.length} 条(${e} 条需留意)`:`过程事件 ${this.events.length} 条`},bodyText(){return QO(String(this.msg.content||``).replace(/\n*\[\s*(?:任务完成|需用户确认)\s*\]\s*$/,``).trimEnd(),pO)},thinking(){return!!(this.streaming&&!this.msg.content&&!this.toolCalls.length)},streamingText(){return!!(this.streaming&&this.msg.content)},waiting(){return!!(this.streaming&&!this.msg.reasoning&&!this.msg.content&&!this.toolCalls.length&&!this.msg.error)},thinkLabel(){return this.thinking?`思考中… ${this.fmtClock(this.elapsedMs)}`:`已思考 ${this.fmtClock(this.msg.reasoningMs||this.elapsedMs)}`},elapsedMs(){return this.thinking?this.elapsed:this.msg.reasoningMs||this.elapsed},peek(){let e=String(this.msg.reasoning||``).split(`
|
|
271
|
+
`).map(e=>e.trim()).filter(Boolean),t=e[e.length-1]||``;return t.length>72?`${t.slice(0,72)}…`:t}},watch:{streaming:{immediate:!0,handler(e){e?this.startTick():this.stopTick()}},thinking(e){e||this.stopTick()}},beforeUnmount(){this.stopTick()},updated(){let e=this.$refs.thinkPre;e&&this.thinkOpen&&this.thinking&&(e.scrollTop=e.scrollHeight)},methods:{startTick(){this.stopTick(),this.elapsed=0,this._tick=setInterval(()=>{this.elapsed+=250},250)},stopTick(){this._tick&&clearInterval(this._tick),this._tick=0},fmtStamp:MD,fmtClock:jD,evOff(e){let t=Number(e&&e.ts)||0;return t>this.msgTs?ND(t-this.msgTs):``},groupClock(e){let t=PD(e[e.length-1],this.nowTs),n=t>this.msgTs?ND(t-this.msgTs):``;return[MD(e[0]&&e[0].startedAt),n].filter(Boolean).join(` · `)},fileUrl(e){return pO(e)},attSub(e){return e.exists===!1?`路径不可读`:e.isDir?`${e.entryCount??e.entries?.length??0} 项`:this.formatSize(e.size)},formatSize(e){let t=Number(e||0);return t?t<1024?`${t} B`:t<1048576?`${(t/1024).toFixed(1)} KB`:`${(t/1024/1024).toFixed(1)} MB`:`0 B`},toolLabel:OD,msText(e){let t=Number(e)||0;return t?t<1e3?`${t}ms`:`${(t/1e3).toFixed(1)}s`:``},groupOpen(e){let t=this.openGroups[e.key];if(t!==void 0)return t;if(e.failed)return!0;let n=e.rows[e.rows.length-1];return!!(n&&n.result===void 0&&!n.error)},toggleGroup(e){this.openGroups={...this.openGroups,[e.key]:!this.groupOpen(e)}},onApproval(e){this.$emit(`approval`,e)},async copyError(){await op(`${this.msg.errorCode?`[${this.msg.errorCode}] `:``}${String(this.msg.error||``)}`)&&(this.errorCopied=!0,setTimeout(()=>{this.errorCopied=!1},1600))},async copyText(){await op(String(this.msg.content||``))&&(this.copied=!0,setTimeout(()=>{this.copied=!1},1600))}}},tk={key:0,class:`aimsg__files`},nk=[`title`],rk=[`src`,`alt`],ik={key:1,class:`aifile__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},ak=[`href`],ok={class:`aifile__meta`},sk={class:`aifile__name`},ck={class:`aifile__sub`},lk={key:1,class:`aimsg__bubble`},uk=[`aria-expanded`],dk={key:0,class:`aithink__spin`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},fk={key:1,class:`aithink__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},pk={class:`aithink__label`},mk={key:2,class:`aithink__peek`},hk={class:`aithink__body`},gk={key:1,class:`aiwait`},_k=[`aria-expanded`,`onClick`],vk={class:`aitool__status`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},yk=[`href`],bk={class:`aitool__name`},xk={class:`aitool__count`},Sk={class:`aitool__args`},Ck=[`title`],wk=[`title`],Tk={class:`aitool__groupbody`},Ek=[`aria-expanded`],Dk={class:`aiev__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},Ok=[`href`],kk={class:`aiev__label`},Ak={class:`aiev__body`},jk={class:`aiev__time`},Mk={key:0,class:`aiev__off`,title:`距本轮开始的累计耗时`},Nk={class:`aiev__msg`},Pk={key:5,class:`aisum`},Fk={class:`aisum__head`},Ik=[`title`],Lk={class:`aisum__chips`},Rk={key:0,class:`aisum__chip aisum__chip--ok`},zk={key:1,class:`aisum__chip aisum__chip--danger`},Bk={key:2,class:`aisum__chip`},Vk={key:4,class:`aisum__chip aisum__chip--warn`},Hk=[`title`],Uk={key:1,class:`aisum__issues`},Wk={class:`aisum__issue-list`},Gk={class:`aisum__issue-text`},Kk=[`title`,`onClick`],qk={key:0,class:`aisum__issues-more`},Jk={key:6,class:`aimsg__error`},Yk={class:`aimsg__error-main`},Xk={class:`aimsg__error-text`},Zk={key:0,class:`aimsg__error-hint`},Qk={key:1,class:`aimsg__error-time`},$k={key:2,class:`aimsg__error-acts`},eA={key:7,class:`aimsg__aborted`},tA={key:0,class:`aimsg__aborted-time`},nA=[`title`],rA={class:`aimsg__budget-text`},iA={key:9,class:`aimsg__acts`},aA=[`title`],oA={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},sA=[`href`];function cA(e,t,n,r,i,a){let o=L(`ChatToolRow`),s=L(`MarkdownBody`);return B(),V(`article`,{class:j([`aimsg`,[`aimsg--${n.msg.role}`,{"aimsg--live":n.streaming}]])},[K(` ===== 用户消息:附件芯片 + 文本气泡 ===== `),n.msg.role===`user`?(B(),V(z,{key:0},[a.attachments.length?(B(),V(`div`,tk,[(B(!0),V(z,null,R(a.attachments,e=>(B(),V(`div`,{key:e.path,class:j([`aifile`,{"aifile--dir":e.isDir,"aifile--missing":e.exists===!1}]),title:e.path},[e.isImage?(B(),V(`img`,{key:0,class:`aifile__thumb`,src:a.fileUrl(e.path),alt:e.name,loading:`lazy`},null,8,rk)):(B(),V(`svg`,ik,[U(`use`,{href:e.isDir?`#icon-folder-plus`:`#icon-file-text`},null,8,ak)])),U(`span`,ok,[U(`span`,sk,M(e.name),1),U(`span`,ck,M(a.attSub(e)),1)])],10,nk))),128))])):K(`v-if`,!0),n.msg.content?(B(),V(`div`,lk,M(n.msg.content),1)):K(`v-if`,!0)],64)):(B(),V(z,{key:1},[K(` ===== 助手消息:思考 → 工具 → 正文(与 Codex 同序) ===== `),K(` 思考过程:默认折叠成一行,进行中给「计时 + 最新一行」预览,结束收成「已思考 N 秒」 `),n.msg.reasoning?(B(),V(`div`,{key:0,class:j([`aithink`,{"is-open":i.thinkOpen,"is-live":a.thinking}])},[U(`button`,{type:`button`,class:`aithink__head`,"aria-expanded":i.thinkOpen?`true`:`false`,onClick:t[0]||=e=>i.thinkOpen=!i.thinkOpen},[t[14]||=U(`svg`,{class:`aithink__chev`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron-right`})],-1),a.thinking?(B(),V(`svg`,dk,[...t[12]||=[U(`use`,{href:`#icon-loading`},null,-1)]])):(B(),V(`svg`,fk,[...t[13]||=[U(`use`,{href:`#icon-sparkles`},null,-1)]])),U(`span`,pk,M(a.thinkLabel),1),a.thinking&&!i.thinkOpen?(B(),V(`span`,mk,M(a.peek),1)):K(`v-if`,!0)],8,uk),I(U(`div`,hk,[U(`pre`,{ref:`thinkPre`},M(n.msg.reasoning),513)],512),[[Sc,i.thinkOpen]])],2)):K(`v-if`,!0),K(` 首个 token 之前的等待态 `),a.waiting?(B(),V(`div`,gk,[...t[15]||=[U(`span`,{class:`aiwait__dot`},null,-1),U(`span`,{class:`aiwait__dot`},null,-1),U(`span`,{class:`aiwait__dot`},null,-1),U(`span`,{class:`aiwait__text`},`正在思考`,-1)]])):K(`v-if`,!0),K(` 工具调用:平铺单次调用;连续同名 ≥3 次折叠成分组行(长任务里几十次 card_read 不该刷屏)。
|
|
272
|
+
行标记抽到 ChatToolRow:分组内成员与平铺行走同一份模板,两处不会漂移 `),(B(!0),V(z,null,R(a.toolGroups,e=>(B(),V(z,{key:e.key},[e.kind===`row`?(B(),H(o,{key:0,tc:e.tc,"turn-ts":a.msgTs,"now-ts":n.nowTs,onApproval:a.onApproval},null,8,[`tc`,`turn-ts`,`now-ts`,`onApproval`])):(B(),V(`div`,{key:1,class:j([`aitool aitool--group`,[e.failed?`aitool--error`:`aitool--done`,{"is-open":a.groupOpen(e)}]])},[U(`button`,{type:`button`,class:`aitool__head`,"aria-expanded":a.groupOpen(e)?`true`:`false`,onClick:t=>a.toggleGroup(e)},[t[16]||=U(`svg`,{class:`aitool__chev`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron-right`})],-1),(B(),V(`svg`,vk,[U(`use`,{href:e.failed?`#icon-alert-triangle`:`#icon-check`},null,8,yk)])),U(`span`,bk,M(a.toolLabel(e.toolName)),1),U(`span`,xk,`×`+M(e.rows.length),1),U(`code`,Sk,M(e.failed?`${e.failed} 次失败,点开看原因`:`连续 ${e.rows.length} 次,点开逐条查看`),1),K(` 分组行同样给「首次调用时刻 · 累计到最后一次」:折叠不等于把时间线也折掉 `),e.clock?(B(),V(`span`,{key:0,class:`aitool__clock`,title:`首次调用 ${e.clock.split(` · `)[0]} · 距本轮开始的累计耗时(算到最后一次)`},M(e.clock),9,Ck)):K(`v-if`,!0),e.ms?(B(),V(`span`,{key:1,class:`aitool__ms`,title:`${e.rows.length} 次调用合计耗时`},M(a.msText(e.ms)),9,wk)):K(`v-if`,!0)],8,_k),I(U(`div`,Tk,[(B(!0),V(z,null,R(e.rows,e=>(B(),H(o,{key:e.toolCallId,tc:e,"turn-ts":a.msgTs,"now-ts":n.nowTs,onApproval:a.onApproval},null,8,[`tc`,`turn-ts`,`now-ts`,`onApproval`]))),128))],512),[[Sc,a.groupOpen(e)]])],2))],64))),128)),K(` 紧凑视图折叠掉的读取类调用:留一行出口,一键回到全量视图(不必去面板头部找开关) `),a.hiddenSteps?(B(),V(`button`,{key:2,type:`button`,class:`aitool__hidden`,onClick:t[1]||=t=>e.$emit(`show-all-steps`)},[t[17]||=U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-eye`})],-1),U(`span`,null,`紧凑视图已折叠 `+M(a.hiddenSteps)+` 次读取类调用,点这里显示全部步骤`,1)])):K(`v-if`,!0),K(` 过程事件时间线:后端 notice / round-retry 的持久落点。横幅只留最近一条且 6 秒即逝,
|
|
273
|
+
「上下文折叠过几次 / 自动续跑过几次 / 网关重试过没有」这些线索全靠这里留存 `),a.events.length?(B(),V(`div`,{key:3,class:j([`aiev`,{"is-open":a.eventsExpanded}])},[U(`button`,{type:`button`,class:`aiev__head`,"aria-expanded":a.eventsExpanded?`true`:`false`,onClick:t[2]||=e=>i.eventsOpen=!a.eventsExpanded},[t[18]||=U(`svg`,{class:`aiev__chev`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron-right`})],-1),(B(),V(`svg`,Dk,[U(`use`,{href:a.hasErrorEvent?`#icon-alert-triangle`:`#icon-activity`},null,8,Ok)])),U(`span`,kk,M(a.eventsLabel),1)],8,Ek),I(U(`ol`,Ak,[(B(!0),V(z,null,R(a.events,(e,t)=>(B(),V(`li`,{key:t,class:j([`aiev__row`,`aiev__row--${e.level}`])},[U(`span`,jk,M(a.fmtStamp(e.ts)),1),a.evOff(e)?(B(),V(`span`,Mk,M(a.evOff(e)),1)):K(`v-if`,!0),U(`span`,Nk,M(e.message),1)],2))),128))],512),[[Sc,a.eventsExpanded]])],2)):K(`v-if`,!0),K(` 正文:Markdown(流式重渲染 + 代码块高亮 / 复制) `),a.bodyText?(B(),H(s,{key:4,class:j([`aimsg__md`,{"is-streaming":a.streamingText}]),source:a.bodyText,streaming:a.streamingText},null,8,[`class`,`source`,`streaming`])):K(`v-if`,!0),K(` 本次改动摘要:写入次数 / 校验错误 / 门禁结论都从工具行就地算——落盘记录里同样算得出来,
|
|
274
|
+
所以重开面板、刷新之后这条摘要依然在,而不是只在当轮可见 `),a.showSummary?(B(),V(`div`,Pk,[U(`span`,Fk,[t[20]||=U(`svg`,{class:`aisum__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-activity`})],-1),t[21]||=U(`span`,{class:`aisum__title`},`本次改动`,-1),K(` 本轮的时间坐标:几点开始、一共跑了多久。摘要条是回合的收尾锚点,这两个数在这里最有用 `),a.turnClock.stamp?(B(),V(`span`,{key:0,class:`aisum__clock`,title:`本轮 ${a.turnClock.stamp} 开始${a.turnClock.endStamp?`,${a.turnClock.endStamp} 收尾`:``}`},[G(M(a.turnClock.stamp)+` 开始`,1),a.turnClock.total?(B(),V(z,{key:0},[G(` · 累计 `+M(a.turnClock.total),1)],64)):K(`v-if`,!0)],8,Ik)):K(`v-if`,!0),U(`span`,Lk,[a.summary.writes?(B(),V(`span`,Rk,`写入 `+M(a.summary.writes)+` 次`,1)):K(`v-if`,!0),a.summary.writeFails?(B(),V(`span`,zk,`写入失败 `+M(a.summary.writeFails)+` 次`,1)):K(`v-if`,!0),a.summary.shots?(B(),V(`span`,Bk,`截图自检 `+M(a.summary.shots)+` 次`,1)):K(`v-if`,!0),a.summary.validate?(B(),V(`span`,{key:3,class:j([`aisum__chip`,a.summary.validate.ok?`aisum__chip--ok`:`aisum__chip--danger`])},`校验 `+M(a.summary.validate.errors)+` 错 / `+M(a.summary.validate.warnings)+` 警`,3)):K(`v-if`,!0),a.summary.failed?(B(),V(`span`,Vk,M(a.summary.failed)+` 次调用报错`,1)):K(`v-if`,!0),a.cacheBadge?(B(),V(`span`,{key:5,class:j([`aisum__chip`,a.cacheBadge.ok?`aisum__chip--ok`:``]),title:a.cacheBadge.title},M(a.cacheBadge.label),11,Hk)):K(`v-if`,!0)]),n.canRollback&&a.summary.writes?(B(),V(`button`,{key:1,type:`button`,class:`aisum__rollback`,title:`取本轮第一次写入前的历史快照,回到 AI 动手之前的版本;回滚本身可再撤销,确认后仍需点「保存到本地」才落盘`,onClick:t[3]||=t=>e.$emit(`rollback`,n.msg)},[...t[19]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-undo`})],-1),U(`span`,null,`回滚到本轮之前`,-1)]])):K(`v-if`,!0)]),K(` 门禁结论原样透出:这是唯一的机器判定,不能被模型自述的「已通过」覆盖 `),a.summary.gate?(B(),V(`p`,{key:0,class:j([`aisum__verdict`,a.summary.gate.passed?`is-pass`:`is-fail`])},[U(`strong`,null,`收尾门禁`+M(a.summary.gate.passed?`通过`:`未通过`),1),a.summary.gate.verdict?(B(),V(z,{key:0},[G(`:`+M(a.summary.gate.verdict),1)],64)):K(`v-if`,!0)],2)):K(`v-if`,!0),K(` 校验问题可点定位(P2-14):校验器在每条消息末尾挂了 #componentId,点「定位」就在画布与
|
|
275
|
+
组件结构里选中那个节点——不用再照着一句 "at depth 1[0]" 自己去树里翻 `),a.validateIssues.length?(B(),V(`div`,Uk,[t[22]||=U(`p`,{class:`aisum__issues-head`},[G(`校验问题`),U(`span`,{class:`aisum__issues-hint`},`点「定位」跳到该节点`)],-1),U(`ul`,Wk,[(B(!0),V(z,null,R(a.validateIssues,(t,n)=>(B(),V(`li`,{key:n,class:j([`aisum__issue`,t.level===`error`?`is-error`:`is-warn`])},[U(`span`,Gk,M(t.text),1),t.cid?(B(),V(`button`,{key:0,type:`button`,class:`aisum__issue-go`,title:`在画布与组件结构中定位 `+t.cid,onClick:n=>e.$emit(`locate-node`,t.cid)},`定位`,8,Kk)):K(`v-if`,!0)],2))),128))]),a.validateMore?(B(),V(`p`,qk,`另有 `+M(a.validateMore)+` 条:展开对应工具行看全部原文`,1)):K(`v-if`,!0)])):K(`v-if`,!0)])):K(`v-if`,!0),n.msg.error?(B(),V(`div`,Jk,[t[23]||=U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`span`,Yk,[U(`span`,Xk,M(n.msg.error),1),K(` 错误分级:后端给 code,这里给「怎么办」与对应的定向动作,不再只丢一句原文让人自己猜 `),a.errorHint?(B(),V(`span`,Zk,M(a.errorHint),1)):K(`v-if`,!0),K(` 失败也要有时刻与累计:报网关工单 / 对后端日志时,「几点失败、跑了多久」是第一句要交代的话 `),a.turnClock.endStamp?(B(),V(`span`,Qk,M(a.turnClock.endStamp)+` 失败 · 本轮已用 `+M(a.turnClock.total),1)):K(`v-if`,!0),n.streaming?K(`v-if`,!0):(B(),V(`span`,$k,[a.errorAction===`settings`?(B(),V(`button`,{key:0,type:`button`,class:`aimsg__budget-go`,onClick:t[4]||=t=>e.$emit(`open-settings`)},`打开设置`)):K(`v-if`,!0),n.canRegenerate?(B(),V(`button`,{key:1,type:`button`,class:`aimsg__budget-go`,onClick:t[5]||=t=>e.$emit(`regenerate`,n.msg)},`重试本轮`)):K(`v-if`,!0),n.canRegenerate?(B(),V(`button`,{key:2,type:`button`,class:`aimsg__budget-go aimsg__budget-go--ghost`,onClick:t[6]||=t=>e.$emit(`continue`)},`从中断处继续`)):K(`v-if`,!0),U(`button`,{type:`button`,class:`aimsg__budget-go aimsg__budget-go--ghost`,onClick:t[7]||=(...e)=>a.copyError&&a.copyError(...e)},M(i.errorCopied?`已复制`:`复制错误`),1)]))])])):K(`v-if`,!0),K(` 手动终止同样给续跑入口:已落盘产物与上下文都还在,点一下就能接着做。
|
|
276
|
+
此前只有熔断收尾(budget)分支有按钮,手滑终止后用户只能自己打字 `),n.msg.status===`aborted`?(B(),V(`div`,eA,[t[24]||=U(`span`,{class:`aimsg__aborted-text`},`已终止生成`,-1),a.turnClock.endStamp?(B(),V(`span`,tA,M(a.turnClock.endStamp)+` 终止 · 已用 `+M(a.turnClock.total),1)):K(`v-if`,!0),n.canRegenerate&&!n.streaming?(B(),V(`button`,{key:1,type:`button`,class:`aimsg__budget-go`,onClick:t[8]||=t=>e.$emit(`continue`)},`从中断处继续`)):K(`v-if`,!0)])):n.msg.budget?.message?(B(),V(`div`,{key:8,class:`aimsg__budget`,title:a.budgetHint},[t[25]||=U(`svg`,{class:`aimsg__budget-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`span`,rA,[U(`strong`,null,M(a.budgetLabel),1),G(`:`+M(n.msg.budget.message)+`(上下文已保留)`,1)]),n.canRegenerate&&!n.streaming?(B(),V(`button`,{key:0,type:`button`,class:`aimsg__budget-go`,onClick:t[9]||=t=>e.$emit(`continue`)},`继续这轮`)):K(`v-if`,!0)],8,nA)):K(`v-if`,!0),K(` 悬停操作:复制 / 重新生成(仅最后一条助手消息可重发) `),n.msg.content||n.msg.error?(B(),V(`footer`,iA,[U(`button`,{type:`button`,class:`aimsg__act`,title:i.copied?`已复制`:`复制回答`,onClick:t[10]||=(...e)=>a.copyText&&a.copyText(...e)},[(B(),V(`svg`,oA,[U(`use`,{href:i.copied?`#icon-check`:`#icon-copy-sm`},null,8,sA)])),U(`span`,null,M(i.copied?`已复制`:`复制`),1)],8,aA),n.canRegenerate&&!n.streaming?(B(),V(`button`,{key:0,type:`button`,class:`aimsg__act`,title:`丢弃这次回答并重新生成`,onClick:t[11]||=t=>e.$emit(`regenerate`,n.msg)},[...t[26]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-reset`})],-1),U(`span`,null,`重新生成`,-1)]])):K(`v-if`,!0)])):K(`v-if`,!0)],64))],2)}var lA=X(ek,[[`render`,cA],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatMessage.vue`]]),uA=106,dA=.5,fA=`cardbuddy:ai-composer-height`,pA={name:`ChatComposer`,props:{busy:{type:Boolean,default:!1},model:{type:String,default:``},attachments:{type:Array,default:()=>[]},placeholder:{type:String,default:`描述你要改的卡片,Enter 发送 / Shift+Enter 换行`},context:{type:Object,default:null}},emits:[`send`,`stop`,`pick`,`add-path`,`remove-attachment`,`drop-files`,`paste-image`,`escape`],data(){return{text:``,attachOpen:!1,pathInputOpen:!1,pathText:``,dragOver:!1,heightPx:0,resizing:!1,compArmed:!1,_compTimer:null,_outside:null,_onWinResize:null}},computed:{canSend(){return!!(this.text.trim()||this.attachments.some(e=>!e.pending&&e.exists!==!1))},compStyle(){return this.heightPx>0?{height:`${this.heightPx}px`}:null},ctx(){let e=this.context;if(!e)return null;let t=Number(e.window)>0?Number(e.window):Number(e.total)>0?Number(e.total):0,n=Math.max(0,Number(e.used)||0);if(!(t>0))return null;let r=Math.min(1,n/t),i=2*Math.PI*8;return{pct:r,arc:(i*r).toFixed(2),circ:i.toFixed(2),pctLabel:`${Math.round(r*100)}%`,level:r>=.85?`danger`:r>=.6?`warn`:`ok`,used:n,total:t}},ctxTitle(){let e=this.ctx;if(!e)return``;let t=e=>e>=1e3?`${(e/1e3).toFixed(1)}k`:String(Math.round(e)),n=Number(this.context?.window)>0?` · 网关窗口 ${t(Number(this.context.window))}`:``;return`上下文占用 ${t(e.used)} / ${t(e.total)} token(${e.pctLabel})${n};接近上限时后端会自动折叠早期工具结果`}},mounted(){this._outside=e=>{let t=this.$refs.attachEl;t&&!t.contains(e.target)&&(this.attachOpen=!1)},document.addEventListener(`mousedown`,this._outside),this.loadHeight(),this._onWinResize=()=>this.clampHeight(),window.addEventListener(`resize`,this._onWinResize),this.autoGrow()},beforeUnmount(){this._outside&&document.removeEventListener(`mousedown`,this._outside),this._onWinResize&&window.removeEventListener(`resize`,this._onWinResize)},methods:{focus(){this.$nextTick(()=>this.$refs.taEl?.focus())},setText(e){this.text=e,this.focus(),this.autoGrow()},fileUrl(e){return pO(e)},chipSub(e){if(e.exists===!1)return`不可读`;if(e.isDir)return`${e.entryCount??e.entries?.length??0} 项`;let t=Number(e.size||0);return t?t<1024?`${t} B`:t<1048576?`${(t/1024).toFixed(0)} KB`:`${(t/1024/1024).toFixed(1)} MB`:``},autoGrow(){let e=this.$refs.taEl;if(e){if(this.heightPx>0){e.style.height=``;return}e.style.height=`auto`,e.style.height=`${Math.min(e.scrollHeight,168)}px`}},heightLimits(){let e=this.$el?.closest(`.aichat`)?.clientHeight||window.innerHeight;return{min:uA,max:Math.max(uA,Math.floor(e*dA))}},clampHeight(){if(!this.heightPx)return;let{min:e,max:t}=this.heightLimits();this.heightPx=Math.max(e,Math.min(t,this.heightPx))},loadHeight(){try{let e=localStorage.getItem(fA),t=e==null?0:parseInt(e,10);!Number.isNaN(t)&&t>=uA&&(this.heightPx=t)}catch{}this.clampHeight()},saveHeight(){try{this.heightPx?localStorage.setItem(fA,String(Math.round(this.heightPx))):localStorage.removeItem(fA)}catch{}},armComp(){clearTimeout(this._compTimer),this._compTimer=setTimeout(()=>{this.compArmed=!0},300)},disarmComp(){clearTimeout(this._compTimer),this._compTimer=null,!this.resizing&&(this.compArmed=!1)},startResize(e){let t=e&&e.currentTarget;if(!t||!this.compArmed)return;this.resizing=!0,document.body.style.cursor=`row-resize`,document.body.style.userSelect=`none`;let n=e.pointerId;try{t.setPointerCapture(n)}catch{}let r=this.$el.getBoundingClientRect().bottom,i=e=>{let{min:t,max:n}=this.heightLimits();this.heightPx=Math.max(t,Math.min(n,Math.round(r-e.clientY)))},a=()=>{t.removeEventListener(`pointermove`,i),t.removeEventListener(`pointerup`,a),t.removeEventListener(`pointercancel`,a),window.removeEventListener(`blur`,a);try{t.hasPointerCapture?.(n)&&t.releasePointerCapture(n)}catch{}this.resizing=!1,document.body.style.cursor=``,document.body.style.userSelect=``,this.saveHeight()};t.addEventListener(`pointermove`,i),t.addEventListener(`pointerup`,a),t.addEventListener(`pointercancel`,a),window.addEventListener(`blur`,a)},resetHeight(){this.heightPx=0,this.saveHeight(),this.$nextTick(this.autoGrow)},onKeydown(e){if(e.key===`Escape`){e.preventDefault(),this.$emit(`escape`);return}e.key===`Enter`&&(e.isComposing||e.keyCode===229||e.shiftKey||(e.preventDefault(),this.busy||this.submit()))},submit(){if(this.busy||!this.canSend)return;let e={text:this.text.trim(),attachments:this.attachments.filter(e=>!e.pending&&e.exists!==!1)};this.text=``,this.attachOpen=!1,this.$nextTick(this.autoGrow),this.$emit(`send`,e)},toggleAttach(){this.attachOpen=!this.attachOpen},pick(e){this.attachOpen=!1,this.$emit(`pick`,e)},openPathInput(){this.attachOpen=!1,this.pathInputOpen=!0,this.pathText=``,this.$nextTick(()=>this.$refs.pathEl?.focus())},closePathInput(){this.pathInputOpen=!1,this.pathText=``},confirmPath(){let e=this.pathText.trim();e&&(this.$emit(`add-path`,e),this.closePathInput())},onDragEnter(){this.dragOver=!0},onDragOver(){this.dragOver=!0},onDragLeave(){this.dragOver=!1},onDrop(e){this.dragOver=!1;let t=e.dataTransfer;t&&this.$emit(`drop-files`,t)},async onPaste(e){let t=e.clipboardData?.items;if(t){for(let n of t)if(n.type&&n.type.indexOf(`image/`)===0){let t=n.getAsFile();if(!t)continue;e.preventDefault();let r=await new Promise(e=>{let n=new FileReader;n.onload=()=>e(String(n.result||``)),n.onerror=()=>e(``),n.readAsDataURL(t)});r&&this.$emit(`paste-image`,r);return}}}}},mA={key:0,class:`aicomp__files`},hA=[`title`],gA=[`src`,`alt`],_A={key:1,class:`aichip__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},vA=[`href`],yA={class:`aichip__name`},bA={key:2,class:`aichip__sub`},xA=[`onClick`],SA={key:1,class:`aicomp__path`},CA=[`disabled`],wA=[`placeholder`],TA={class:`aicomp__bar`},EA={class:`aicomp__tools`},DA={class:`aicomp__attach`,ref:`attachEl`},OA={key:0,class:`aicomp__menu`,role:`menu`},kA={class:`aicomp__right`},AA=[`title`],jA={class:`aicomp__ctx-ring`,viewBox:`0 0 20 20`,"aria-hidden":`true`},MA=[`stroke-dasharray`],NA={class:`aicomp__ctx-pct`},PA=[`title`],FA=[`disabled`,`title`];function IA(e,t,n,r,i,a){return B(),V(`div`,{class:j([`aicomp`,{"is-busy":n.busy,"is-drag":i.dragOver,"is-manual":i.heightPx>0,"is-resizing":i.resizing}]),style:A(a.compStyle)},[K(` 上缘拖拽把手:调输入区高度(106px ~ 面板高度 50%,双击恢复自适应),与面板宽度把手同一套交互 `),U(`div`,{class:j([`aicomp__grip`,{"is-dragging":i.resizing,"is-armed":i.compArmed}]),title:`拖拽调整输入区高度(双击恢复自适应)`,onMouseenter:t[0]||=(...e)=>a.armComp&&a.armComp(...e),onMouseleave:t[1]||=(...e)=>a.disarmComp&&a.disarmComp(...e),onPointerdown:t[2]||=q((...e)=>a.startResize&&a.startResize(...e),[`prevent`]),onDblclick:t[3]||=q((...e)=>a.resetHeight&&a.resetHeight(...e),[`prevent`])},null,34),K(` 已挂载的本地文件:只预览 + 传路径,不上传 `),n.attachments.length?(B(),V(`div`,mA,[(B(!0),V(z,null,R(n.attachments,n=>(B(),V(`div`,{key:n.id||n.path,class:j([`aichip`,{"aichip--dir":n.isDir,"aichip--pending":n.pending,"aichip--missing":n.exists===!1}]),title:n.path},[n.isImage&&!n.pending?(B(),V(`img`,{key:0,class:`aichip__thumb`,src:a.fileUrl(n.path),alt:n.name,loading:`lazy`},null,8,gA)):(B(),V(`svg`,_A,[U(`use`,{href:n.pending?`#icon-loading`:n.isDir?`#icon-folder-plus`:n.isImage?`#icon-image`:`#icon-file-text`},null,8,vA)])),U(`span`,yA,M(n.pending?`解析路径中…`:n.name),1),n.pending?K(`v-if`,!0):(B(),V(`span`,bA,M(a.chipSub(n)),1)),U(`button`,{type:`button`,class:`aichip__rm`,title:`移除`,onClick:t=>e.$emit(`remove-attachment`,n.id||n.path)},[...t[24]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]],8,xA)],10,hA))),128))])):K(`v-if`,!0),K(` 粘贴绝对路径(非 macOS / 拖拽反查失败时的兜底入口) `),i.pathInputOpen?(B(),V(`div`,SA,[I(U(`input`,{ref:`pathEl`,"onUpdate:modelValue":t[4]||=e=>i.pathText=e,class:`aicomp__path-input`,type:`text`,placeholder:`粘贴本地图片或文件夹的绝对路径,回车确认`,spellcheck:`false`,onKeydown:[t[5]||=vl(q((...e)=>a.confirmPath&&a.confirmPath(...e),[`prevent`]),[`enter`]),t[6]||=vl(q((...e)=>a.closePathInput&&a.closePathInput(...e),[`stop`,`prevent`]),[`esc`])]},null,544),[[il,i.pathText]]),U(`button`,{type:`button`,class:`aicomp__path-ok`,disabled:!i.pathText.trim(),onClick:t[7]||=(...e)=>a.confirmPath&&a.confirmPath(...e)},`添加`,8,CA),U(`button`,{type:`button`,class:`aicomp__path-no`,onClick:t[8]||=(...e)=>a.closePathInput&&a.closePathInput(...e)},`取消`)])):K(`v-if`,!0),U(`div`,{class:`aicomp__box`,onDragenter:t[20]||=q((...e)=>a.onDragEnter&&a.onDragEnter(...e),[`prevent`]),onDragover:t[21]||=q((...e)=>a.onDragOver&&a.onDragOver(...e),[`prevent`]),onDragleave:t[22]||=q((...e)=>a.onDragLeave&&a.onDragLeave(...e),[`prevent`]),onDrop:t[23]||=q((...e)=>a.onDrop&&a.onDrop(...e),[`prevent`])},[I(U(`textarea`,{ref:`taEl`,"onUpdate:modelValue":t[9]||=e=>i.text=e,class:`aicomp__ta`,placeholder:n.placeholder,rows:`1`,onInput:t[10]||=(...e)=>a.autoGrow&&a.autoGrow(...e),onKeydown:t[11]||=(...e)=>a.onKeydown&&a.onKeydown(...e),onPaste:t[12]||=(...e)=>a.onPaste&&a.onPaste(...e)},null,40,wA),[[il,i.text]]),U(`div`,TA,[U(`div`,EA,[U(`div`,DA,[U(`button`,{type:`button`,class:j([`aicomp__iconbtn`,{"is-open":i.attachOpen}]),title:`挂载本地图片 / 文件 / 文件夹`,onClick:t[13]||=(...e)=>a.toggleAttach&&a.toggleAttach(...e)},[...t[25]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-paperclip`})],-1)]],2),i.attachOpen?(B(),V(`div`,OA,[U(`button`,{type:`button`,role:`menuitem`,onClick:t[14]||=e=>a.pick(`image`)},[...t[26]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-image`})],-1),G(` 本地图片… `,-1)]]),U(`button`,{type:`button`,role:`menuitem`,onClick:t[15]||=e=>a.pick(`file`)},[...t[27]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-file-text`})],-1),G(` 本地文件… `,-1)]]),U(`button`,{type:`button`,role:`menuitem`,onClick:t[16]||=e=>a.pick(`folder`)},[...t[28]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-folder-plus`})],-1),G(` 本地文件夹… `,-1)]]),t[30]||=U(`div`,{class:`aicomp__menu-sep`},null,-1),U(`button`,{type:`button`,role:`menuitem`,onClick:t[17]||=(...e)=>a.openPathInput&&a.openPathInput(...e)},[...t[29]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-link`})],-1),G(` 粘贴路径… `,-1)]])])):K(`v-if`,!0)],512),t[31]||=U(`span`,{class:`aicomp__hint`},`拖拽文件 / 文件夹到此,或直接 ⌘V 粘贴截图`,-1)]),U(`div`,kA,[a.ctx?(B(),V(`span`,{key:0,class:j([`aicomp__ctx`,`is-${a.ctx.level}`]),title:a.ctxTitle},[(B(),V(`svg`,jA,[t[32]||=U(`circle`,{class:`aicomp__ctx-track`,cx:`10`,cy:`10`,r:`8`},null,-1),U(`circle`,{class:`aicomp__ctx-arc`,cx:`10`,cy:`10`,r:`8`,"stroke-dasharray":`${a.ctx.arc} ${a.ctx.circ}`,transform:`rotate(-90 10 10)`},null,8,MA)])),U(`span`,NA,M(a.ctx.pctLabel),1)],10,AA)):K(`v-if`,!0),n.model?(B(),V(`span`,{key:1,class:`aicomp__model`,title:`当前模型:${n.model}`},M(n.model),9,PA)):K(`v-if`,!0),n.busy?(B(),V(`button`,{key:2,type:`button`,class:`aicomp__send aicomp__send--stop`,title:`终止生成(Esc)`,onClick:t[18]||=t=>e.$emit(`stop`)},[...t[33]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"aria-hidden":`true`},[U(`use`,{href:`#icon-stop`})],-1)]])):(B(),V(`button`,{key:3,type:`button`,class:`aicomp__send`,disabled:!a.canSend,title:a.canSend?`发送(Enter)`:`输入内容后发送`,onClick:t[19]||=(...e)=>a.submit&&a.submit(...e)},[...t[34]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-send`})],-1)]],8,FA))])])],32)],6)}var LA=X(pA,[[`render`,IA],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatComposer.vue`]]),RA={name:`AiSettings`,components:{NumberStepper:Ag,Switch:ZC},props:{config:{type:Object,default:()=>({baseUrl:``,model:``,hasKey:!1,apiKeyMasked:``})},modelId:{type:String,default:null},initialModel:{type:Object,default:null}},emits:[`close`,`saved`],data(){let e=this.modelId&&this.initialModel||{};return{form:{name:e.name||``,baseUrl:e.baseUrl||``,model:e.model||``,apiKey:``,thinking:e.thinking!==!1,vision:e.vision===!0,maxTokens:e.maxTokensAuto?0:Number(e.maxTokens)>0?Number(e.maxTokens):0},reveal:!1,saving:!1,testing:!1,probing:!1,ping:null,help:null,keyLoaded:!1,submitted:!1,touched:{}}},computed:{title(){return this.modelId?`编辑模型`:`添加模型`},errors(){let e={},t=this.form.baseUrl.trim(),n=this.form.model.trim();return t?/^https?:\/\/[^\s]+$/i.test(t)||(e.baseUrl=`Base URL 需以 http:// 或 https:// 开头`):e.baseUrl=`请填写 Base URL`,n||(e.model=`请填写模型名`),!this.keyLoaded&&!this.form.apiKey.trim()&&(e.apiKey=`请填写 API Key`),e},isValid(){return Object.keys(this.errors).length===0},knownCapLimit(){return(Number(this.config.maxTokensCap)>0?Number(this.config.maxTokensCap):0)||(Number(this.config.maxTokensWindow)>0?Number(this.config.maxTokensWindow):0)},maxTokensOver(){return this.knownCapLimit>0&&this.form.maxTokens>this.knownCapLimit},maxTokensPlaceholder(){let e=Number(this.config.maxTokens)>0?Number(this.config.maxTokens):0;return e>0?`留空 = 自动(当前按 ${e})`:`留空 = 自动`},keyPlaceholder(){return this.keyLoaded?this.form.apiKey?``:`已保存的密钥为空,请填写新密钥`:this.config.hasKey?`已保存(${this.config.apiKeyMasked||`••••`}),回显失败:留空沿用、填写覆盖`:`sk-…`}},created(){this.loadKey()},mounted(){document.addEventListener(`click`,this.onDocClick,!0),document.addEventListener(`keydown`,this.onKeydown)},beforeUnmount(){document.removeEventListener(`click`,this.onDocClick,!0),document.removeEventListener(`keydown`,this.onKeydown)},methods:{toggleHelp(e){this.help=this.help===e?null:e},showError(e){return!!this.errors[e]&&(this.submitted||this.touched[e])},markTouched(e){this.$set(this.touched,e,!0)},onDocClick(e){if(!this.help)return;let t=e.target;t instanceof Element&&t.closest(`.aiset__pop, .aiset__help`)||(this.help=null)},onKeydown(e){e.key===`Escape`&&this.help&&(e.stopPropagation(),this.help=null)},onMaxTokens(e){let t=Number(String(e).trim());this.form.maxTokens=Number.isFinite(t)&&t>=0?Math.round(t):0},async probe(){let e=[];if(this.form.baseUrl.trim()||e.push(`Base URL`),this.form.apiKey.trim()||e.push(`API Key`),this.form.model.trim()||e.push(`模型名`),e.length){this.ping={ok:!1,text:`探测前请先填写:${e.join(` / `)}`};return}this.probing=!0,this.ping=null;try{let e=await wO({baseUrl:this.form.baseUrl,apiKey:this.form.apiKey,model:this.form.model}),t=Number(e.window)>0?Number(e.window):0,n=Number(e.cap)>0?Number(e.cap):0;if(n>0){this.form.maxTokens=n;let r=e.source===`models-meta`?`模型元数据`:e.source===`probe`?`二分试探`:e.source===`halved`?`减半回写`:e.source||`探测`,i=[`接受单次输出上限 ${n}`];t>0&&i.push(`上下文窗口 ${t}`),this.ping={ok:!0,text:`网关${i.join(`、`)}(来源:${r})→ 已填入 ${n};留空则走自动(取 min(上限, ${Number(e.ceiling)>0?e.ceiling:32768}) = ${Number(e.autoMax)>0?e.autoMax:n})`}}else{let n=[];t>0&&n.push(`上下文窗口 ${t}`),e.source===`fallback`?n.push(`网关未接受任何档位(可能是地址 / 密钥 / 模型名有误,或该网关不暴露上限)`):n.push(`未探到网关接受的单次输出上限`),this.ping={ok:!1,text:`${n.join(`;`)}。建议留空走自动:后端按默认值开跑,被网关拒绝时自动减半并记下真实上限`}}}catch(e){this.ping={ok:!1,text:`探测失败:${e.message||e}`}}finally{this.probing=!1}},async loadKey(){if(this.modelId)try{let e=await yO(this.modelId,!0),t=typeof e.apiKey==`string`?e.apiKey:``;t&&(this.form.apiKey=t,this.keyLoaded=!0),typeof e.name==`string`&&(this.form.name=e.name),typeof e.baseUrl==`string`&&(this.form.baseUrl=e.baseUrl),typeof e.model==`string`&&(this.form.model=e.model),this.form.maxTokens=e.maxTokensAuto||!(Number(e.maxTokens)>0)?0:Number(e.maxTokens),e.thinking!==void 0&&(this.form.thinking=e.thinking!==!1),e.vision!==void 0&&(this.form.vision=e.vision===!0)}catch{}},payload(){let e={name:this.form.name.trim(),baseUrl:this.form.baseUrl.trim(),model:this.form.model.trim(),thinking:!!this.form.thinking,vision:!!this.form.vision,maxTokens:Number(this.form.maxTokens)>0?Number(this.form.maxTokens):0};return(this.keyLoaded||this.form.apiKey.trim())&&(e.apiKey=this.form.apiKey.trim()),e},async test(){if(!this.isValid){this.submitted=!0,this.help=null,this.ping={ok:!1,text:`请先补全必填项(Base URL / 模型名 / API Key)再测试连接`};return}this.testing=!0,this.ping=null;try{let e=await TO(this.payload());this.ping=e.ok?{ok:!0,text:`连接正常 · ${e.model||this.form.model} · ${e.latencyMs}ms`}:{ok:!1,text:`连接失败${e.status?`(HTTP ${e.status})`:``}:${e.message||`未知错误`}`}}catch(e){this.ping={ok:!1,text:`测试失败:${e.message||e}`}}finally{this.testing=!1}},async save(){if(this.submitted=!0,!this.isValid){this.help=null;let e={baseUrl:`aiset-baseurl`,model:`aiset-model`,apiKey:`aiset-key`},t=Object.keys(this.errors)[0],n=t?this.$el.querySelector(`#${e[t]}`):null;n&&typeof n.focus==`function`&&n.focus(),this.ping={ok:!1,text:`请先补全必填项(Base URL / 模型名 / API Key)`};return}this.saving=!0;try{let e=this.modelId?await xO(this.modelId,this.payload()):await bO(this.payload());this.$emit(`saved`,e)}catch(e){this.ping={ok:!1,text:`保存失败:${e.message||e}`}}finally{this.saving=!1}}}},zA={class:`aiset__mask`},BA={class:`aiset`,role:`dialog`,"aria-modal":`true`,"aria-label":`AI 模型设置`},VA={class:`aiset__head`},HA={class:`aiset__title`},UA={class:`aiset__body`},WA={class:`aiset__field`},GA={class:`aiset__field`},KA={class:`aiset__labelrow`},qA=[`aria-expanded`],JA=[`aria-invalid`],YA={key:0,class:`aiset__errline`},XA={key:1,class:`aiset__pop`},ZA={class:`aiset__field`},QA={class:`aiset__labelrow`},$A=[`aria-expanded`],ej=[`aria-invalid`],tj={key:0,class:`aiset__errline`},nj={key:1,class:`aiset__pop`},rj={class:`aiset__field`},ij={class:`aiset__labelrow`},aj=[`aria-expanded`],oj={class:`aiset__keywrap`},sj=[`type`,`placeholder`,`aria-invalid`],cj=[`title`,`aria-pressed`],lj={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},uj=[`href`],dj={key:0,class:`aiset__errline`},fj={key:1,class:`aiset__pop`},pj={class:`aiset__field`},mj={class:`aiset__labelrow`},hj=[`aria-expanded`],gj={class:`aiset__stepperrow`},_j=[`disabled`],vj={key:0,class:`aiset__warnline`},yj={key:1,class:`aiset__pop`},bj={class:`aiset__field`},xj={class:`aiset__labelrow`},Sj=[`aria-expanded`],Cj={key:0,class:`aiset__pop`},wj={class:`aiset__field`},Tj={class:`aiset__labelrow`},Ej=[`aria-expanded`],Dj={key:0,class:`aiset__pop`},Oj={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},kj=[`href`],Aj={class:`aiset__foot`},jj=[`disabled`],Mj={class:`aiset__btn-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},Nj=[`href`],Pj=[`disabled`],Fj=[`disabled`];function Ij(e,t,n,r,i,a){let o=L(`NumberStepper`),s=L(`Switch`);return B(),V(`div`,zA,[U(`section`,BA,[U(`header`,VA,[t[22]||=U(`svg`,{class:`aiset__head-icon is-solid-icon`,viewBox:`0 0 1024 1024`,"aria-hidden":`true`},[U(`use`,{href:`#icon-model`})],-1),U(`span`,HA,M(a.title),1),U(`button`,{type:`button`,class:`aiset__x`,title:`关闭`,onClick:t[0]||=t=>e.$emit(`close`)},[...t[21]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])]),K(` 字段说明一律收进「?」浮层:面板只留标签 + 控件,需要时点开看详情 `),U(`div`,UA,[U(`div`,WA,[t[23]||=U(`div`,{class:`aiset__labelrow`},[U(`label`,{class:`aiset__label`,for:`aiset-name`},`名称`)],-1),I(U(`input`,{id:`aiset-name`,"onUpdate:modelValue":t[1]||=e=>i.form.name=e,class:`aiset__input`,type:`text`,placeholder:`模型显示名(如 GPT-4o / 我的 GLM)`,spellcheck:`false`,autocomplete:`off`},null,512),[[il,i.form.name]])]),U(`div`,GA,[U(`div`,KA,[t[25]||=U(`label`,{class:`aiset__label`,for:`aiset-baseurl`},[G(`Base URL`),U(`i`,{class:`aiset__req`,"aria-hidden":`true`},`*`)],-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`baseUrl`}]),"aria-expanded":i.help===`baseUrl`,title:`查看说明`,onClick:t[2]||=q(e=>a.toggleHelp(`baseUrl`),[`stop`])},[...t[24]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,qA)]),I(U(`input`,{id:`aiset-baseurl`,"onUpdate:modelValue":t[3]||=e=>i.form.baseUrl=e,class:j([`aiset__input`,{"is-invalid":a.showError(`baseUrl`)}]),type:`text`,placeholder:`https://api.example.com/v1`,spellcheck:`false`,autocomplete:`off`,"aria-invalid":a.showError(`baseUrl`)?`true`:`false`,onBlur:t[4]||=e=>a.markTouched(`baseUrl`)},null,42,JA),[[il,i.form.baseUrl]]),a.showError(`baseUrl`)?(B(),V(`p`,YA,M(a.errors.baseUrl),1)):K(`v-if`,!0),i.help===`baseUrl`?(B(),V(`p`,XA,[...t[26]||=[G(`OpenAI 兼容网关的基址,`,-1),U(`strong`,null,`不含`,-1),G(),U(`code`,null,`/chat/completions`,-1),G(` 后缀(后端会自己拼)。例:`,-1),U(`code`,null,`https://api.openai.com/v1`,-1),G(`。`,-1)]])):K(`v-if`,!0)]),U(`div`,ZA,[U(`div`,QA,[t[28]||=U(`label`,{class:`aiset__label`,for:`aiset-model`},[G(`模型名`),U(`i`,{class:`aiset__req`,"aria-hidden":`true`},`*`)],-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`model`}]),"aria-expanded":i.help===`model`,title:`查看说明`,onClick:t[5]||=q(e=>a.toggleHelp(`model`),[`stop`])},[...t[27]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,$A)]),I(U(`input`,{id:`aiset-model`,"onUpdate:modelValue":t[6]||=e=>i.form.model=e,class:j([`aiset__input`,{"is-invalid":a.showError(`model`)}]),type:`text`,placeholder:`gpt-4o / GLM-4.6 / deepseek-chat`,spellcheck:`false`,autocomplete:`off`,"aria-invalid":a.showError(`model`)?`true`:`false`,onBlur:t[7]||=e=>a.markTouched(`model`)},null,42,ej),[[il,i.form.model]]),a.showError(`model`)?(B(),V(`p`,tj,M(a.errors.model),1)):K(`v-if`,!0),i.help===`model`?(B(),V(`p`,nj,`必须与网关侧的模型标识完全一致。建卡这类多步工具调用建议用支持 function calling 的模型。`)):K(`v-if`,!0)]),U(`div`,rj,[U(`div`,ij,[t[30]||=U(`label`,{class:`aiset__label`,for:`aiset-key`},[G(`API Key`),U(`i`,{class:`aiset__req`,"aria-hidden":`true`},`*`)],-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`apiKey`}]),"aria-expanded":i.help===`apiKey`,title:`查看说明`,onClick:t[8]||=q(e=>a.toggleHelp(`apiKey`),[`stop`])},[...t[29]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,aj)]),U(`div`,oj,[I(U(`input`,{id:`aiset-key`,"onUpdate:modelValue":t[9]||=e=>i.form.apiKey=e,class:j([`aiset__input aiset__input--key`,{"is-invalid":a.showError(`apiKey`)}]),type:i.reveal?`text`:`password`,placeholder:a.keyPlaceholder,spellcheck:`false`,autocomplete:`off`,"aria-invalid":a.showError(`apiKey`)?`true`:`false`,onBlur:t[10]||=e=>a.markTouched(`apiKey`)},null,42,sj),[[fl,i.form.apiKey]]),U(`button`,{type:`button`,class:`aiset__eye`,title:i.reveal?`掩码显示密钥`:`明文显示密钥`,"aria-pressed":i.reveal,onClick:t[11]||=e=>i.reveal=!i.reveal},[(B(),V(`svg`,lj,[U(`use`,{href:i.reveal?`#icon-eye-off`:`#icon-eye`},null,8,uj)]))],8,cj)]),a.showError(`apiKey`)?(B(),V(`p`,dj,M(a.errors.apiKey),1)):K(`v-if`,!0),i.help===`apiKey`?(B(),V(`p`,fj,[...t[31]||=[G(` 密钥保存在项目根 `,-1),U(`code`,null,`.env.cb.local`,-1),G(`(个人覆盖层,已被 .gitignore 忽略,不会进版本库)。 打开面板自动回填已保存的密钥(默认掩码),点输入框尾部小眼睛切换明文;`,-1),U(`strong`,null,`清空后保存即删除`,-1),G(`已保存的密钥。 `,-1)]])):K(`v-if`,!0)]),U(`div`,pj,[U(`div`,mj,[t[33]||=U(`label`,{class:`aiset__label`},`单次输出上限`,-1),t[34]||=U(`span`,{class:`aiset__unit`},`max_tokens`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`maxTokens`}]),"aria-expanded":i.help===`maxTokens`,title:`查看说明`,onClick:t[12]||=q(e=>a.toggleHelp(`maxTokens`),[`stop`])},[...t[32]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,hj)]),U(`div`,gj,[W(o,{id:`aiset-maxtok`,class:`aiset__stepper`,value:i.form.maxTokens>0?String(i.form.maxTokens):``,step:1024,min:0,max:262144,placeholder:a.maxTokensPlaceholder,onInput:a.onMaxTokens},null,8,[`value`,`placeholder`,`onInput`]),U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.probing||i.saving||i.testing,onClick:t[13]||=(...e)=>a.probe&&a.probe(...e)},M(i.probing?`探测中…`:`探测`),9,_j)]),a.maxTokensOver?(B(),V(`p`,vj,` 超过网关已知上限 `+M(a.knownCapLimit)+`:对话时会主动夹取到该值,建议留空走自动 `,1)):K(`v-if`,!0),i.help===`maxTokens`?(B(),V(`p`,yj,[t[35]||=U(`strong`,null,`普通用户不用管这一项:留空 = 自动`,-1),t[36]||=G(`。后端自己协商:先读网关 `,-1),t[37]||=U(`code`,null,`/v1/models`,-1),t[38]||=G(` 的上下文窗口(免费、毫秒级,最多等 2 秒,超时先用默认 24576 开跑), 拿到后取 `,-1),t[39]||=U(`code`,null,`min(窗口, 32768)`,-1),t[40]||=G(` 当作单次输出上限(输出预算 ≠ 上下文窗口,建卡一轮 32k 足够)。 读不到元数据也不会偷偷发试探请求;想知道窗口多大就点「探测」做一次二分试探(会产生一次真实补全,约十几秒)。 手填值超过网关接受上限时,对话开跑前会主动夹取并说明;真被 400 拒绝才会自动减半重试, 减半成功的值记为「接受上限」(**不是窗口**:窗口与输出上限是两回事,有网关窗口 262144 但 max_tokens 硬上限 131072)。 只有某轮明确报「被单次输出上限截断」才需要手填更大值。注意:推理模型的思考过程也算进这个上限。 `,-1),t[41]||=U(`br`,null,null,-1),t[42]||=U(`strong`,null,[G(`注意:`),U(`code`,null,`32768`),G(` 是自动模式的「封顶假设值」,不是网关能力上限。`)],-1),t[43]||=G(` 真实上限只能实测得到,请以「接受的单次输出上限」为准(如 qwen-max 实测仅 8192)。 `,-1),t[44]||=U(`br`,null,null,-1),t[45]||=G(`当前自动生效值:`,-1),U(`strong`,null,M(n.config.maxTokens>0?n.config.maxTokens:24576),1),G(`; 网关上下文窗口:`+M(n.config.maxTokensWindow>0?n.config.maxTokensWindow:`未拿到(网关可能不提供元数据)`)+`; 接受的单次输出上限:`+M(n.config.maxTokensCap>0?n.config.maxTokensCap:`未知(点「探测」,或撞过一次 400 后自动回写)`)+`。 `,1)])):K(`v-if`,!0)]),U(`div`,bj,[K(` 仅「勾选框 + 标题」包进 label:点说明 / 问号不应误触开关 `),U(`div`,xj,[t[47]||=U(`span`,{class:`aiset__label`},`深度思考`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`thinking`}]),"aria-expanded":i.help===`thinking`,title:`查看说明`,onClick:t[14]||=q(e=>a.toggleHelp(`thinking`),[`stop`])},[...t[46]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,Sj),W(s,{modelValue:i.form.thinking,"onUpdate:modelValue":t[15]||=e=>i.form.thinking=e,class:`aiset__switch`},null,8,[`modelValue`])]),i.help===`thinking`?(B(),V(`p`,Cj,[...t[48]||=[G(` 开启:模型先长篇推理再动手,规划更稳但慢很多、更费 token。关闭:直接出结果,实测同一网关快数倍。 关闭依赖网关支持 `,-1),U(`code`,null,`chat_template_kwargs.enable_thinking`,-1),G(`(vLLM / SGLang 系);网关不认时后端会自动回退成带思考并在对话里提示一次。 另外,`,-1),U(`strong`,null,`某一轮思考超时`,-1),G(`时后端会自动只在那一轮关闭深度思考并重试,逼出结果。 `,-1)]])):K(`v-if`,!0)]),U(`div`,wj,[U(`div`,Tj,[t[50]||=U(`span`,{class:`aiset__label`},`多模态视觉`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`vision`}]),"aria-expanded":i.help===`vision`,title:`查看说明`,onClick:t[16]||=q(e=>a.toggleHelp(`vision`),[`stop`])},[...t[49]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,Ej),W(s,{modelValue:i.form.vision,"onUpdate:modelValue":t[17]||=e=>i.form.vision=e,class:`aiset__switch`},null,8,[`modelValue`])]),i.help===`vision`?(B(),V(`p`,Dj,[...t[51]||=[G(` 开启后首轮对话会`,-1),U(`strong`,null,`自动探测`,-1),G(`网关是否真支持图像(比较带图 / 不带图的 prompt_tokens):支持则把渲染截图、设计稿 vs 渲染并排对比图、你挂载的图片注入上下文,AI 可直接读图找差异; 不支持会自动降级为数值闭环(pixelDiff.match)并在对话里提示一次。注入前降采样到长边 ≤ 1024px / ≤ 900KB,每轮最多 2 张;对话记录落盘不含图像。 `,-1)]])):K(`v-if`,!0)]),i.ping?(B(),V(`div`,{key:0,class:j([`aiset__ping`,i.ping.ok?`is-ok`:`is-bad`])},[(B(),V(`svg`,Oj,[U(`use`,{href:i.ping.ok?`#icon-check`:`#icon-alert-triangle`},null,8,kj)])),U(`span`,null,M(i.ping.text),1)],2)):K(`v-if`,!0)]),U(`footer`,Aj,[U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.testing||i.saving,onClick:t[18]||=(...e)=>a.test&&a.test(...e)},[(B(),V(`svg`,Mj,[U(`use`,{href:i.testing?`#icon-loading`:`#icon-activity`},null,8,Nj)])),U(`span`,null,M(i.testing?`测试中…`:`测试连接`),1)],8,jj),t[52]||=U(`span`,{class:`aiset__foot-gap`},null,-1),U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.saving,onClick:t[19]||=t=>e.$emit(`close`)},`取消`,8,Pj),U(`button`,{type:`button`,class:`aiset__btn aiset__btn--primary`,disabled:i.saving||i.testing,onClick:t[20]||=(...e)=>a.save&&a.save(...e)},M(i.saving?`保存中…`:`保存`),9,Fj)])])])}var Lj=X(RA,[[`render`,Ij],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/AiSettings.vue`]]),Rj={name:`ModelList`,props:{models:{type:Array,default:()=>[]},activeId:{type:String,default:null},turnRunning:{type:Boolean,default:!1}},emits:[`add`,`edit`,`delete`,`activate`,`close`,`open-common`,`import-ccswitch`],methods:{locked(e){return!!(this.turnRunning&&e&&e.id===this.activeId)},hostOf(e){let t=String(e||``).trim();if(!t)return`未填地址`;try{return new URL(t).host}catch{return t.replace(/^https?:\/\//,``).replace(/\/+$/,``)||t}}}},zj={class:`aiset__mask`},Bj={class:`aiset modellist`,role:`dialog`,"aria-modal":`true`,"aria-label":`模型选择`},Vj={class:`aiset__head`},Hj={class:`aiset__body ml__body`},Uj={class:`ml__toolbar`},Wj={key:0,class:`ml__lock`,role:`status`},Gj={key:1,class:`empty-state`},Kj={class:`ml__list`},qj=[`aria-disabled`,`onClick`],Jj={key:0,viewBox:`0 0 16 16`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},Yj={class:`ml__info`},Xj={class:`ml__name`},Zj={class:`ml__meta`},Qj={class:`ml__model`},$j={class:`ml__host`},eM={key:0,class:`ml__key`,title:`已配置密钥`},tM={key:1,class:`ml__key ml__key--off`,title:`未配置密钥`},nM={key:2,class:`ml__key ml__key--lock`,title:`对话进行中,正在使用的模型已锁定`},rM={class:`ml__actions`},iM=[`disabled`,`title`,`onClick`],aM=[`disabled`,`title`,`onClick`],oM={class:`ml__foot`},sM={class:`ml__hint`};function cM(e,t,n,r,i,a){return B(),V(`div`,zj,[U(`section`,Bj,[U(`header`,Vj,[t[5]||=U(`svg`,{class:`aiset__head-icon is-solid-icon`,viewBox:`0 0 1024 1024`,"aria-hidden":`true`},[U(`use`,{href:`#icon-model`})],-1),t[6]||=U(`span`,{class:`aiset__title`},`模型`,-1),U(`button`,{type:`button`,class:`aiset__x`,title:`关闭`,onClick:t[0]||=t=>e.$emit(`close`)},[...t[4]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])]),U(`div`,Hj,[K(` 操作工具条:添加模型 / 从 cc-switch 导入,靠右对齐 `),U(`div`,Uj,[U(`button`,{type:`button`,class:`ml__import`,title:`从 cc-switch 导入`,onClick:t[1]||=t=>e.$emit(`import-ccswitch`)},[...t[7]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-download`})],-1),U(`span`,null,`导入`,-1)]]),U(`button`,{type:`button`,class:`ml__add`,title:`添加模型`,onClick:t[2]||=t=>e.$emit(`add`)},[...t[8]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-plus`})],-1),U(`span`,null,`添加模型`,-1)]])]),K(` 对话进行中:正在使用的模型被锁,说明原因与解除方式,避免用户反复点却没反应 `),n.turnRunning?(B(),V(`div`,Wj,[...t[9]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),U(`span`,null,`有对话正在进行:正在使用的模型已锁定,本轮结束后可切换或修改。其他模型仍可编辑。`,-1)]])):K(`v-if`,!0),K(` 空状态:与其他面板占位(图标 + 文字)同一语言 `),n.models.length?(B(),V(z,{key:2},[K(` 模型列表:参考 cc-switch 的 provider 列表——每条可编辑 / 删除,当前生效项高亮 `),U(`ul`,Kj,[(B(!0),V(z,null,R(n.models,r=>(B(),V(`li`,{key:r.id,class:j([`ml__item`,{"is-active":r.id===n.activeId,"is-locked":a.locked(r)}]),"aria-disabled":a.locked(r)?`true`:`false`,onClick:t=>e.$emit(`activate`,r)},[U(`span`,{class:j([`ml__check`,{"is-on":r.id===n.activeId}]),"aria-hidden":`true`},[r.id===n.activeId?(B(),V(`svg`,Jj,[...t[11]||=[U(`use`,{href:`#icon-check`},null,-1)]])):K(`v-if`,!0)],2),U(`span`,Yj,[U(`span`,Xj,M(r.name||r.model||`未命名模型`),1),U(`span`,Zj,[U(`span`,Qj,M(r.model||`未填模型名`),1),t[12]||=U(`span`,{class:`ml__dot`},`·`,-1),U(`span`,$j,M(a.hostOf(r.baseUrl)),1),r.hasKey?(B(),V(`span`,eM,`已配密钥`)):(B(),V(`span`,tM,`无密钥`)),a.locked(r)?(B(),V(`span`,nM,`运行中 · 锁定`)):K(`v-if`,!0)])]),U(`span`,rM,[U(`button`,{type:`button`,class:`ml__btn`,disabled:a.locked(r),title:a.locked(r)?`对话进行中,正在使用的模型不可编辑`:`编辑`,onClick:q(t=>e.$emit(`edit`,r),[`stop`])},[...t[13]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-edit`})],-1)]],8,iM),U(`button`,{type:`button`,class:`ml__btn ml__btn--danger`,disabled:a.locked(r),title:a.locked(r)?`对话进行中,正在使用的模型不可删除`:`删除`,onClick:q(t=>e.$emit(`delete`,r),[`stop`])},[...t[14]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-trash`})],-1)]],8,aM)])],10,qj))),128))])],2112)):(B(),V(`div`,Gj,[...t[10]||=[as(`<span class="empty-state__badge" aria-hidden="true"><svg class="is-solid-icon" viewBox="0 0 1024 1024"><use href="#icon-model"></use></svg></span><p class="debug__empty">还没有模型</p><p class="empty-state__hint">点上方「添加模型」配置第一个 AI 模型(Base URL / API Key / 模型名),或「导入」从 cc-switch 拉取已有的 Codex 供应商。配置保存在项目根 .env.cb.local,不进版本库。</p>`,3)]]))]),U(`footer`,oM,[U(`span`,sM,M(n.turnRunning?`对话进行中:正在使用的模型已锁定,无法切换`:`点击任意模型即可切换为当前生效模型`),1),U(`button`,{type:`button`,class:`ml__common`,title:`通用设置(执行策略 / 环境参数,所有模型共享)`,onClick:t[3]||=t=>e.$emit(`open-common`)},[...t[15]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-settings`})],-1),U(`span`,null,`通用设置`,-1)]])])])])}var lM=X(Rj,[[`render`,cM],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ModelList.vue`]]),uM=6e4,dM={name:`AiCommonSettings`,components:{NumberStepper:Ag,Switch:ZC},emits:[`close`,`saved`],data(){return{form:{allowShell:!0,autoApprove:`all`,maxSteps:0,turnTimeoutMin:60,stallTimeoutMin:120,stallRetries:-1,reasoningTimeoutMin:600,autoContinueMax:-1},saving:!1,ping:null,help:null,adv:!1,approveOptions:[{value:`none`,label:`逐次确认`},{value:`skill`,label:`免技能`},{value:`all`,label:`全免确认`}]}},created(){this.loadConfig()},mounted(){document.addEventListener(`click`,this.onDocClick,!0),document.addEventListener(`keydown`,this.onKeydown)},beforeUnmount(){document.removeEventListener(`click`,this.onDocClick,!0),document.removeEventListener(`keydown`,this.onKeydown)},methods:{toggleHelp(e){this.help=this.help===e?null:e},onDocClick(e){if(!this.help)return;let t=e.target;t instanceof Element&&t.closest(`.aiset__pop, .aiset__help`)||(this.help=null)},onKeydown(e){e.key===`Escape`&&this.help&&(e.stopPropagation(),this.help=null)},onInt(e,t){let n=String(t).trim();if(!n){this.form[e]=e===`stallRetries`||e===`autoContinueMax`?-1:0;return}let r=Number(n);this.form[e]=Number.isFinite(r)?Math.round(r):0},async loadConfig(){try{let e=await hO();e.shellEnabled!==void 0&&(this.form.allowShell=e.shellEnabled!==!1),e.autoApprove&&(this.form.autoApprove=e.autoApprove),Number(e.maxSteps)>0&&(this.form.maxSteps=Number(e.maxSteps)),Number(e.turnTimeoutMs)>0&&(this.form.turnTimeoutMin=Math.round(Number(e.turnTimeoutMs)/uM)),Number(e.stallTimeoutMs)>0&&(this.form.stallTimeoutMin=Math.round(Number(e.stallTimeoutMs)/uM)),e.stallRetries!==void 0&&e.stallRetries>=0&&(this.form.stallRetries=Number(e.stallRetries)),Number(e.reasoningTimeoutMs)>0&&(this.form.reasoningTimeoutMin=Math.round(Number(e.reasoningTimeoutMs)/uM)),e.autoContinueMax!==void 0&&e.autoContinueMax>=0&&(this.form.autoContinueMax=Number(e.autoContinueMax))}catch{}},async save(){this.saving=!0,this.ping=null;try{let e=await gO({allowShell:!!this.form.allowShell,autoApprove:this.form.autoApprove,maxSteps:Number(this.form.maxSteps)>0?Number(this.form.maxSteps):0,turnTimeoutMs:Number(this.form.turnTimeoutMin)>0?Number(this.form.turnTimeoutMin)*uM:0,stallTimeoutMs:Number(this.form.stallTimeoutMin)>0?Number(this.form.stallTimeoutMin)*uM:0,stallRetries:Number(this.form.stallRetries)>=0?Number(this.form.stallRetries):-1,reasoningTimeoutMs:Number(this.form.reasoningTimeoutMin)>0?Number(this.form.reasoningTimeoutMin)*uM:0,autoContinueMax:Number(this.form.autoContinueMax)>=0?Number(this.form.autoContinueMax):-1});this.$emit(`saved`,e)}catch(e){this.ping={ok:!1,text:`保存失败:${e.message||e}`}}finally{this.saving=!1}}}},fM={class:`aiset__mask`},pM={class:`aiset`,role:`dialog`,"aria-modal":`true`,"aria-label":`AI 通用设置`},mM={class:`aiset__head`},hM={class:`aiset__body`},gM={class:`aiset__field`},_M={class:`aiset__labelrow`},vM=[`aria-expanded`],yM={key:0,class:`aiset__pop`},bM={class:`aiset__field`},xM={class:`aiset__labelrow`},SM=[`aria-expanded`],CM={class:`aiset__seg`},wM=[`onClick`],TM={key:0,class:`aiset__pop`},EM={class:`aiset__adv`},DM=[`aria-expanded`],OM={class:`aiset__adv-hint`},kM={key:0,class:`aiset__adv-body`},AM={class:`aiset__field`},jM={class:`aiset__labelrow`},MM=[`aria-expanded`],NM={class:`aiset__stepperrow`},PM={key:0,class:`aiset__pop`},FM={class:`aiset__field`},IM={class:`aiset__labelrow`},LM=[`aria-expanded`],RM={class:`aiset__stepperrow`},zM={key:0,class:`aiset__pop`},BM={class:`aiset__field`},VM={class:`aiset__labelrow`},HM=[`aria-expanded`],UM={class:`aiset__stepperrow`},WM={key:0,class:`aiset__pop`},GM={class:`aiset__field`},KM={class:`aiset__labelrow`},qM=[`aria-expanded`],JM={class:`aiset__stepperrow`},YM={key:0,class:`aiset__pop`},XM={class:`aiset__field`},ZM={class:`aiset__labelrow`},QM=[`aria-expanded`],$M={class:`aiset__stepperrow`},eN={key:0,class:`aiset__pop`},tN={class:`aiset__field`},nN={class:`aiset__labelrow`},rN=[`aria-expanded`],iN={class:`aiset__stepperrow`},aN={key:0,class:`aiset__pop`},oN={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},sN=[`href`],cN={class:`aiset__foot`},lN=[`disabled`],uN=[`disabled`];function dN(e,t,n,r,i,a){let o=L(`Switch`),s=L(`NumberStepper`);return B(),V(`div`,fM,[U(`section`,pM,[U(`header`,mM,[t[20]||=U(`svg`,{class:`aiset__head-icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-settings`})],-1),t[21]||=U(`span`,{class:`aiset__title`},`通用设置`,-1),U(`button`,{type:`button`,class:`aiset__x`,title:`关闭`,onClick:t[0]||=t=>e.$emit(`close`)},[...t[19]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])]),U(`div`,hM,[t[51]||=U(`p`,{class:`aiset__note`},[G(`以下为`),U(`strong`,null,`所有模型共享`),G(`的执行策略 / 环境参数,与具体模型无关,故不放在每个模型条目里。`)],-1),U(`div`,gM,[U(`div`,_M,[t[23]||=U(`span`,{class:`aiset__label`},`本地命令执行`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`allowShell`}]),"aria-expanded":i.help===`allowShell`,title:`查看说明`,onClick:t[1]||=q(e=>a.toggleHelp(`allowShell`),[`stop`])},[...t[22]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,vM),W(o,{modelValue:i.form.allowShell,"onUpdate:modelValue":t[2]||=e=>i.form.allowShell=e,class:`aiset__switch`},null,8,[`modelValue`])]),i.help===`allowShell`?(B(),V(`p`,yM,[...t[24]||=[G(` 是否注册 `,-1),U(`code`,null,`shell_exec`,-1),G(` 本地命令执行。默认开(工具只监听 127.0.0.1,命令过白名单 + 全量审计)。 关掉后 AI 不能跑本地命令,但仍可执行技能脚本(由 `,-1),U(`code`,null,`autoApprove`,-1),G(` 控制是否逐次确认)。 `,-1)]])):K(`v-if`,!0)]),U(`div`,bM,[U(`div`,xM,[t[26]||=U(`span`,{class:`aiset__label`},`免确认执行策略`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`autoApprove`}]),"aria-expanded":i.help===`autoApprove`,title:`查看说明`,onClick:t[3]||=q(e=>a.toggleHelp(`autoApprove`),[`stop`])},[...t[25]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,SM)]),U(`div`,CM,[(B(!0),V(z,null,R(i.approveOptions,e=>(B(),V(`button`,{key:e.value,type:`button`,class:j([`aiset__seg-btn`,{"is-on":i.form.autoApprove===e.value}]),onClick:t=>i.form.autoApprove=e.value},M(e.label),11,wM))),128))]),i.help===`autoApprove`?(B(),V(`p`,TM,[...t[27]||=[U(`code`,null,`none`,-1),G(`=逐次弹审批;`,-1),U(`code`,null,`skill`,-1),G(`=只免技能脚本;`,-1),U(`code`,null,`all`,-1),G(`=技能脚本 + 本地命令都免确认(默认)。 建卡管线连跑十几次脚本 / 命令,`,-1),U(`code`,null,`all`,-1),G(` 避免每次等用户点「允许」。 `,-1)]])):K(`v-if`,!0)]),K(` 保活 / 预算阈值:实测调优出来的值,改只会变坏,故默认收起。
|
|
277
|
+
全部有代码默认值,留空即走默认;折叠区保留可写入口,真要调时不用去翻 .env `),U(`div`,EM,[U(`button`,{type:`button`,class:`aiset__adv-head`,"aria-expanded":i.adv,onClick:t[4]||=e=>i.adv=!i.adv},[(B(),V(`svg`,{class:j([`aiset__adv-caret`,{"is-open":i.adv}]),viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[...t[28]||=[U(`use`,{href:`#icon-chevron-right`},null,-1)]],2)),t[29]||=U(`span`,{class:`aiset__adv-title`},`高级:保活与预算阈值`,-1),U(`span`,OM,M(i.adv?``:`默认值经实测调优,不建议修改`),1)],8,DM),i.adv?(B(),V(`div`,kM,[t[50]||=U(`p`,{class:`aiset__adv-note`},[G(` 这几项是长程任务的`),U(`strong`,null,`熔断与保活阈值`),G(`,数值由实测调优得出(如纯思考预算从 90s 放宽到 600s,因 240s 会误伤正常轮次)。 留空即走默认,`),U(`strong`,null,`没有明确理由不建议改动`),G(`。 `)],-1),U(`div`,AM,[U(`div`,jM,[t[31]||=U(`span`,{class:`aiset__label`},`单轮步数上限`,-1),t[32]||=U(`span`,{class:`aiset__unit`},`0 / 留空 = 不限`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`maxSteps`}]),"aria-expanded":i.help===`maxSteps`,title:`查看说明`,onClick:t[5]||=q(e=>a.toggleHelp(`maxSteps`),[`stop`])},[...t[30]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,MM)]),U(`div`,NM,[W(s,{id:`common-maxsteps`,class:`aiset__stepper`,value:i.form.maxSteps>0?String(i.form.maxSteps):``,step:8,min:0,max:1e3,placeholder:`留空 = 不限(推荐)`,onInput:t[6]||=e=>a.onInt(`maxSteps`,e)},null,8,[`value`])]),i.help===`maxSteps`?(B(),V(`p`,PM,[...t[33]||=[U(`strong`,null,`普通用户不用管:留空 = 不限`,-1),G(`。失控由三道精准熔断兜住(同参打转跳过 / 单轮墙钟到点收尾 / 每 24 步提醒)。 只有想硬性控成本时才填(>0 即恢复旧硬顶行为)。 `,-1)]])):K(`v-if`,!0)]),U(`div`,FM,[U(`div`,IM,[t[35]||=U(`span`,{class:`aiset__label`},`单轮墙钟上限`,-1),t[36]||=U(`span`,{class:`aiset__unit`},`分钟`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`turnTimeout`}]),"aria-expanded":i.help===`turnTimeout`,title:`查看说明`,onClick:t[7]||=q(e=>a.toggleHelp(`turnTimeout`),[`stop`])},[...t[34]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,LM)]),U(`div`,RM,[W(s,{id:`common-turn`,class:`aiset__stepper`,value:i.form.turnTimeoutMin>0?String(i.form.turnTimeoutMin):``,step:5,min:0,max:240,placeholder:`留空 = 60`,onInput:t[8]||=e=>a.onInt(`turnTimeoutMin`,e)},null,8,[`value`])]),i.help===`turnTimeout`?(B(),V(`p`,zM,` 单轮允许跑的最长时间(分钟)。到点收尾汇报、上下文不丢,回复「继续」接着做。默认 60 分钟,不限步数后的唯一兜底闸门。 `)):K(`v-if`,!0)]),U(`div`,BM,[U(`div`,VM,[t[38]||=U(`span`,{class:`aiset__label`},`网关静默阈值`,-1),t[39]||=U(`span`,{class:`aiset__unit`},`分钟`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`stall`}]),"aria-expanded":i.help===`stall`,title:`查看说明`,onClick:t[9]||=q(e=>a.toggleHelp(`stall`),[`stop`])},[...t[37]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,HM)]),U(`div`,UM,[W(s,{id:`common-stall`,class:`aiset__stepper`,value:i.form.stallTimeoutMin>0?String(i.form.stallTimeoutMin):``,step:1,min:0,max:120,placeholder:`留空 = 2`,onInput:t[10]||=e=>a.onInt(`stallTimeoutMin`,e)},null,8,[`value`])]),i.help===`stall`?(B(),V(`p`,WM,` 上游多少分钟不回任何字节算「网关静默」;静默自动重试本步而非整轮报废。默认 2 分钟(120 秒)。 `)):K(`v-if`,!0)]),U(`div`,GM,[U(`div`,KM,[t[41]||=U(`span`,{class:`aiset__label`},`静默重试次数`,-1),t[42]||=U(`span`,{class:`aiset__unit`},`-1 = 默认`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`stallRetries`}]),"aria-expanded":i.help===`stallRetries`,title:`查看说明`,onClick:t[11]||=q(e=>a.toggleHelp(`stallRetries`),[`stop`])},[...t[40]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,qM)]),U(`div`,JM,[W(s,{id:`common-stallretries`,class:`aiset__stepper`,value:i.form.stallRetries>=0?String(i.form.stallRetries):``,step:1,min:-1,max:20,placeholder:`留空 / -1 = 3`,onInput:t[12]||=e=>a.onInt(`stallRetries`,e)},null,8,[`value`])]),i.help===`stallRetries`?(B(),V(`p`,YM,` 网关静默后的自动重试次数。0 = 回到「一次静默即报错」的旧行为;留空 / -1 = 用默认 3 次。 `)):K(`v-if`,!0)]),U(`div`,XM,[U(`div`,ZM,[t[44]||=U(`span`,{class:`aiset__label`},`纯思考预算`,-1),t[45]||=U(`span`,{class:`aiset__unit`},`分钟`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`reasoning`}]),"aria-expanded":i.help===`reasoning`,title:`查看说明`,onClick:t[13]||=q(e=>a.toggleHelp(`reasoning`),[`stop`])},[...t[43]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,QM)]),U(`div`,$M,[W(s,{id:`common-reasoning`,class:`aiset__stepper`,value:i.form.reasoningTimeoutMin>0?String(i.form.reasoningTimeoutMin):``,step:1,min:0,max:300,placeholder:`留空 = 10`,onInput:t[14]||=e=>a.onInt(`reasoningTimeoutMin`,e)},null,8,[`value`])]),i.help===`reasoning`?(B(),V(`p`,eN,` 单轮「纯思考」(不调工具)的预算(分钟)。到点催促 + 关深度思考重试;催 3 次仍无产出则停该熔断,改墙钟兜底。默认 10 分钟(600 秒)。 `)):K(`v-if`,!0)]),U(`div`,tN,[U(`div`,nN,[t[47]||=U(`span`,{class:`aiset__label`},`自动续跑上限`,-1),t[48]||=U(`span`,{class:`aiset__unit`},`-1 = 默认`,-1),U(`button`,{type:`button`,class:j([`aiset__help`,{"is-on":i.help===`autoContinue`}]),"aria-expanded":i.help===`autoContinue`,title:`查看说明`,onClick:t[15]||=q(e=>a.toggleHelp(`autoContinue`),[`stop`])},[...t[46]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-help`})],-1)]],10,rN)]),U(`div`,iN,[W(s,{id:`common-autocont`,class:`aiset__stepper`,value:i.form.autoContinueMax>=0?String(i.form.autoContinueMax):``,step:1,min:-1,max:200,placeholder:`留空 / -1 = 12`,onInput:t[16]||=e=>a.onInt(`autoContinueMax`,e)},null,8,[`value`])]),i.help===`autoContinue`?(B(),V(`p`,aN,[...t[49]||=[G(` 模型没给收尾标记(`,-1),U(`code`,null,`[任务完成]`,-1),G(` / `,-1),U(`code`,null,`[需用户确认]`,-1),G(`)就停手时的自动续跑次数上限。0 = 关闭(等你手打「继续」);留空 / -1 = 用默认 12。 `,-1)]])):K(`v-if`,!0)])])):K(`v-if`,!0)]),i.ping?(B(),V(`div`,{key:0,class:j([`aiset__ping`,i.ping.ok?`is-ok`:`is-bad`])},[(B(),V(`svg`,oN,[U(`use`,{href:i.ping.ok?`#icon-check`:`#icon-alert-triangle`},null,8,sN)])),U(`span`,null,M(i.ping.text),1)],2)):K(`v-if`,!0)]),U(`footer`,cN,[t[52]||=U(`span`,{class:`aiset__foot-gap`},null,-1),U(`button`,{type:`button`,class:`aiset__btn`,disabled:i.saving,onClick:t[17]||=t=>e.$emit(`close`)},`取消`,8,lN),U(`button`,{type:`button`,class:`aiset__btn aiset__btn--primary`,disabled:i.saving,onClick:t[18]||=(...e)=>a.save&&a.save(...e)},M(i.saving?`保存中…`:`保存`),9,uN)])])])}var fN=X(dM,[[`render`,dN],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/AiCommonSettings.vue`]]),pN=2e3;function mN(e){try{let t=JSON.stringify(e);return t==null?0:t.length}catch{return 1/0}}function hN(e,t){let n=typeof e==`string`?e:e==null?``:JSON.stringify(e);return n.length<=t?e:`${n.slice(0,t)}\n…(历史归档已裁剪,完整内容以卡片与落盘产物为准)`}function gN(e,t){if(!e||typeof e!=`object`)return e;let n={};for(let[r,i]of Object.entries(e))n[r]=typeof i==`string`||typeof i==`object`&&i?hN(i,t):i;return n}function _N(e,t=!1){let n=Array.isArray(e)?e:[],r=t?400:pN;return n.map(e=>{if(!e||!Array.isArray(e.toolCalls)||!e.toolCalls.length)return e;let n=!1,i=e.toolCalls.map(e=>{if(!e||typeof e!=`object`)return e;let i=gN(e.args,r),a=t?e.result==null||e.result===``?e.result:`[历史归档已裁剪]`:hN(e.result,r);return(JSON.stringify(i)!==JSON.stringify(e.args)||String(a)!==String(e.result))&&(n=!0),{...e,args:i,result:a}});return n?{...e,toolCalls:i,trimmedArchive:!0}:e})}var vN=12e3,yN={pick:{id:`pick`,label:`选一张已有的卡`,hint:`从顶栏下拉里挑`,icon:`#icon-search`,weight:`read`,text:`列出仓库里现有的卡片,按用途分组,帮我挑一张适合修改的。`},scaffold:{id:`scaffold`,label:`新建一张卡`,hint:`从空白骨架开始`,icon:`#icon-folder-plus`,weight:`write`,text:`帮我新建一张卡片:先用 card_scaffold 生成骨架,再按我的需求补齐结构与示例内容,最后自检。`},spec:{id:`spec`,label:`按设计稿标注建卡`,hint:`先拖入 MeaXure 目录`,icon:`#icon-image-upload`,weight:`write`,attach:!0,text:`我会挂载一份 Sketch MeaXure 标注导出目录,请按标注生成卡片 schema 并自检。`},fromimage:{id:`fromimage`,label:`从参考图建卡`,hint:`拖一张设计图进来`,icon:`#icon-image`,weight:`write`,attach:!0,text:`我会拖入一张参考设计图(本机路径),请按图生成卡片 schema 并截图自检还原度。`},learn:{id:`learn`,label:`看已有卡学写法`,hint:`只读,不改卡`,icon:`#icon-search`,weight:`read`,text:`列出仓库里结构最完整的几张卡片,读 1-2 张的关键片段,说明本仓库的建卡约定与常用范式。`},component:{id:`component`,label:`加一个常用组件`,hint:`列表 / 按钮 / 金额卡`,icon:`#icon-plus`,weight:`write`,text:`帮我给这张卡加一个常用组件(列表 / 按钮组 / 金额统计卡),按仓库范式写并自检。`},explain:{id:`explain`,label:`解释结构与数据来源`,hint:`只读,不改卡`,icon:`#icon-search`,weight:`read`,text:`读取当前卡片 schema,用中文解释它的结构、关键绑定与数据来源,指出可能的问题。`},bind:{id:`bind`,label:`把写死文案抽成变量`,hint:`绑定 data.json`,icon:`#icon-link`,weight:`write`,text:`把当前卡片里写死的动态值(金额 / 日期 / 名称等)抽成变量并绑定 data.json,保持展示文案与设计稿一致。`},fix:{id:`fix`,label:`校验并修复`,hint:`会改动卡片`,icon:`#icon-wrench`,weight:`write`,text:`对当前卡片执行校验,列出全部错误并按规则修复,修完再校验一次确认清零。`},shot:{id:`shot`,label:`截图自检还原度`,hint:`多尺寸预览比对`,icon:`#icon-images`,weight:`read`,text:`给当前卡片截图,检查布局、字号、间距与配色是否协调,指出需要调整的地方。`},interact:{id:`interact`,label:`加按钮点击行为`,hint:`customAction / 发消息`,icon:`#icon-send`,weight:`write`,text:`给当前卡片里的主按钮加点击行为(customAction 或发送一条消息),参照现有卡片的写法。`},diagnose:{id:`diagnose`,label:`定位并修复刚才的报错`,hint:`接上一轮`,icon:`#icon-alert-triangle`,weight:`write`,text:`上一轮失败了,请读取错误信息与上下文,定位原因并修复,修完再校验一次。`},resume:{id:`resume`,label:`从中断处继续`,hint:`不重做已完成部分`,icon:`#icon-redo`,weight:`write`,text:`上一轮被中断了,请按上下文里的中断标记从中断处继续,不要从零重做。`},rollback:{id:`rollback`,label:`回滚上一轮改动`,hint:`恢复到改动前`,icon:`#icon-undo`,weight:`write`,text:`把上一轮对卡片做的改动回滚到改动前,并说明回滚了什么。`}},bN={nocare:[`pick`,`scaffold`,`spec`,`learn`,`component`],empty:[`spec`,`fromimage`,`scaffold`,`component`,`learn`],card:[`explain`,`bind`,`fix`,`shot`,`interact`],error:[`diagnose`,`resume`,`rollback`,`explain`,`fix`]},xN={nocare:{title:`选择或新建一张卡`,desc:`先从顶栏选一张卡,或让 AI 新建一张;也可以把设计稿标注目录、参考图拖进来,只传本机路径不上传。`},empty:{title:`把这张空卡搭起来`,desc:`描述想要的效果,或拖入设计稿标注目录 / 参考图,AI 会按标注生成卡片并截图自检。`},error:{title:`接着上一轮往下做`,desc:`上一轮失败或被中断了:可以接着修、从中断处继续,或回滚到改动前。`},card:{title:`让 AI 直接改这张卡`,desc:`描述需求即可,AI 会调用卡片工具读改校验并截图自检;也可以把设计稿标注目录、参考图拖进来,只传本机路径不上传。`}};function SN(e){let t=Array.isArray(e)?e:[];for(let e=t.length-1;e>=0;--e){let n=t[e];if(n&&n.role===`assistant`)return n.status||`done`}return``}function CN({cardId:e,cardEmpty:t,messages:n}={}){if(!e)return`nocare`;if(t)return`empty`;let r=SN(n);return r===`error`||r===`aborted`?`error`:`card`}function wN(e){return(bN[e]||bN.card).map(e=>yN[e]).filter(Boolean)}function TN(e,t,n=4){let r=Array.isArray(e)?e:[];if(r.length<=n)return r.slice();let i=r.length,a=((Number(t)||0)%i+i)%i;return[...r.slice(a),...r.slice(0,a)].slice(0,n)}function EN(e,t=4){return(Array.isArray(e)?e:[]).slice(0,t)}var DN=`cardbuddy:ai-panel-width`,ON=2e4,kN=`cardbuddy:ai-compact-steps`,AN=380,jN=.5,MN=.33,NN=0;function PN(e=`m`){return NN+=1,`${e}${Date.now().toString(36)}-${NN}`}var FN=`有对话正在进行,无法修改正在使用的模型:请先等这一轮结束,或在输入区点「停止」`,IN={name:`ChatPanel`,components:{ChatMessage:lA,ChatComposer:LA,AiSettings:Lj,ModelList:lM,AiCommonSettings:fN,ConfirmDialog:_p},props:{visible:{type:Boolean,default:!1},cardId:{type:String,default:``},cardName:{type:String,default:``},cardEmpty:{type:Boolean,default:!1}},emits:[`close`,`busy`,`turn-progress`,`turn-finished`,`rollback-turn`,`locate-node`],data(){return{messages:[],draftAttachments:[],busy:!1,loadingHistory:!1,modelListOpen:!1,models:[],activeId:null,turnRunning:!1,modelEditOpen:!1,editModelId:null,editInitialModel:null,confirmDeleteModel:null,ccSwitchOpen:!1,ccSwitchProviders:[],ccSwitchLoading:!1,ccSwitchReason:``,ccSwitchSelected:{},commonOpen:!1,confirmClear:!1,notice:null,config:{baseUrl:``,model:``,hasKey:!1,apiKeyMasked:``},widthPx:0,winW:typeof window<`u`?window.innerWidth:1280,resizing:!1,gripArmed:!1,_gripTimer:null,listH:0,pinned:!0,contextUsage:null,compactSteps:!1,archiveTrimmed:!1,suggestOffset:0,suggestStats:{},confirmStop:!1,turnStep:0,turnStage:null,turnToolLabel:``,turnStartedAt:0,lastByteAt:0,turnId:``,lastSeq:0,_resumeProbe:!1,nowTs:0,_abort:null,_saveTimer:0,_loadedCard:``,_cardRenamedTo:``,_saving:!1,_liveTicker:0,_turnPersistTimer:0}},computed:{suggestBatchKey(){return CN({cardId:this.cardId,cardEmpty:this.cardEmpty,messages:this.messages})},suggestBatch(){return wN(this.suggestBatchKey)},suggestions(){return TN(this.suggestBatch,this.suggestOffset)},canShuffle(){return this.suggestBatch.length>4},quickChips(){return EN(this.suggestBatch)},emptyTitle(){return(xN[this.suggestBatchKey]||xN.card).title},emptyDesc(){return(xN[this.suggestBatchKey]||xN.card).desc},ccSwitchCheckedCount(){let e=this.ccSwitchSelected||{};return Object.keys(e).filter(t=>e[t]).length},ccSwitchDupCount(){return(this.ccSwitchProviders||[]).filter(e=>e.duplicate).length},configReady(){return!!(this.config.baseUrl&&this.config.model&&this.config.hasKey)},panelWidth(){let e=this.winW||1280,t=Math.max(AN,Math.floor(e*jN)),n=Math.round(e*MN),r=this.widthPx||n;return Math.max(AN,Math.min(t,r))},panelStyle(){let e={width:`${this.panelWidth}px`};return this.listH>0&&(e[`--ai-list-h`]=`${this.listH}px`),e},stallLimitMs(){let e=Number(this.config.stallTimeoutMs)>0?Number(this.config.stallTimeoutMs):12e4;return Math.round(e*1.5)},idleMs(){return this.lastByteAt?Math.max(0,(this.nowTs||Date.now())-this.lastByteAt):0},stalled(){return!!(this.busy&&this.idleMs>this.stallLimitMs)},liveText(){if(!this.busy)return``;let e=[];return this.turnStartedAt&&e.push(`${MD(this.turnStartedAt)} 开始`),this.turnStep>0&&e.push(`第 ${this.turnStep} 步`),e.push(`已用 ${this.fmtClock(this.nowTs-this.turnStartedAt)}`),this.turnStage?e.push(`${this.turnStage.id} ${this.turnStage.label}`):this.turnToolLabel&&e.push(this.turnToolLabel),this.stalled?`${Math.round(this.idleMs/1e3)} 秒没收到任何数据,连接可能已中断(${e.join(` · `)})`:(e.push(`最近数据 ${Math.round(this.idleMs/1e3)} 秒前`),e.join(` · `))}},watch:{suggestBatchKey(){this.suggestOffset=0},visible(e){e?(this.refreshConfig(),this.ensureHistory().then(()=>this.checkResumableTurn()),this.$nextTick(()=>{this.scrollToBottom(!0),this.$refs.composerEl?.focus()})):this.busy&&this.flushHistory()},cardId(e,t){if(this._cardRenamedTo&&this._cardRenamedTo===e){this._cardRenamedTo=``,this._dirtyFor===t&&(this._dirtyFor=e),this._loadedCard===t?(this._loadedCard=e,this._dirtyFor===e&&this.flushHistory(e)):(this._loadedCard=``,this.ensureHistory());return}this._saveTimer&&=(clearTimeout(this._saveTimer),0);let n=this._dirtyFor===t?this.serialize():null;this._dirtyFor=null,this.draftAttachments=[],this.messages=[],n&&t&&this.flushHistory(t,n),this.ensureHistory()}},mounted(){this.loadWidth(),this.loadCompact(),window.addEventListener(`resize`,this.onWinResize),window.addEventListener(`pagehide`,this.onPagehide),this.observeListHeight(),this.refreshConfig(),this.ensureHistory()},beforeUnmount(){window.removeEventListener(`resize`,this.onWinResize),window.removeEventListener(`pagehide`,this.onPagehide),this._stopListObserve&&this._stopListObserve(),this.stopTurnTimers(),this.stopTickers(),this.flushHistory(),this._abort&&this._abort.abort()},methods:{onWinResize(){this.winW=window.innerWidth},onImageClick(e){let t=e.target&&e.target.closest?e.target.closest(`img`):null;if(!t||t.dataset.noZoom===`1`)return;let n=Array.from(this.$el.querySelectorAll(`img`)).filter(e=>e.dataset.noZoom!==`1`),r=n.indexOf(t);r<0||DS(n.map(e=>({src:e.currentSrc||e.src,alt:e.alt||``,title:e.getAttribute(`title`)||e.closest(`[title]`)?.getAttribute(`title`)||``})),r)},observeListHeight(){let e=this.$refs.listEl;if(!e)return;let t=()=>{let t=Math.round(e.clientHeight||0);t>0&&t!==this.listH&&(this.listH=t)};if(t(),typeof ResizeObserver>`u`){this._stopListObserve=()=>window.removeEventListener(`resize`,t),window.addEventListener(`resize`,t);return}let n=new ResizeObserver(e=>{let n=Math.round(e?.[0]?.contentRect?.height||0);n>0&&n!==this.listH?this.listH=n:t()});n.observe(e),this._stopListObserve=()=>n.disconnect()},loadWidth(){try{let e=localStorage.getItem(DN);if(e!=null){let t=parseInt(e,10);!Number.isNaN(t)&&t>=AN&&(this.widthPx=t)}}catch{}},saveWidth(){try{this.widthPx?localStorage.setItem(DN,String(Math.round(this.panelWidth))):localStorage.removeItem(DN)}catch{}},armGrip(){clearTimeout(this._gripTimer),this._gripTimer=setTimeout(()=>{this.gripArmed=!0},300)},disarmGrip(){clearTimeout(this._gripTimer),this._gripTimer=null,!this.resizing&&(this.gripArmed=!1)},startResize(e){let t=e&&e.currentTarget;if(!t||!this.gripArmed)return;this.resizing=!0,document.body.style.cursor=`col-resize`,document.body.style.userSelect=`none`;let n=e.pointerId;try{t.setPointerCapture(n)}catch{}let r=e=>{let t=Math.max(AN,Math.floor(window.innerWidth*jN));this.widthPx=Math.max(AN,Math.min(t,Math.round(window.innerWidth-e.clientX)))},i=()=>{t.removeEventListener(`pointermove`,r),t.removeEventListener(`pointerup`,i),t.removeEventListener(`pointercancel`,i),window.removeEventListener(`blur`,i);try{t.hasPointerCapture?.(n)&&t.releasePointerCapture(n)}catch{}this.resizing=!1,document.body.style.cursor=``,document.body.style.userSelect=``,this.saveWidth()};t.addEventListener(`pointermove`,r),t.addEventListener(`pointerup`,i),t.addEventListener(`pointercancel`,i),window.addEventListener(`blur`,i)},resetWidth(){this.widthPx=0,this.saveWidth()},async refreshConfig(){try{let e=await hO();this.config={...e,hasKey:!!(e.hasKey||e.apiKey)},e.turnRunning!==void 0&&(this.turnRunning=e.turnRunning===!0)}catch{this.config={baseUrl:``,model:``,hasKey:!1,apiKeyMasked:``}}},async loadModels(){try{let e=await _O();this.models=Array.isArray(e.models)?e.models:[],this.activeId=e.activeId||null,this.turnRunning=e.turnRunning===!0}catch{this.models=[],this.activeId=null}},openModelList(){this.modelListOpen=!0,this.loadModels(),this.refreshConfig()},closeModelList(){this.modelListOpen=!1},onModelAdd(){this.modelListOpen=!1,this.editModelId=null,this.editInitialModel=null,this.modelEditOpen=!0},onModelEdit(e){if(this.turnRunning&&e&&e.id===this.activeId)return this.notify(`warn`,FN);this.modelListOpen=!1,this.editModelId=e&&e.id?e.id:null,this.editInitialModel=e||null,this.modelEditOpen=!0},onModelEditClose(){this.modelEditOpen=!1,this.modelListOpen=!0},async onModelSaved(){this.modelEditOpen=!1,this.modelListOpen=!0,await this.loadModels(),await this.refreshConfig()},async onModelActivate(e){if(!(!e||!e.id)){if(this.turnRunning&&e.id!==this.activeId)return this.notify(`warn`,FN);try{await CO(e.id)}catch(e){this.notify(`warn`,`切换模型失败:${e.message||e}`)}await this.loadModels(),await this.refreshConfig()}},onModelDelete(e){if(!(!e||!e.id)){if(this.turnRunning&&e.id===this.activeId)return this.notify(`warn`,FN);this.confirmDeleteModel=e}},async doDeleteModel(){let e=this.confirmDeleteModel;if(this.confirmDeleteModel=null,!(!e||!e.id)){try{await SO(e.id)}catch(e){this.notify(`warn`,`删除失败:${e.message||e}`);return}await this.loadModels(),await this.refreshConfig(),this.notify(`ok`,`已删除模型「${e.name||e.model||e.id}」`)}},get deleteModelMessage(){let e=this.confirmDeleteModel;return`确定删除模型「${e?e.name||e.model||e.id:``}」吗?此操作不可撤销,配置将从 .env.cb.local 移除${e&&e.id===this.activeId?`。该模型当前为生效模型,删除后会自动回落到剩余模型中的第一条(若已无模型则需重新添加)。`:`。`}`},async onImportCcSwitch(){this.ccSwitchOpen=!0,this.ccSwitchLoading=!0,this.ccSwitchProviders=[],this.ccSwitchReason=``,this.ccSwitchSelected={};try{let e=await vO(),t=Array.isArray(e.providers)?e.providers:[],n=this.models.map(e=>e.model).filter(Boolean);t.forEach(e=>{e.duplicate=n.includes(e.model)}),this.ccSwitchProviders=t,t.length||(this.ccSwitchReason=e.reason||`cc-switch 中没有可导入的 Codex 类供应商`)}catch(e){this.ccSwitchReason=`读取 cc-switch 失败:${e&&e.message||e}`}finally{this.ccSwitchLoading=!1}},toggleCcSwitchItem(e){if(!e||e.duplicate)return;let t={...this.ccSwitchSelected};t[e.id]?delete t[e.id]:t[e.id]=!0,this.ccSwitchSelected=t},async confirmImportCcSwitch(){let e=this.ccSwitchProviders.filter(e=>this.ccSwitchSelected[e.id]&&!e.duplicate);if(!e.length)return;let t=0,n=0;for(let r of e)try{await bO({name:r.name||r.model,baseUrl:r.baseUrl,apiKey:r.apiKey||``,model:r.model,maxTokens:0,thinking:!1,vision:!1}),t++}catch(e){n++,console.error(`[cc-switch 导入失败]`,r.name,e)}this.ccSwitchOpen=!1,await this.loadModels(),await this.refreshConfig(),n?this.notify(`warn`,`导入完成:成功 ${t} 个、失败 ${n} 个`):this.notify(`ok`,`已从 cc-switch 导入 ${t} 个模型`)},openCommon(){this.modelListOpen=!1,this.commonOpen=!0},async onCommonSaved(){this.commonOpen=!1,await this.refreshConfig(),this.notify(`ok`,`通用设置已保存`)},async ensureHistory(){let e=this.cardId;if(!(!e||this._loadedCard===e)){this._loadedCard=e,this.loadingHistory=!0;try{let t=await MO(e);if(this.cardId!==e)return;let n=this.busy?this.turnId:``,r=(t.messages||[]).map(e=>this.revive(e)).filter(e=>!(n&&e.role===`assistant`&&e.turnId===n));this.archiveTrimmed=r.some(e=>e.trimmedArchive===!0);let i=new Set(r.map(e=>e.id)),a=this.messages.filter(e=>!i.has(e.id));this.messages=[...r,...a],this.contextUsage=null,this._dirtyFor=null,this.checkResumableTurn(),this.$nextTick(()=>this.scrollToBottom(!0))}catch{this.cardId===e&&(this.messages=[]),this._dirtyFor=null}finally{this.cardId===e&&(this.loadingHistory=!1)}}},serialize(){return this.messages.map(e=>{let t={id:e.id,role:e.role,content:e.content||``,ts:e.ts};return e.role===`assistant`?(t.reasoning=e.reasoning||``,t.reasoningMs=e.reasoningMs||0,t.error=e.error||``,e.errorCode&&(t.errorCode=e.errorCode),e.events?.length&&(t.events=e.events.map(e=>({ts:e.ts||0,level:e.level||`warn`,code:e.code||``,message:e.message||``}))),t.elapsedMs=e.elapsedMs||0,t.status=e.status===`streaming`?`aborted`:e.status||`done`,e.turnId&&(t.turnId=e.turnId),e.serverAuthored&&(t.serverAuthored=!0),e.budget?.message&&(t.budget={reason:e.budget.reason||``,message:e.budget.message}),e.usage&&(t.usage=e.usage),e.toolCalls?.length&&(t.toolCalls=e.toolCalls.map(e=>({toolCallId:e.toolCallId,toolName:e.toolName,args:e.args||{},result:e.result,error:e.error||``,ms:e.ms||0,startedAt:e.startedAt||0,command:e.command||``,approvalNote:e.approvalNote||``,autoApproved:!!e.autoApproved})))):e.attachments?.length&&(t.attachments=e.attachments.map(e=>({path:e.path,name:e.name,isDir:!!e.isDir,isImage:!!e.isImage,size:e.size||0,entryCount:e.entryCount||0,exists:e.exists!==!1}))),t})},revive(e){return{id:e.id||PN(),role:e.role===`user`?`user`:`assistant`,content:e.content||``,reasoning:e.reasoning||``,reasoningMs:e.reasoningMs||0,elapsedMs:Number(e.elapsedMs)||0,toolCalls:Array.isArray(e.toolCalls)?e.toolCalls.map(t=>(e.status===`aborted`||e.status===`streaming`)&&t&&!t.error&&t.result==null?{...t,error:`已终止:该调用未拿到结果(轮次被中断)`}:t):[],attachments:Array.isArray(e.attachments)?e.attachments:[],events:Array.isArray(e.events)?e.events:[],error:e.error||``,errorCode:e.errorCode||``,trimmedArchive:e.trimmedArchive===!0,status:e.status||`done`,turnId:e.turnId||``,serverAuthored:e.serverAuthored===!0,budget:e.budget?.message?{reason:e.budget.reason||``,message:e.budget.message}:void 0,ts:e.ts||0}},persist(){this.cardId&&(this._dirtyFor=this.cardId,this._saveTimer&&clearTimeout(this._saveTimer),this._saveTimer=setTimeout(()=>this.flushHistory(),500))},fitArchive(e){if(mN(e)<=4e6)return e;let t=_N(e,!1);return mN(t)>4e6&&(t=_N(t,!0)),this.archiveTrimmed=!0,t},async flushHistory(e=this.cardId,t=null){if(this._saveTimer&&=(clearTimeout(this._saveTimer),0),e){if(this._saving){this._saveTimer=setTimeout(()=>this.flushHistory(e,t),800);return}this._saving=!0;try{await NO(e,this.fitArchive(t||this.serialize())),this._dirtyFor===e&&(this._dirtyFor=null)}catch(e){this.notify(`warn`,`对话记录保存失败:${e.message||e}`)}finally{this._saving=!1}}},migrateCard(e,t){!e||!t||e===t||this.cardId===e&&(this._saveTimer&&=(clearTimeout(this._saveTimer),0),this._cardRenamedTo=t,this._dirtyFor===e&&(this._dirtyFor=t))},discardCard(e){e&&(this._saveTimer&&=(clearTimeout(this._saveTimer),0),this._dirtyFor===e&&(this._dirtyFor=null),(this._loadedCard===e||this.cardId===e)&&(this.busy&&this._abort&&this._abort.abort(),this.messages=[],this.draftAttachments=[],this.contextUsage=null,this._loadedCard=``))},askClear(){this.messages.length&&(this.confirmClear=!0)},async doClear(){this.confirmClear=!1;let e=this.cardId;this.messages=[],this.contextUsage=null,this._loadedCard=e,this._dirtyFor=null,this._saveTimer&&=(clearTimeout(this._saveTimer),0);try{await PO(e),this.notify(`ok`,`已清空本卡片的对话记录`)}catch(e){this.notify(`warn`,`清空失败:${e.message||e}`)}},async onPick(e){try{let t=await EO(e);if(t.cancelled)return;for(let e of t.items||[])this.pushAttachment(e);t.items?.length||this.notify(`warn`,`未选到可用文件`)}catch(e){this.notify(`warn`,e.message||`无法调起系统选择器,可改用拖拽或粘贴路径`)}},async onAddPath(e){try{let t=await DO(e);this.pushAttachment(t)}catch(t){this.notify(`warn`,`路径不可用:${e}(${t.message||t})`)}},async onPasteImage(e){try{let t=await AO(e);this.pushAttachment(t,`粘贴的截图已存到本机 .cache/ai-attachments/`)}catch(e){this.notify(`warn`,`截图保存失败:${e.message||e}`)}},async onDropFiles(e){let t=Array.from(e.items||[]).map(e=>e.webkitGetAsEntry?e.webkitGetAsEntry():null).filter(Boolean),n=Array.from(e.files||[]),r=[];if(t.length)for(let e of t)r.push(this.resolveEntry(e));else for(let e of n)r.push(this.resolveFile(e));if(!r.length){this.notify(`warn`,`没有识别到可挂载的文件`);return}let i=(await Promise.all(r)).filter(e=>!e).length;i&&this.notify(`warn`,`${i} 项未能定位本机路径,可改用「粘贴路径」添加`)},async resolveEntry(e){if(e.isDirectory){let t=await this.firstFileInDir(e);return this.resolveByName(e.name,e.fullPath||e.name,t?.size??-1)}let t=await this.entryToFile(e);return t?this.resolveFile(t):this.resolveByName(e.name,e.fullPath||e.name,-1)},async resolveFile(e){return this.resolveByName(e.name,e.webkitRelativePath||e.name,e.size)},async resolveByName(e,t,n){let r={id:PN(`att`),path:``,name:e,isDir:!1,isImage:!1,pending:!0};this.draftAttachments=[...this.draftAttachments,r];try{let r=await kO(OO({name:e,relPath:t,size:n}),ON,`locate`);return this.pushAttachment(r),r}catch{return null}finally{this.draftAttachments=this.draftAttachments.filter(e=>e.id!==r.id)}},entryToFile(e){return new Promise(t=>{try{e.file(e=>t(e),()=>t(null))}catch{t(null)}})},firstFileInDir(e){return new Promise(t=>{try{e.createReader().readEntries(async e=>{for(let n of e||[])if(!n.isDirectory){let e=await this.entryToFile(n);if(e)return t(e)}t(null)},()=>t(null))}catch{t(null)}})},pushAttachment(e,t){e?.path&&(this.draftAttachments.some(t=>t.path===e.path)||(this.draftAttachments=[...this.draftAttachments,{...e,note:t}],t&&this.notify(`ok`,t)))},removeAttachment(e){e&&(this.draftAttachments=this.draftAttachments.filter(t=>(t.id||t.path)!==e))},useSuggestion(e){this.$refs.composerEl?.setText(e.text),this.trackSuggest(e)},shuffleSuggestions(){let e=this.suggestBatch.length;e&&(this.suggestOffset=(this.suggestOffset+4)%e)},trackSuggest(e){if(!(!e||!e.id)){this.suggestStats[e.id]=(this.suggestStats[e.id]||0)+1;try{window.dispatchEvent(new CustomEvent(`cardbuddy:suggest`,{detail:{id:e.id,label:e.label,weight:e.weight,batch:this.suggestBatchKey}}))}catch{}}},async onSend({text:e,attachments:t}){if(this.busy||!await this.ensureConfig())return;this.notice=null;let n={id:PN(`u`),role:`user`,content:e,attachments:t.map(e=>({...e})),ts:Date.now()};this.messages.push(n),this.draftAttachments=[],this.pinned=!0,await this.runTurn({retractMsgId:n.id,draft:{text:e,attachments:n.attachments}})},async ensureConfig(){return await this.refreshConfig(),this.configReady?!0:(this.modelListOpen=!0,this.loadModels(),this.notify(`warn`,`请先在模型库中添加并配置模型(Base URL / API Key / 模型名)`),!1)},onContinue(){this.busy||this.onSend({text:`继续`,attachments:[]})},async regenerate(e){if(this.busy)return;let t=this.messages.findIndex(t=>t.id===e.id);t>0&&(this.messages=this.messages.slice(0,t)),await this.runTurn()},async runTurn(e={}){this.messages.push({id:PN(`a`),role:`assistant`,content:``,reasoning:``,reasoningMs:0,toolCalls:[],events:[],error:``,status:`streaming`,ts:Date.now()});let t=this.messages[this.messages.length-1],n=t.id;this.busy=!0,this.pinned=!0,this.startTurn();let r=new AbortController;this._abort=r;let i=!1,a=Date.now(),o=()=>{t.reasoning&&!t.reasoningMs&&(t.reasoningMs=Date.now()-a)};try{await IO({messages:this.toWire(this.messages.filter(e=>e.id!==n)),cardContext:this.cardId?{id:this.cardId}:void 0,attachments:this.lastAttachments(),signal:r.signal,onEvent:e=>this.onEvent(e,t,o)}),t.status===`streaming`&&(t.status=`done`)}catch(a){let s=r.signal.aborted||/abort/i.test(String(a?.message||a));o(),a?.code===`turn-in-flight`?(i=!0,this.messages=this.messages.filter(t=>t.id!==n&&t.id!==e.retractMsgId),e.draft&&(this.draftAttachments=(e.draft.attachments||[]).map(e=>({...e})),this.$refs.composerEl?.setText(e.draft.text||``)),this.notify(`warn`,String(a?.message||`这张卡片已有一个回合在跑:请先终止或等它结束,再发新消息`)),this.$nextTick(()=>this.checkResumableTurn())):s?t.status=`aborted`:await this.reattachAfterDrop(t,o)?this.pushEvent(t,{level:`info`,code:`stream-resumed`,message:`已接回本回合,继续跟随进度`}):(t.error=String(a?.message||a),t.errorCode=String(a?.code||``),t.status=`error`)}finally{o(),this.endTurn(t,{rejected:i})}},endTurn(e,{rejected:t=!1}={}){e.status===`streaming`&&(e.status=`done`),t||(e.elapsedMs=Math.max(0,Date.now()-this.turnStartedAt)),this.busy=!1,this._abort=null,this.stopTurnTimers(),this.persist(),this.$emit(`busy`,!1),t||this.$emit(`turn-finished`,{status:e.status,error:e.error||``,steps:this.turnStep,ms:Date.now()-this.turnStartedAt,startedAt:this.turnStartedAt,finishedAt:Date.now(),turnId:this.turnId||e.turnId||``}),this.$nextTick(()=>this.scrollToBottom())},async checkResumableTurn(){let e=this.cardId;if(!(!e||this.busy||this._resumeProbe)){this._resumeProbe=!0;try{let t;try{t=await LO(e)}catch{return}let n=t&&t.active;if(!n||!n.turnId||this.cardId!==e||this.busy)return;await this.attachToTurn({cardId:e,turnId:String(n.turnId),startedAt:Number(n.startedAt)||0,afterSeq:0,note:n.detached?`接回一个仍在服务端运行的回合(上次连接已中断,进度与已落盘产物都在)`:`接回本回合的实时进度`})}finally{this._resumeProbe=!1}}},async attachToTurn({cardId:e,turnId:t,startedAt:n=0,afterSeq:r=0,note:i=``}){let a=this.messages.find(e=>e.role===`assistant`&&e.turnId===t);a||=(this.messages.push({id:PN(`a`),role:`assistant`,content:``,reasoning:``,reasoningMs:0,toolCalls:[],events:[],error:``,status:`streaming`,ts:n||Date.now(),turnId:t}),this.messages[this.messages.length-1]),a.content=``,a.reasoning=``,a.reasoningMs=0,a.toolCalls=[],a.events=[],a.error=``,a.errorCode=``,a.budget=void 0,a.status=`streaming`,a.turnId=t,this.busy=!0,this.pinned=!0,this.startTurn(),this.turnId=t,this.lastSeq=Number(r)||0,n&&(this.turnStartedAt=n,a.ts=n);let o=new AbortController;this._abort=o;let s=n||Date.now(),c=()=>{a.reasoning&&!a.reasoningMs&&(a.reasoningMs=Date.now()-s)};i&&this.notify(`warn`,i);try{this.lastSeq=await zO({cardId:e,turnId:t,afterSeq:this.lastSeq,signal:o.signal,onEvent:e=>this.onEvent(e,a,c)})}catch(e){o.signal.aborted||/abort/i.test(String(e?.message||e))||(a.error=String(e?.message||e),a.errorCode=String(e?.code||``),a.status=`error`)}finally{c(),this.endTurn(a)}},async reattachAfterDrop(e,t){let n=this.cardId,r=this.turnId||e.turnId,i=this._abort;if(!n||!r||!i||i.signal.aborted)return!1;try{return this.pushEvent(e,{level:`warn`,code:`stream-dropped`,message:`连接中断:正在按断点续订本回合(服务端仍在跑,已执行的写入不受影响)`}),this.lastSeq=await zO({cardId:n,turnId:r,afterSeq:this.lastSeq,signal:i.signal,onEvent:n=>this.onEvent(n,e,t)}),!0}catch{return!1}},onEvent(e,t,n){this.lastByteAt=Date.now();let r=Number(e.seq)||0;switch(r>this.lastSeq&&(this.lastSeq=r),e.type){case`turn-start`:e.turnId&&(this.turnId=String(e.turnId),t.turnId=String(e.turnId)),Number(e.startedAt)&&(this.turnStartedAt=Number(e.startedAt),t.ts=Number(e.startedAt));break;case`client-detached`:this.pushEvent(t,{level:`info`,code:`client-detached`,message:`连接曾中断,回合在服务端继续跑(事件已全部落日志)`});break;case`turn-end`:(e.status===`aborted`||e.status===`error`)&&(t.status=e.status),e.usage&&this.applyUsage(t,e.usage);break;case`usage`:this.applyUsage(t,e);break;case`reasoning-delta`:t.reasoning+=e.text||``;break;case`text-delta`:n(),t.content+=e.text||``;break;case`tool-call-start`:n(),this.findToolRow(t,e)||t.toolCalls.push({toolCallId:e.toolCallId||PN(`tc`),toolName:e.toolName,args:{},pending:!0,result:void 0,error:``,startedAt:Date.now(),ms:0});break;case`tool-call`:{n();let r=this.findToolRow(t,e);r?(e.toolCallId&&(r.toolCallId=e.toolCallId),e.toolName&&(r.toolName=e.toolName),r.args=e.args||{},r.pending=!1):t.toolCalls.push({toolCallId:e.toolCallId||PN(`tc`),toolName:e.toolName,args:e.args||{},result:void 0,error:``,startedAt:Date.now(),ms:0});break}case`tool-result`:{let n=t.toolCalls.find(t=>t.toolCallId===e.toolCallId||!e.toolCallId&&t.toolName===e.toolName&&t.result===void 0);n&&(n.result=e.result??``,n.truncated=!!e.truncated,e.error&&(n.error=String(e.error)),e.image&&(n.image=e.image),n.ms=Date.now()-(n.startedAt||Date.now())),this.persist();break}case`approval-request`:{let n=this.findToolRow(t,e)||t.toolCalls[t.toolCalls.length-1];n&&n.toolName===e.toolName&&n.result===void 0?(n.approvalId=e.approvalId,e.command&&(n.command=e.command),n.needsApproval=!0):t.toolCalls.push({toolCallId:e.toolCallId||PN(`tc`),toolName:e.toolName,args:e.args||{},command:e.command||``,approvalId:e.approvalId,needsApproval:!0,result:void 0,error:``,startedAt:Date.now(),ms:0});break}case`approval-decided`:{let n=(t.toolCalls||[]).find(t=>t.approvalId===e.approvalId);n&&(n.needsApproval=!1,n.approvalNote=e.ok?e.scope===`turn`?`已允许,本回合后续同类执行不再询问…`:`已允许,执行中…`:e.reason||`已拒绝执行`);break}case`approval-auto`:{let n=this.findToolRow(t,e)||[...t.toolCalls||[]].reverse().find(t=>t.toolName===e.toolName&&t.result===void 0);n&&(e.command&&(n.command=e.command),n.autoApproved=!0,n.approvalNote=`按设置免确认执行`);break}case`notice`:{let n=e.level===`info`||e.level===`error`?e.level:`warn`;this.pushEvent(t,{level:n,code:e.code||``,message:e.message||``}),n!==`info`&&this.notify(n===`error`?`danger`:`warn`,e.message||``);break}case`round-retry`:{let n=Number(e.dropReasoning)||0,r=Number(e.dropText)||0,i=Number(e.dropTools)||0;n>0&&(t.reasoning=t.reasoning.slice(0,Math.max(0,t.reasoning.length-n))),r>0&&(t.content=t.content.slice(0,Math.max(0,t.content.length-r))),i>0&&t.toolCalls.splice(Math.max(0,t.toolCalls.length-i),i),t.reasoning||(t.reasoningMs=0),this.pushEvent(t,{level:`warn`,code:`retry-${e.reason||`unknown`}`,message:e.message||``}),this.notify(`warn`,e.message||``);break}case`context-usage`:this.contextUsage={used:Number(e.used)||0,total:Number(e.total)||0,window:Number(e.window)||0};break;case`turn-ended`:t.budget={reason:String(e.reason||``),message:String(e.message||``)};break;case`error`:t.error=t.error?`${t.error}\n${e.message}`:String(e.message||``),e.code&&(t.errorCode=String(e.code)),t.status=`error`;break;case`aborted`:t.status=`aborted`}let i=t.toolCalls||[];this.turnStep=i.length;let a=i[i.length-1];if(a){this.turnToolLabel=`正在${OD(a.toolName)}…`;let e=FD(a);e&&(!this.turnStage||e.order>this.turnStage.order)&&(this.turnStage=e)}this.$nextTick(()=>this.scrollToBottom())},async onApproval({tc:e,ok:t,scope:n=`once`}){if(e?.approvalId){e.needsApproval=!1,e.approvalNote=t?n===`turn`?`已允许,本回合后续同类执行不再询问…`:`已允许,执行中…`:`已拒绝执行`;try{await jO({approvalId:e.approvalId,ok:t,scope:n})}catch(e){this.notify(`warn`,`审批提交失败:${e.message}`)}}},findToolRow(e,t){let n=e.toolCalls||[];if(t.toolCallId){let e=n.find(e=>e.toolCallId===t.toolCallId);if(e)return e}return n.find(e=>e.pending&&e.toolName===t.toolName)||null},stop(){this.confirmStop=!1;let e=this._abort,t=this.cardId,n=this.turnId||``;t&&n&&RO(t).catch(e=>{e?.code!==`no-turn`&&this.notify(`warn`,`终止请求未送达:${e.message}`)}),e&&(e.abort(),this.notify(`ok`,`已终止本次生成`))},doStop(){this.stop()},onEscape(){if(this.confirmStop){this.confirmStop=!1;return}if(this.confirmDeleteModel){this.confirmDeleteModel=null;return}if(this.commonOpen){this.commonOpen=!1;return}if(this.modelListOpen||this.modelEditOpen){this.modelListOpen=!1,this.modelEditOpen=!1;return}if(this.busy){this.confirmStop=!0;return}this.$emit(`close`)},lastAttachments(){for(let e=this.messages.length-1;e>=0;e--){let t=this.messages[e];if(t.role===`user`)return(t.attachments||[]).map(e=>({path:e.path,name:e.name,isDir:e.isDir,isImage:e.isImage}))}return[]},toWire(e){return e.map(e=>{if(e.role===`user`){let t=e.attachments||[],n=e.content||``;if(t.length){let e=t.map(e=>`- ${e.isDir?`文件夹`:e.isImage?`图片`:`文件`}:${e.path}`);n=`${n}${n?`
|
|
278
278
|
|
|
279
279
|
`:``}[已挂载本地文件(仅本机路径,未上传;需要内容请用工具读取)]\n${e.join(`
|
|
280
|
-
`)}`}return{role:`user`,content:n}}let t=(e.toolCalls||[]).filter(e=>e.result!==void 0||e.error).map(e=>({toolCallId:e.toolCallId,toolName:e.toolName,args:e.args||{},result:typeof e.result==`string`?e.result.slice(0,
|
|
281
|
-
输入区拖高 / 反馈条出现都不会把它盖住或悬空 `),U(`div`,
|
|
282
|
-
长任务里「还活着吗」全靠这一行——旧版只有一句「生成中…」,网关静默与真在跑无从区分 `),i.busy?(B(),V(`div`,{key:0,class:j([`aichat__live`,{"is-stalled":a.stalled}]),role:`status`,"aria-live":`polite`},[t[35]||=U(`span`,{class:`aichat__live-dot`},null,-1),U(`span`,tP,M(a.liveText),1),a.stalled?(B(),V(`button`,{key:0,type:`button`,class:`aichat__live-act`,title:`连接可能已中断,终止本轮(已落盘的产物会保留)`,onClick:t[11]||=(...e)=>a.stop&&a.stop(...e)},` 终止 `)):K(`v-if`,!0)],2)):K(`v-if`,!0)],64)):(B(),V(`div`,WN,[t[34]||=U(`span`,{class:`aichat__empty-logo`},[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-sparkles`})])],-1),U(`p`,GN,M(a.emptyTitle),1),U(`p`,KN,M(a.emptyDesc),1),U(`div`,qN,[(B(!0),V(z,null,R(a.suggestions,e=>(B(),V(`button`,{key:e.id,type:`button`,class:j([`aichat__suggest`,`is-${e.weight}`]),title:e.text,"data-suggest-id":e.id,onClick:t=>a.useSuggestion(e)},[(B(),V(`svg`,YN,[U(`use`,{href:e.icon},null,8,XN)])),U(`span`,ZN,[U(`span`,QN,M(e.label),1),U(`span`,$N,M(e.hint),1)]),e.weight===`write`?(B(),V(`span`,eP,`改卡`)):K(`v-if`,!0)],10,JN))),128)),a.canShuffle?(B(),V(`button`,{key:0,type:`button`,class:`aichat__suggest-shuffle`,onClick:t[9]||=(...e)=>a.shuffleSuggestions&&a.shuffleSuggestions(...e)},[...t[33]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-refresh`})],-1),U(`span`,null,`换一批`,-1)]])):K(`v-if`,!0)])]))],544),K(` 回到底部:脱离底部吸附时出现 `),I(U(`button`,{type:`button`,class:`aichat__jump`,title:`回到底部`,onClick:t[13]||=e=>a.scrollToBottom(!0)},[...t[36]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-arrow-down`})],-1)]],512),[[Sc,!i.pinned&&i.messages.length]])]),K(` 常驻「常用」指令:有对话后空态建议区不再出现,这里保留一排轻量入口,随上下文同源 `),a.quickChips.length&&i.messages.length&&!i.busy?(B(),V(`div`,nP,[(B(!0),V(z,null,R(a.quickChips,e=>(B(),V(`button`,{key:e.id,type:`button`,class:j([`aichat__chip`,`is-${e.weight}`]),title:e.text,"data-suggest-id":e.id,onClick:t=>a.useSuggestion(e)},[(B(),V(`svg`,iP,[U(`use`,{href:e.icon},null,8,aP)])),U(`span`,null,M(e.label),1)],10,rP))),128))])):K(`v-if`,!0),K(` 操作反馈(附件解析失败 / 历史保存失败等) `),i.notice?(B(),V(`div`,{key:2,class:j([`aichat__notice`,`aichat__notice--${i.notice.type}`])},[U(`span`,null,M(i.notice.text),1),U(`button`,{type:`button`,class:`aichat__notice-x`,title:`关闭`,onClick:t[14]||=e=>i.notice=null},[...t[37]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])],2)):K(`v-if`,!0),W(s,{ref:`composerEl`,busy:i.busy,model:i.config.model,attachments:i.draftAttachments,placeholder:a.configReady?`描述你要改的卡片,Enter 发送 / Shift+Enter 换行`:`请先在设置中配置模型…`,context:i.contextUsage,onSend:a.onSend,onStop:a.stop,onPick:a.onPick,onAddPath:a.onAddPath,onRemoveAttachment:a.removeAttachment,onDropFiles:a.onDropFiles,onPasteImage:a.onPasteImage,onEscape:a.onEscape},null,8,[`busy`,`model`,`attachments`,`placeholder`,`context`,`onSend`,`onStop`,`onPick`,`onAddPath`,`onRemoveAttachment`,`onDropFiles`,`onPasteImage`,`onEscape`]),K(` 一级面板:模型库。从齿轮 / 横幅 / 消息内「去设置」进入 `),i.modelListOpen?(B(),H(c,{key:3,models:i.models,"active-id":i.activeId,"turn-running":i.turnRunning,onClose:a.closeModelList,onAdd:a.onModelAdd,onEdit:a.onModelEdit,onDelete:a.onModelDelete,onActivate:a.onModelActivate,onImportCcswitch:a.onImportCcSwitch,onOpenCommon:a.openCommon},null,8,[`models`,`active-id`,`turn-running`,`onClose`,`onAdd`,`onEdit`,`onDelete`,`onActivate`,`onImportCcswitch`,`onOpenCommon`])):K(`v-if`,!0),K(` 新增 / 编辑模型:复用 AiSettings(modelId 区分,initialModel 预填) `),i.modelEditOpen?(B(),H(l,{key:4,config:i.config,"model-id":i.editModelId,"initial-model":i.editInitialModel,onClose:a.onModelEditClose,onSaved:a.onModelSaved},null,8,[`config`,`model-id`,`initial-model`,`onClose`,`onSaved`])):K(`v-if`,!0),K(` 删除模型确认:二次确认后才真正落盘删除 `),W(u,{visible:!!i.confirmDeleteModel,"close-on-mask":!1,title:`删除模型`,message:a.deleteModelMessage,"confirm-text":`删除`,severity:`danger`,onConfirm:a.doDeleteModel,onCancel:t[15]||=e=>i.confirmDeleteModel=null},null,8,[`visible`,`message`,`onConfirm`]),K(` cc-switch 导入弹窗:列出 cc-switch 的 Codex 类供应商,勾选后批量导入模型库(按 model 去重) `),W(ic,{name:`modal`},{default:Lr(()=>[i.ccSwitchOpen?(B(),V(`div`,{key:0,class:`ni-overlay`,onClick:t[19]||=q(e=>i.ccSwitchOpen=!1,[`self`])},[U(`div`,oP,[U(`div`,sP,[t[38]||=U(`span`,{class:`ni-title`},`从 cc-switch 导入`,-1),U(`button`,{class:`ni-close`,type:`button`,title:`关闭`,onClick:t[16]||=e=>i.ccSwitchOpen=!1})]),U(`div`,cP,[U(`div`,lP,[K(` 加载中 `),i.ccSwitchLoading?(B(),V(`p`,uP,`正在读取 cc-switch 供应商…`)):i.ccSwitchReason?(B(),V(z,{key:1},[K(` 无可导入项 `),U(`p`,dP,M(i.ccSwitchReason),1)],2112)):(B(),V(z,{key:2},[K(` 供应商列表 `),U(`ul`,fP,[(B(!0),V(z,null,R(i.ccSwitchProviders,e=>(B(),V(`li`,{key:e.id,class:j([`ccsw-dlg__item`,{"is-active":i.ccSwitchSelected[e.id],"is-dup":e.duplicate}]),onClick:t=>a.toggleCcSwitchItem(e)},[U(`span`,{class:j([`ccsw-dlg__check`,{"is-on":i.ccSwitchSelected[e.id]}])},[i.ccSwitchSelected[e.id]?(B(),V(`svg`,mP,[...t[39]||=[U(`use`,{href:`#icon-check`},null,-1)]])):K(`v-if`,!0)],2),U(`span`,hP,[U(`span`,gP,[G(M(e.name||e.model)+` `,1),e.isCurrent?(B(),V(`span`,_P,`当前`)):K(`v-if`,!0),e.duplicate?(B(),V(`span`,vP,`已存在`)):K(`v-if`,!0)]),U(`span`,yP,[U(`span`,bP,M(e.model),1),t[40]||=U(`span`,{class:`ccsw-dlg__dot`},`·`,-1),U(`span`,xP,M(e.baseUrl),1)])])],10,pP))),128))])],2112))])]),U(`div`,SP,[U(`span`,CP,M(a.ccSwitchDupCount>0?`已有 ${a.ccSwitchDupCount} 个重复模型被自动跳过`:`勾选要导入的供应商,批量加入模型库`),1),U(`div`,wP,[U(`button`,{class:`ni-btn ni-btn--ghost`,type:`button`,onClick:t[17]||=e=>i.ccSwitchOpen=!1},`取消`),U(`button`,{class:`ni-btn`,type:`button`,disabled:i.ccSwitchLoading||!i.ccSwitchProviders.length||a.ccSwitchCheckedCount===0,onClick:t[18]||=(...e)=>a.confirmImportCcSwitch&&a.confirmImportCcSwitch(...e)},M(a.ccSwitchCheckedCount>0?`导入选中 ${a.ccSwitchCheckedCount} 项`:`导入`),9,TP)])])])])):K(`v-if`,!0)]),_:1}),K(` 通用设置:所有模型共享的执行策略 / 环境参数 `),i.commonOpen?(B(),H(d,{key:5,onClose:t[20]||=e=>i.commonOpen=!1,onSaved:a.onCommonSaved},null,8,[`onSaved`])):K(`v-if`,!0),W(u,{visible:i.confirmClear,"close-on-mask":!1,title:`清空对话记录`,message:`将删除卡片「${n.cardName||n.cardId||`当前卡片`}」的全部对话记录,此操作不可撤销。`,"confirm-text":`清空`,severity:`danger`,onConfirm:a.doClear,onCancel:t[21]||=e=>i.confirmClear=!1},null,8,[`visible`,`message`,`onConfirm`]),K(` 终止确认:生成中按 Esc 会走到这里。几十分钟的建卡被一次误按抹掉代价太大,故加一道确认 `),W(u,{visible:i.confirmStop,"close-on-mask":!1,title:`终止本次生成`,message:`已执行的写入与落盘产物都会保留,上下文也留在对话里,之后回复「继续」可从中断处接着做。确定现在终止?`,"confirm-text":`终止生成`,severity:`danger`,onConfirm:a.doStop,onCancel:t[22]||=e=>i.confirmStop=!1},null,8,[`visible`,`onConfirm`])],38)}var DP=X(jN,[[`render`,EP],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatPanel.vue`]]),OP=`/assets/site-icon-CFMif8z4.png`,kP={includeMocks:!0},AP=2500,jP=new eu,MP=au({},jP);typeof window<`u`&&(window.__rt=MP);var NP=188,PP=320,FP=200,IP=160,LP={name:`App`,components:{RenderTree:ap,DebugPanel:wy,ApiCallPanel:By,CardSelect:ib,AlertCardLayer:mb,DeviceOverlay:Yb,PickerOverlay:ix,DatePickerOverlay:yx,SelectionOverlay:Cx,HoverGuides:kx,RemotePreview:_S,AppToast:TS,ImageLightbox:GS,ConfirmDialog:_p,CardGallery:fC,NewCardDialog:MC,ComponentPalette:qC,Switch:ZC,ChatPanel:DP},provide(){return{adapter:jP,cardRuntime:MP,customComponents:{}}},data(){return{adapter:jP,rt:MP,logoUrl:OP,appVersion:`0.32.0`,cardList:[],cardCount:0,galleryOpen:!1,cardDialog:{visible:!1,mode:`create`,cardId:``,cardDesc:``},selectedId:``,externalReloadNote:``,externalReloadTimer:null,selfSaveId:``,selfSaveAt:0,preview:null,chromeOff:!1,theme:`dark`,cardReady:!1,reloadToken:0,moveCollapseToken:0,refreshing:!1,loadingCard:!1,currentSchema:null,currentCard:null,cardImportMeta:null,localSchema:null,localData:null,selectedNodeId:``,activeTab:`vars`,apiPanelOpen:!0,addNodePanelOpen:!1,addNodeTarget:null,validateBadge:{state:`idle`,errors:0,warnings:0,renderOk:null,ts:0},validateTimer:null,copiedSchema:!1,copyTimer:null,savedCard:!1,savingCard:!1,saveTimer:null,savingRemote:!1,savedRemote:!1,verifiedRemote:null,saveRemoteTimer:null,syncingRemote:!1,syncedRemote:!1,remotePreviewOpen:!1,syncTarget:null,syncTimer:null,uploadingSlices:!1,loginModal:!1,loginName:``,loginPassword:``,loginSubmitting:!1,loginError:``,confirm:{show:!1,title:``,message:``,confirmText:`继续`,cancelText:`取消`,severity:`primary`,onConfirm:null},past:[],future:[],baseline:null,_commitTimer:null,viewportHeight:700,canvasBg:`gray`,refreshing:!1,bgOptions:[{key:`checker`,label:`棋盘`},{key:`white`,label:`白色`},{key:`gray`,label:`浅灰`},{key:`black`,label:`黑色`}],_previewWidthPx:372,_apiPanelWidthPx:360,presetSizes:[{key:375,value:`375`},{key:430,value:`430`},{key:188,value:`188`}],stageWidth:typeof window<`u`?window.innerWidth:1280,colsWidth:0,stageHeight:typeof window<`u`?window.innerHeight-52:748,dragging:!1,apiDragging:!1,armedLeft:!1,armedApi:!1,_armTimerLeft:null,_armTimerApi:null,_stageObserver:null,devServiceOpen:!1,aiChatOpen:(()=>{try{return sessionStorage.getItem(`cardbuddy:ai-chat-open`)===`1`}catch{return!1}})(),chatBusy:!1,chatProgress:null,devServiceForm:Nl(),apiBaseResolved:Fl(),devSvcLive:`unknown`,devSvcDown:!1,_unsubCardsChanged:null}},computed:{fabTitle(){if(this.aiChatOpen)return`AI 开发助手(已打开)`;if(!this.chatBusy)return`AI 开发助手`;let e=this.chatProgress,t=e&&e.startedAt?`${MD(e.startedAt)} 开始 · `:``;return`AI 开发助手正在生成(${e?`${t}第 ${e.steps} 步 · 已用 ${jD(e.ms)}${e.stage?` · ${e.stage}`:``}${e.stalled?` · 疑似断流`:``}`:``}),点击展开查看`},fabBadge(){return this.chatProgress&&this.chatProgress.stalled?`!`:String(this.chatProgress&&this.chatProgress.steps||0)},currentBg(){return this.bgOptions.find(e=>e.key===this.canvasBg)||this.bgOptions[0]},cardIds(){return this.cardList.map(e=>e&&e.id).filter(Boolean)},canUndo(){return this.past.length>0},canRedo(){return this.future.length>0},devSvcBlockReason(){let e=this.devServiceForm||{};return String(e.baseUrl||``).trim()?e.enabled?null:`disabled`:`empty`},canPaste(){return!!Hu()},hasCardSource(){return!!(this.cardImportMeta&&this.cardImportMeta.source)},historyDirty(){return!this.localSchema||!this.currentSchema?!1:!this.structuralEqual(this.currentSchema,this.localSchema)||!this.dataEqual(this.rt&&this.rt.rootScope,this.localData)},devSvcConn(){return this.apiBaseResolved===null?`unconfigured`:this.devSvcLive===`open`?`open`:this.devSvcDown?`closed`:`connecting`},devSvcTitle(){if(this.apiBaseResolved===null)return this.devSvcBlockReason===`disabled`?`已填地址但未开启用本地服务`:`未配置本地开发服务(部署态必填)`;let e=this.apiBaseResolved===``?`同源开发服务`:`本地开发服务`;return this.devSvcLive===`open`?e+`已连接`:this.devSvcDown?e+`已断开(连接失败或服务已停止,重连中…)`:e+`连接中 / 重连中…`},devSvcClass(){return this.apiBaseResolved===null?`app__btn--warn`:this.devSvcLive===`open`?`app__btn--connected`:this.devSvcDown?`app__btn--disconnected`:`app__btn--reconnecting`},devSvcLabel(){return this.apiBaseResolved===null?`未配置本地服务`:this.devSvcLive===`open`?`本地服务已连接`:this.devSvcDown?`本地服务已断开`:`本地服务连接中…`},badgeText(){return{idle:`待校验`,pending:`校验中…`,ok:`校验通过`,error:`校验未通过`,nopython:`未配置校验`,fail:`校验服务异常`}[this.validateBadge.state]||`待校验`},badgeTitle(){let e=this.validateBadge;if(e.state===`ok`)return`结构合法 + 渲染不抛错(不保证画得对,视觉正确性见截图)`;if(e.state===`error`){let t=[];return e.errors&&t.push(`契约错误 ${e.errors} 个`),e.renderOk===!1&&t.push(`渲染抛出异常`),`校验未通过:`+(t.join(`;`)||`详见 /__validate 与 /__render-status`)}return e.state===`nopython`?`未找到 python3/python,无法跑契约校验(请安装 Python 或设置 DSL_PYTHON)`:e.state===`fail`?`校验服务异常(dev server 未启动或端点不可用)`:``},previewWidth(){if(this.chromeOff)return this.stageWidth;let{min:e,max:t}=this.previewBounds,n=this._previewWidthPx||NP;return Math.max(e,Math.min(t,n))},viewportWidth(){return this.stageWidth,typeof window<`u`?window.innerWidth:1280},debugSoftWidth(){return Math.max(FP,Math.floor(this.viewportWidth/3))},previewBounds(){let e=this.stageWidth||0,t=Math.floor(e/2),n=e-PP-this.debugSoftWidth;return{min:NP,max:Math.max(NP,Math.min(t,n))}},debugMinWidth(){let e=this.colsWidth||Math.max(0,(this.stageWidth||0)-this.previewWidth);return Math.max(FP,Math.min(this.debugSoftWidth,Math.floor(e)-PP))},apiPanelBounds(){let e=this.colsWidth||Math.max(0,(this.stageWidth||0)-this.previewWidth),t=Math.max(IP,Math.floor(e)-this.debugMinWidth);return{min:Math.min(PP,t),max:t}},canvasW(){return Math.round(this.previewWidth||375)},selectedCardName(){let e=this.cardList.find(e=>e.id===this.selectedId);return e&&e.name||this.selectedId||``},cardEmpty(){let e=this.currentSchema;if(!e||!e.view)return!0;let t=e.view.components;return!Array.isArray(t)||t.length===0},apiPanelWidth(){let{min:e,max:t}=this.apiPanelBounds,n=this._apiPanelWidthPx||360;return Math.max(e,Math.min(t,n))},frameStyle(){return{}}},watch:{activeTab(e){e!==`structure`&&(this.selectedNodeId=``,Ex())},aiChatOpen(e){try{sessionStorage.setItem(`cardbuddy:ai-chat-open`,e?`1`:`0`)}catch{}},theme(e){document.documentElement.dataset.theme=e},apiPanelOpen(e){try{localStorage.setItem(`cardbuddy:api-panel-open`,e?`1`:`0`)}catch{}}},beforeUnmount(){this.viewportObserver&&this.viewportObserver.disconnect(),this._stageObserver&&this._stageObserver.disconnect(),this.saveTimer&&clearTimeout(this.saveTimer),this.syncTimer&&clearTimeout(this.syncTimer),this.saveRemoteTimer&&clearTimeout(this.saveRemoteTimer),window.removeEventListener(`keydown`,this.onKeydown)},mounted(){this.viewportObserver=new ResizeObserver(e=>{for(let t of e)this.viewportHeight=Math.round(t.contentRect.height)}),this.$refs.phoneViewport&&this.viewportObserver.observe(this.$refs.phoneViewport),this.loadPreviewWidth(),this.loadApiPanelWidth(),this._stageObserver=new ResizeObserver(e=>{for(let t of e){if(t.target===this.$refs.colsEl){this.colsWidth=Math.round(t.contentRect.width);continue}this.stageWidth=Math.round(t.contentRect.width),this.stageHeight=Math.round(t.contentRect.height)}}),this.$refs.stageEl&&this._stageObserver.observe(this.$refs.stageEl),this.$refs.colsEl&&this._stageObserver.observe(this.$refs.colsEl),window.addEventListener(`keydown`,this.onKeydown)},async created(){Ib(MP);let e=new URLSearchParams(location.search).get(`chrome`);this.chromeOff=e===`off`||e===``;try{let e=localStorage.getItem(`cardbuddy:theme`);(e===`light`||e===`dark`)&&(this.theme=e)}catch{}document.documentElement.dataset.theme=this.theme;try{localStorage.getItem(`cardbuddy:api-panel-open`)===`0`&&(this.apiPanelOpen=!1)}catch{}await this.fetchCardList();let t=new URLSearchParams(location.search).get(`card`),n=null;try{let e=localStorage.getItem(`cardbuddy:selected-card`);e&&this.cardList.some(t=>t.id===e)&&(n=e)}catch{}let r=t&&this.cardList.some(e=>e.id===t)?t:n||this.cardList[0]&&this.cardList[0].id;r&&(this.selectedId=r,await this.loadCard(this.selectedId)),this.$watch(()=>this.rt.rootScope,()=>{this.syncDataToSchema()},{deep:!0}),this.setupCardsChanged()},methods:{setupCardsChanged(){if(this._unsubCardsChanged){try{this._unsubCardsChanged()}catch{}this._unsubCardsChanged=null}this.devSvcLive=`connecting`,this._unsubCardsChanged=Vl(e=>this.onCardsChanged(e),e=>this.onDevServiceState(e))},onDevServiceState(e){let t=this.devSvcLive===`connecting`;this.devSvcLive=e,e===`open`?this.devSvcDown=!1:e===`closed`&&(this.devSvcDown=!0),e===`connecting`?!t&&!this._svcWatchdog&&(this._svcWatchdog=setTimeout(()=>{this.devSvcLive===`connecting`&&(this.devSvcLive=`closed`,this.devSvcDown=!0),this._svcWatchdog=null},8e3)):this._svcWatchdog&&=(clearTimeout(this._svcWatchdog),null)},saveDevService(){Pl(this.devServiceForm),this.apiBaseResolved=Fl(),this.setupCardsChanged(),this.devServiceOpen=!1,Z(`本地开发服务配置已保存`,`ok`),this.fetchCardList()},beginColumnDrag(e,t,n){let r=e&&e.currentTarget;if(!r)return;let i=e.pointerId;try{r.setPointerCapture(i)}catch{}let a=()=>{r.removeEventListener(`pointermove`,t),r.removeEventListener(`pointerup`,a),r.removeEventListener(`pointercancel`,a),window.removeEventListener(`blur`,a);try{r.hasPointerCapture?.(i)&&r.releasePointerCapture(i)}catch{}document.body.style.cursor=``,document.body.style.userSelect=``,n()};document.body.style.cursor=`col-resize`,document.body.style.userSelect=`none`,r.addEventListener(`pointermove`,t),r.addEventListener(`pointerup`,a),r.addEventListener(`pointercancel`,a),window.addEventListener(`blur`,a)},armSplitter(e){let t=e===`api`?`_armTimerApi`:`_armTimerLeft`;clearTimeout(this[t]),this[t]=setTimeout(()=>{e===`api`?this.armedApi=!0:this.armedLeft=!0},600)},disarmSplitter(e){let t=e===`api`?`_armTimerApi`:`_armTimerLeft`;if(clearTimeout(this[t]),this[t]=null,e===`api`){if(this.apiDragging)return;this.armedApi=!1}else{if(this.dragging)return;this.armedLeft=!1}},startDrag(e){if(this.chromeOff||!this.armedLeft)return;let t=this.$refs.stageEl;if(!t)return;let n=t.getBoundingClientRect().left;this.dragging=!0,this.beginColumnDrag(e,e=>{let{min:t,max:r}=this.previewBounds;this._previewWidthPx=Math.max(t,Math.min(r,Math.round(e.clientX-n)))},()=>{this.dragging=!1,this.savePreviewWidth()})},startApiDrag(e){if(this.chromeOff||!this.apiPanelOpen||!this.armedApi)return;let t=this.$refs.colsEl;if(!t)return;let n=t.getBoundingClientRect().right;this.apiDragging=!0,this.beginColumnDrag(e,e=>{let{min:t,max:r}=this.apiPanelBounds;this._apiPanelWidthPx=Math.max(t,Math.min(r,Math.round(n-e.clientX)))},()=>{this.apiDragging=!1,this.saveApiPanelWidth()})},loadPreviewWidth(){try{let e=localStorage.getItem(`cardbuddy:preview-width`);if(e!=null){let t=parseInt(e,10);!Number.isNaN(t)&&t>=188&&(this._previewWidthPx=t)}}catch{}},savePreviewWidth(){try{localStorage.setItem(`cardbuddy:preview-width`,String(Math.round(this._previewWidthPx)))}catch{}},setPresetWidth(e){if(this.chromeOff)return;let{min:t,max:n}=this.previewBounds;this._previewWidthPx=Math.max(t,Math.min(n,e)),this.savePreviewWidth()},loadApiPanelWidth(){try{let e=localStorage.getItem(`cardbuddy:api-panel-width`);if(e!=null){let t=parseInt(e,10);!Number.isNaN(t)&&t>=320&&(this._apiPanelWidthPx=t)}}catch{}},saveApiPanelWidth(){try{localStorage.setItem(`cardbuddy:api-panel-width`,String(Math.round(this.apiPanelWidth)))}catch{}},chooseBg(e){this.canvasBg=e},onSelect(e){this.loadingCard=!0,this.selectedId=e,this.loadCard(e,{clearAll:!0})},selectCard(e){this.selectedId=e;try{localStorage.setItem(`cardbuddy:selected-card`,e)}catch{}},openGallery(){this.cardList.length&&(this.galleryOpen=!0)},openNewCard(){this.cardDialog.mode=`create`,this.cardDialog.cardId=``,this.cardDialog.cardDesc=``,this.cardDialog.visible=!0,this.fetchCardList()},openRenameCard(){this.selectedId&&(this.cardDialog.mode=`rename`,this.cardDialog.cardId=this.selectedId,this.cardDialog.cardDesc=this.currentSchema&&this.currentSchema.desc||``,this.cardDialog.visible=!0,this.fetchCardList())},async onCardRenamed({oldId:e,id:t}){if(this.cardDialog.visible=!1,Z(t===e?`已更新卡片描述`:`已重命名卡片 ${e} → ${t}`,`ok`),t!==e)return this.applyCardRename(e,t);await this.fetchCardList(),await this.loadCard(t)},async applyCardRename(e,t){if(!e||!t||e===t)return;let n=`${e}->${t}`;if(this._renameAppliedKey===n)return;this._renameAppliedKey=n,setTimeout(()=>{this._renameAppliedKey===n&&(this._renameAppliedKey=``)},1e3);let r=this.selectedId===e;if(this.$refs.chatPanel?.migrateCard(e,t),r&&this.selectCard(t),this.selfSaveId=t,this.selfSaveAt=Date.now(),await this.fetchCardList(),r){if(this.historyDirty&&!this.confirm.show){this.requestConfirm({title:`卡片已重命名`,message:`卡片「${e}」已重命名为「${t}」,而编辑器内还有未保存的改动。\n重新载入会放弃这些未保存改动并显示磁盘版本;保留改动则继续用当前编辑器内容(后续保存会写到新目录 ${t})。`,confirmText:`重新载入`,cancelText:`保留我的改动`,onConfirm:()=>this.loadCard(t)});return}await this.loadCard(t)}},closeGallery(){this.galleryOpen=!1},async openCardFolder(){if(this.selectedId)try{let e=await J(`/__open-folder`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:this.selectedId})}),t=(e.headers.get(`content-type`)||``).includes(`application/json`)?await e.json().catch(()=>({})):{};!e.ok||!t.ok?Z(t.error||`打开文件夹失败`,`err`):Z(`已打开卡片文件夹`,`ok`)}catch{Z(`无法连接本地开发服务,请确认已启动`,`err`)}},async refreshCard(){if(!(!this.selectedId||this.refreshing)){this.refreshing=!0;try{await this.loadCard(this.selectedId)}finally{this.refreshing=!1}}},toggleTheme(){this.theme=this.theme===`light`?`dark`:`light`;try{localStorage.setItem(`cardbuddy:theme`,this.theme)}catch{}},toggleApiPanel(){this.apiPanelOpen=!this.apiPanelOpen},async refreshValidateBadge(){let e=this.selectedId;if(!(!e||!this.preview)&&(this.validateTimer&&clearTimeout(this.validateTimer),this.validateBadge={...this.validateBadge,state:`pending`},await new Promise(e=>{this.validateTimer=setTimeout(e,120)}),this.selectedId===e))try{let[t,n]=await Promise.all([J(`/__validate/${encodeURIComponent(e)}`),J(`/__render-status/${encodeURIComponent(e)}`)]);if(!t.ok){this.validateBadge={...this.validateBadge,state:t.status===503?`nopython`:`fail`};return}let r=await t.json().catch(()=>null),i=n.ok?await n.json().catch(()=>null):null;if(!r){this.validateBadge={...this.validateBadge,state:`fail`};return}let a=!!r.ok,o=!i||!!i.renderOk,s=a&&o?`ok`:`error`,c=this.validateBadge.state!==s;this.validateBadge={state:s,errors:(r.errors||[]).length,warnings:(r.warnings||[]).length,renderOk:o,ts:Date.now()},c&&(s===`ok`||s===`error`)&&this.celebrateValidate(s)}catch{this.validateBadge={...this.validateBadge,state:`fail`}}},celebrateValidate(e=`ok`){let t=this.$refs.validateBadgeEl;if(!t||window.matchMedia&&window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)return;t.classList.remove(`is-celebrating`),t.offsetWidth,t.classList.add(`is-celebrating`),setTimeout(()=>t.classList.remove(`is-celebrating`),600);let n=t.getBoundingClientRect(),r={ok:`--ok`,error:`--danger`,pending:`--warn`,fail:`--text-faint`,nopython:`--text-faint`}[e]||`--ok`,i={ok:`#52c41a`,error:`#F5222D`,pending:`#FAAD14`,fail:`#8c8c8c`,nopython:`#8c8c8c`}[e]||`#52c41a`,a=getComputedStyle(t).getPropertyValue(r).trim()||i,o=document.createElement(`div`);o.className=`app__confetti`,o.style.left=n.left+n.width/2+`px`,o.style.top=n.top+n.height/2+`px`;let s=[`polygon(50% 0%, 0% 100%, 100% 100%)`,`polygon(62% 0%, 100% 40%, 45% 100%, 0% 52%)`,`polygon(0% 0%, 100% 18%, 82% 100%, 12% 70%)`,`polygon(22% 0%, 100% 8%, 88% 100%, 0% 76%)`,`polygon(0% 32%, 100% 0%, 76% 100%, 18% 86%)`,`polygon(8% 0%, 100% 22%, 70% 100%, 0% 64%)`,`polygon(0% 12%, 100% 0%, 100% 78%, 30% 100%, 12% 55%)`],c=n.width/2,l=n.height/2;for(let e=0;e<22;e++){let e=document.createElement(`span`);e.className=`app__confetti-bit`;let t=Math.random()*4|0,n,r;t===0?(n=(Math.random()*2-1)*c,r=-l):t===1?(n=c,r=(Math.random()*2-1)*l):t===2?(n=(Math.random()*2-1)*c,r=l):(n=-c,r=(Math.random()*2-1)*l);let i=Math.hypot(n,r)||1,u=Math.atan2(r/i,n/i)+(Math.random()-.5)*.5,d=16+Math.random()*26;e.style.setProperty(`--sx`,n.toFixed(1)+`px`),e.style.setProperty(`--sy`,r.toFixed(1)+`px`),e.style.setProperty(`--tx`,(Math.cos(u)*d).toFixed(1)+`px`),e.style.setProperty(`--ty`,(Math.sin(u)*d).toFixed(1)+`px`),e.style.setProperty(`--rot`,(Math.random()*720-360).toFixed(0)+`deg`),e.style.setProperty(`--clip`,s[Math.random()*s.length|0]),e.style.setProperty(`--c`,a),e.style.setProperty(`--o`,(.68+Math.random()*.27).toFixed(2));let f=Math.random(),p,m;f<.35?(p=1.5+Math.random()*2,m=10+Math.random()*10):f<.75?(p=4+Math.random()*5,m=p*(.6+Math.random()*.8)):(p=2+Math.random()*2.5,m=p),e.style.width=p.toFixed(0)+`px`,e.style.height=m.toFixed(0)+`px`,o.appendChild(e)}document.body.appendChild(o),setTimeout(()=>o.remove(),800)},async loadCard(e,t={}){if(e){this.loadingCard=!0;try{let n=await J(`/__card/${encodeURIComponent(e)}`);if(!n.ok){this.rt.pushError(`loadCard`,`HTTP `+n.status);return}let r=await n.json();if(!r.schema){this.rt.pushError(`loadCard`,`schema 读取失败`);return}this.selectCard(e),t.clearAll?this.rt.clearErrors():this.rt.clearBindingErrors(),this.rt.clearApiCalls(),t.keepScope||this.rt.setRootScope(Xg(r.schema,kP)),this.currentCard={schema:r.schema},this.currentSchema=r.schema,this.cardImportMeta=null,this.fetchImportMeta(e),this.localSchema=this.cloneSchema(r.schema),this.localData=this.cloneData(Xg(r.schema,kP)),this.preview=Pu(r.schema),typeof window<`u`&&(window.__cardModel=Bu(r.schema)),this.cardReady=!1,this.$nextTick(()=>{this.cardReady=!0}),this.syncDataToSchema(),this.selectedNodeId=``,this.baseline={schema:this.cloneSchema(this.currentSchema)},this.reloadToken+=1,ub(),Lb(),this.refreshValidateBadge(),await this.loadHistory(e)}finally{this.loadingCard=!1}}},cloneSchema(e){return e?JSON.parse(JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t)):null},normalizeForCompare(e){let t=this.cloneSchema(e);if(t&&t.dictionary&&Array.isArray(t.dictionary.inputParams))for(let e of t.dictionary.inputParams)e&&typeof e==`object`&&(e.defaultValue=void 0);return t},structuralEqual(e,t){return!e||!t?e===t:JSON.stringify(this.normalizeForCompare(e))===JSON.stringify(this.normalizeForCompare(t))},cloneData(e){return e==null?e:JSON.parse(JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t))},dataEqual(e,t){return JSON.stringify(e)===JSON.stringify(t)},applySchemaSnapshot(e){if(!this.selectedId||!e)return;let t=e.schema||e,n=e.data==null?Xg(t,kP):e.data;this.currentSchema=this.cloneSchema(t),this.rt.setRootScope(this.cloneData(n)),this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``,this.reloadToken+=1,this.refreshValidateBadge()},commitHistory(){if(!this.currentSchema||!this.baseline)return;let e=this.structuralEqual(this.currentSchema,this.baseline.schema),t=this.dataEqual(this.rt.rootScope,Xg(this.baseline.schema,kP));if(e&&t)return;let n={schema:this.baseline.schema};this.past.push(n),this.past.length>30&&this.past.shift(),this.future=[],this.baseline={schema:this.cloneSchema(this.currentSchema)},this.persistSnapshot(n)},scheduleCommit(){this._commitTimer&&clearTimeout(this._commitTimer),this._commitTimer=setTimeout(()=>{this._commitTimer=null,this.commitHistory()},500)},persistSnapshot(e){let t=this.selectedId;if(!t)return;let n=e.schema||e;J(`/__history/${encodeURIComponent(t)}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({schema:n},(e,t)=>e===`_schemaNode`?void 0:t,2)}).catch(e=>console.warn(`[历史快照落盘失败]`,e))},async loadHistory(e){this.past=[],this.future=[];try{let t=await J(`/__history/${encodeURIComponent(e)}`);if(!t.ok)return;let n=await t.json().catch(()=>null),r=n&&n.snapshots||[];this.past=r.slice(-30).map(e=>({schema:e.schema,data:e.data==null?Xg(e.schema,kP):e.data}))}catch(e){console.warn(`[加载编辑历史失败]`,e)}},undo(){if(!this.canUndo)return;let e=this.past.pop();this.future.push(this.baseline),this.future.length>30&&this.future.shift(),this.baseline=e,this.applySchemaSnapshot(e)},redo(){if(!this.canRedo)return;let e=this.future.pop();this.past.push(this.baseline),this.past.length>30&&this.past.shift(),this.baseline=e,this.applySchemaSnapshot(e)},async applyHistoryToLocal(){this.loadingCard||!this.historyDirty||!this.preview||!this.selectedId||await this.saveCard()&&Z(`已将该版本保存到本地`,`ok`)},onSchemaChanged(){!this.selectedId||!this.currentSchema||(this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``)},onSchemaCommit(){!this.selectedId||!this.currentSchema||(this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``,this.commitHistory())},syncDataToSchema(){let e=this.currentSchema;if(!e||!e.dictionary||!Array.isArray(e.dictionary.inputParams))return;let t=this.rt&&this.rt.rootScope;if(!t||typeof t!=`object`)return;let n=e.dictionary.inputParams,r=Zg(e);for(let e of Object.keys(t)){let i=n.find(t=>t&&(t.key===e||t.name===e));if(!i)continue;let a=JSON.parse(JSON.stringify(t[e],(e,t)=>e===`_schemaNode`?void 0:t));r&&Object.prototype.hasOwnProperty.call(r,e)?r[e]=a:i.defaultValue=a}},onSelectNode(e){this.selectedNodeId=e||``},findPreviewNodeById(e,t){if(!e||t==null)return null;let n=String(t),r=e=>{if(!e)return null;if(String(e.id)===n)return e;let t=[];if(e.components&&t.push(...e.components),e.slots)for(let n of e.slots)n.components&&t.push(...n.components);for(let e of t){let t=r(e);if(t)return t}return null};return r(e)},copySelectedNode(){let e=this.selectedNodeId;if(!e||e===`_root`||!this.currentSchema||!this.preview)return;let t=this.findPreviewNodeById(this.preview.view,e);if(!t)return;let n=this.findSchemaNodeByComponentId(this.currentSchema.view,t.componentId);n&&(Wu(n.node,this.selectedId),Z(`已复制节点(含子节点)`,`ok`))},pasteNode(){let e=Hu();if(!e||!this.currentSchema)return;let t=Gu(e),n=[...new Set(t.filter(e=>!vu[e]))];if(n.length){Z(`粘贴失败:含未知组件类型 `+n.join(`、`),`err`);return}let r=JSON.parse(JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t));Ku(r);let i=this.selectedNodeId&&this.selectedNodeId!==`_root`?this.findPreviewNodeById(this.preview.view,this.selectedNodeId):null,a=`root`;i&&(a=ju(i.className)?`into`:`after`),this.insertClone(r,i,a);let o=Uu();o&&o!==this.selectedId?Z(`已从卡片「${o}」跨卡片粘贴到「${this.selectedId}」`,`ok`):Z(`已粘贴节点(含子节点)`,`ok`)},duplicateNode(){let e=this.selectedNodeId;if(!e||e===`_root`||!this.currentSchema||!this.preview)return;let t=this.findPreviewNodeById(this.preview.view,e);if(!t)return;let n=this.findSchemaNodeByComponentId(this.currentSchema.view,t.componentId);if(!n)return;let r=JSON.parse(JSON.stringify(n.node,(e,t)=>e===`_schemaNode`?void 0:t));Ku(r),n.parentArr.splice(n.index+1,0,r),this.afterStructuralEdit(r.componentId)},insertClone(e,t,n){let r=this.currentSchema;if(n===`root`)r.view.components||(r.view.components=[]),r.view.components.push(e);else if(n===`into`){let n=t&&t._schemaNode;if(!n){r.view.components||(r.view.components=[]),r.view.components.push(e),this.afterStructuralEdit(e.componentId);return}let i=Mu(t.className),a=(n.slots||[]).find(e=>e.slotKey===i);a||(n.slots||=[],a={slotKey:i,slotScope:!1,slotSwitch:`1`,components:[]},n.slots.push(a)),a.components||(a.components=[]),a.components.push(e)}else{let n=this.findSchemaNodeByComponentId(r.view,t.componentId);n?n.parentArr.splice(n.index+1,0,e):(r.view.components||(r.view.components=[]),r.view.components.push(e))}this.afterStructuralEdit(e.componentId)},afterStructuralEdit(e){let t=this.currentSchema;this.reloadToken+=1,this.preview=Pu(t),typeof window<`u`&&(window.__cardModel=Bu(t)),this.syncDataToSchema(),this.selectedNodeId=e&&this.findViewIdByComponentId(this.preview.view,e)||``,this.scheduleCommit()},deleteSelectedNode(){let e=this.selectedNodeId;if(!e||e===`_root`||!this.currentSchema||!this.preview)return;let t=this.findPreviewNodeById(this.preview.view,e);if(!t)return;let n=this.findSchemaNodeByComponentId(this.currentSchema.view,t.componentId);n&&(n.parentArr.splice(n.index,1),this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``,Ex(),this.scheduleCommit())},hasTextSelection(){if(typeof window>`u`||!window.getSelection)return!1;let e=window.getSelection();return!!e&&!e.isCollapsed&&e.toString().trim()!==``},hasNodeSelection(){return!!this.selectedNodeId&&this.selectedNodeId!==`_root`},isEditableTarget(e){let t=e.target;if(!t)return!1;let n=t.tagName;return!!(n===`INPUT`||n===`TEXTAREA`||n===`SELECT`||t.isContentEditable)},onKeydown(e){if(this.chromeOff||!this.preview)return;let t=this.isEditableTarget(e),n=e.ctrlKey||e.metaKey,r=e.key;if(n&&(r===`c`||r===`C`)){if(t||this.hasTextSelection()||!this.hasNodeSelection())return;this.copySelectedNode(),e.preventDefault();return}if(n&&(r===`v`||r===`V`)){if(t||this.hasTextSelection()||!this.hasNodeSelection()||!Hu())return;this.pasteNode(),e.preventDefault();return}if(n&&(r===`d`||r===`D`)){if(t||this.hasTextSelection()||!this.hasNodeSelection())return;this.duplicateNode(),e.preventDefault();return}if(n&&(r===`z`||r===`Z`)){if(t)return;e.preventDefault(),e.shiftKey?this.redo():this.undo();return}if(n&&(r===`y`||r===`Y`)){if(t)return;e.preventDefault(),this.redo();return}if(r===`Delete`||r===`Backspace`){if(t||!this.selectedNodeId||this.selectedNodeId===`_root`)return;e.preventDefault(),this.deleteSelectedNode();return}if(r===`Escape`){this.selectedNodeId&&(this.selectedNodeId=``,e.preventDefault());return}},onHoverNode(e){if(!e){Ex();return}if(e.leave){Ex(e.id);return}let t=typeof document<`u`?document.querySelector(`.phone__screen`):null;if(!t){Ex(e.id);return}let n=e=>window.CSS&&CSS.escape?CSS.escape(String(e)):String(e).replace(/["\\\]]/g,`\\$&`),r=null;e.componentId!=null&&(r=t.querySelector(`[data-cid="`+n(e.componentId)+`"]`)),!r&&e.id!=null&&(r=t.querySelector(`[data-cid="`+n(e.id)+`"]`)),r?Tx(r,e.id):Ex(e.id)},onCanvasClick(e){if(!e.ctrlKey&&!e.metaKey||this.chromeOff)return;let t=e.target&&e.target.closest?e.target.closest(`[data-cid]`):null;if(!t)return;let n=t.getAttribute(`data-cid`);if(!n)return;let r=this.findPreviewNodeByCid(n);r&&(this.activeTab=`structure`,this.selectedNodeId=r.id)},onAiLocateNode(e){let t=e?this.findPreviewNodeByCid(e):null;if(!t){Z(`没找到组件 ${e||``}:卡片可能已被改动,重新校验一次即可`,`err`);return}this.activeTab=`structure`,this.selectedNodeId=t.id},findPreviewNodeByCid(e){let t=this.preview&&this.preview.view;if(!t)return null;let n=String(e),r=e=>{if(!e)return null;if(String(e.componentId==null?e.id:e.componentId)===n)return e;let t=[];if(e.components&&t.push(...e.components),e.slots)for(let n of e.slots)n.components&&t.push(...n.components);for(let e of t){let t=r(e);if(t)return t}return null};return r(t)},onAddNode(e){this.currentSchema&&(this.addNodeTarget=e||null,this.addNodePanelOpen=!0)},cancelAddNode(){this.addNodePanelOpen=!1,this.addNodeTarget=null},findSchemaLocation(e,t){let n=e=>{for(let r=0;r<e.length;r++){let i=e[r];if(i===t)return{containerArr:e,index:r};let a=i.slots||[];for(let e of a){let t=n(e.components||[]);if(t)return t}}return null};return n(e&&e.components||[])},findViewIdByComponentId(e,t){if(!e)return null;if(e.componentId===t)return e.id;let n=[];if(e.components&&n.push(...e.components),e.slots)for(let t of e.slots)t.components&&n.push(...t.components);for(let e of n){let n=this.findViewIdByComponentId(e,t);if(n)return n}return null},findSchemaNodeByComponentId(e,t){let n=(e,r)=>{for(let i=0;i<e.length;i++){let a=e[i];if(a.componentId===t)return{node:a,parentArr:e,index:i,owner:r};let o=a.slots||[];for(let e of o){let t=n(e.components||[],a);if(t)return t}}return null};return n(e&&e.components||[],`root`)},isDescendantCompId(e,t){if(!t||!t.componentId)return!1;if(t.componentId===e)return!0;let n=[];if(t.components&&n.push(...t.components),t.slots)for(let e of t.slots)e.components&&n.push(...e.components);for(let t of n)if(this.isDescendantCompId(e,t))return!0;return!1},moveNode(e,t,n){let r=this.currentSchema;if(!r||!r.view||e===t)return!1;let i=this.findSchemaNodeByComponentId(r.view,e);if(!i)return!1;let a=i.node;if(this.isDescendantCompId(t,a))return!1;let o,s;if(t===`__root__`)r.view.components||(r.view.components=[]),o=r.view.components,s=o.length;else{let e=this.findSchemaNodeByComponentId(r.view,t);if(!e)return!1;let i=e.node;if(n===`inside`){if(!ju(i.className))return!1;let e=Mu(i.className),t=(i.slots||[]).find(t=>t.slotKey===e);t||(i.slots||=[],t={slotKey:e,slotScope:!1,slotSwitch:`1`,components:[]},i.slots.push(t)),t.components||(t.components=[]),o=t.components,s=o.length}else o=e.parentArr,s=n===`before`?e.index:e.index+1}let c=o===i.parentArr&&i.index<s;return i.parentArr.splice(i.index,1),c&&--s,o.splice(s,0,a),a},onMoveNode({sourceCompId:e,targetCompId:t,position:n}){if(!this.currentSchema||!this.moveNode(e,t,n))return;this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema();let r=this.findViewIdByComponentId(this.preview.view,e);this.selectedNodeId=r||``,r&&(this.moveCollapseToken+=1)},onPickComponent(e){let t=this.addNodeTarget||{},n=t.node||null,r=t.mode||`auto`,i=this.currentSchema;if(!i){this.cancelAddNode();return}let a;try{a=Nu(e)}catch(e){console.error(`[创建组件节点失败]`,e),this.rt.pushError(`addNode`,String(e&&e.message)),this.cancelAddNode();return}let o=!n||n.className===`Root`;if((r===`before`||r===`after`)&&!o){let e=n._schemaNode,t=e?this.findSchemaLocation(i.view,e):null;if(!t)i.view.components||(i.view.components=[]),i.view.components.push(a);else{let e=r===`before`?t.index:t.index+1;t.containerArr.splice(e,0,a)}}else if(o)i.view.components||(i.view.components=[]),i.view.components.push(a);else{let e=n._schemaNode;if(!e){this.cancelAddNode();return}if(ju(n.className)){let t=Mu(n.className),r=(e.slots||[]).find(e=>e.slotKey===t);r||(e.slots||=[],r={slotKey:t,slotScope:!1,slotSwitch:`1`,components:[]},e.slots.push(r)),r.components||(r.components=[]),r.components.push(a)}else{let t=this.findSchemaLocation(i.view,e);t?t.containerArr.splice(t.index+1,0,a):(i.view.components||(i.view.components=[]),i.view.components.push(a))}}this.cancelAddNode(),this.reloadToken+=1,this.preview=Pu(i),typeof window<`u`&&(window.__cardModel=Bu(i)),this.syncDataToSchema();let s=this.findViewIdByComponentId(this.preview.view,a.componentId);this.selectedNodeId=s||``,this.scheduleCommit()},async copySchema(){if(!this.currentSchema)return;this.syncDataToSchema();let e=``;try{let t={...this.currentSchema};this.rt&&this.rt.rootScope&&(t.data=this.rt.rootScope),e=JSON.stringify(t,(e,t)=>{if(e!==`_schemaNode`)return t},2)}catch{e=`(无法序列化)`}await this.doCopy(e)&&(this.copiedSchema=!0,this.copyTimer&&clearTimeout(this.copyTimer),this.copyTimer=setTimeout(()=>{this.copiedSchema=!1},1500))},async doCopy(e){try{if(navigator.clipboard&&navigator.clipboard.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}},async runSync(e){if(!this.syncingRemote&&!(e&&!this.selectedId)){this.syncingRemote=!0,this.syncedRemote=!1,this.syncTarget=e?`selected`:`full`;try{let t=await J(`/__sync`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e?{cardCode:e}:{})});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.message||e.error||`HTTP `+t.status)}let n=await t.json();if(n.needCredentials){this.openLoginModal();return}if(!n.success){let e=(n.failed||[]).map(e=>`${e.id}: ${e.error}`).join(`; `);throw Error(e||`同步失败`)}this.syncedRemote=!0,this.syncTimer&&clearTimeout(this.syncTimer),this.syncTimer=setTimeout(()=>{this.syncedRemote=!1,this.syncTarget=null},1800),await this.onRefresh(),Z(this.syncTarget===`selected`?`已同步当前卡片到本地`:`全量同步完成`,`ok`)}catch(e){console.error(`[同步远程数据失败]`,e),Z(`同步失败:`+(e&&e.message),`err`)}finally{this.syncingRemote=!1}}},syncRemote(){return this.runSync()},syncSelected(){return this.runSync(this.selectedId)},openLoginModal(){this.loginModal=!0,this.loginName=``,this.loginPassword=``,this.loginError=``},closeLoginModal(){this.loginSubmitting||(this.loginModal=!1,this.loginPassword=``,this.loginError=``)},async submitLogin(){if(this.loginSubmitting)return;let e=this.loginName.trim(),t=this.loginPassword;if(!e||!t){this.loginError=`账号与密码均不能为空`;return}this.loginSubmitting=!0,this.loginError=``;try{let n=await J(`/__login-credentials`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({loginName:e,loginPassword:t})}),r=await n.json().catch(()=>({}));if(!n.ok||!r.ok)throw Error(r.message||r.error||`HTTP `+n.status);this.loginModal=!1,this.loginPassword=``,Z(`凭据已保存,正在重试同步…`,`ok`),await this.runSync(this.syncTarget===`selected`?this.selectedId:void 0)}catch(e){this.loginError=`保存失败:`+(e&&e.message)}finally{this.loginSubmitting=!1}},chooseSync(e){if(e===`full`){if(this.syncingRemote)return;this.requestConfirm({title:`全量同步`,message:`即将从远端 FinMall 拉取完整卡片列表,并逐张覆盖本地同名卡片。本地独有卡片会保留,但被覆盖卡片的未保存改动将丢失,且无法撤销。是否继续?`,confirmText:`继续同步`,severity:`warn`,onConfirm:()=>this.syncRemote()});return}!this.preview||!this.selectedId||this.syncingRemote||this.requestConfirm({title:`当前同步`,message:`即将从远端 FinMall 拉取当前卡片「${this.selectedId}」的最新版本并覆盖本地。本地未保存的改动将丢失,且无法撤销。是否继续?`,confirmText:`继续同步`,onConfirm:()=>this.syncSelected()})},chooseRsave(e){if(e===`save`){if(!this.preview||!this.selectedId||this.savingRemote||!this.hasCardSource)return;this.requestConfirm({title:`版本推送`,message:`即将把本地卡片「${this.selectedId}」的当前版本推送并覆盖到远端 FinMall。线上版本会被立即更新,且该操作不可撤销。是否继续?`,confirmText:`继续推送`,severity:`warn`,onConfirm:()=>this.saveToRemote()});return}if(e===`slices`){if(!this.preview||!this.selectedId||this.uploadingSlices)return;this.requestConfirm({title:`切图上传`,message:`即将把当前卡片「${this.selectedId}」引用的本地切图(src/slices/)上传到 FinMall 图片库,并把卡片里的 /slices/ 引用替换为线上地址(@filestore/…)。本地切图文件保留不动;内容未变的切图会直接复用已有线上地址,不重复上传。`+(this.historyDirty?`
|
|
280
|
+
`)}`}return{role:`user`,content:n}}let t=(e.toolCalls||[]).filter(e=>e.result!==void 0||e.error).map(e=>({toolCallId:e.toolCallId,toolName:e.toolName,args:e.args||{},result:typeof e.result==`string`?e.result.slice(0,vN):e.result,error:e.error||``})),n=e.content||``;return e.status===`aborted`&&(n=n?`${n}\n\n[本轮生成被用户手动中止,以上为已完成部分;未完成的步骤没有执行,请从中断处继续。]`:`[上一轮被用户手动中止于思考/工具阶段,没有产出可用内容;请重新规划并继续完成用户的目标。]`),{role:`assistant`,content:n,toolCalls:t}})},onScroll(){let e=this.$refs.listEl;e&&(this.pinned=e.scrollHeight-e.scrollTop-e.clientHeight<48)},scrollToBottom(e=!1){let t=this.$refs.listEl;t&&(!e&&!this.pinned||(t.scrollTop=t.scrollHeight))},stopTickers(){this._saveTimer&&clearTimeout(this._saveTimer),this._saveTimer=0},startTurn(){let e=Date.now();this.turnId=``,this.lastSeq=0,this.turnStep=0,this.turnStage=null,this.turnToolLabel=``,this.turnStartedAt=e,this.lastByteAt=e,this.nowTs=e,this.stopTurnTimers(),this._liveTicker=setInterval(()=>{this.nowTs=Date.now(),this.$emit(`turn-progress`,{steps:this.turnStep,startedAt:this.turnStartedAt,ms:this.nowTs-this.turnStartedAt,stage:this.turnStage?`${this.turnStage.id} ${this.turnStage.label}`:this.turnToolLabel,stalled:this.stalled})},1e3),this._turnPersistTimer=setInterval(()=>this.persist(),8e3),this.persist(),this.$emit(`busy`,!0)},stopTurnTimers(){this._liveTicker&&clearInterval(this._liveTicker),this._liveTicker=0,this._turnPersistTimer&&clearInterval(this._turnPersistTimer),this._turnPersistTimer=0},onPagehide(){let e=this.cardId;if(!e||!this.messages.length)return;let t=this.fitArchive(this.serialize());this._dirtyFor=null,this._saveTimer&&=(clearTimeout(this._saveTimer),0),NO(e,t,{keepalive:!0}).catch(()=>{})},fmtClock:jD,pushEvent(e,t){let n=String(t&&t.message||``);!n||!e||(Array.isArray(e.events)||(e.events=[]),e.events.push({ts:Date.now(),level:t.level||`warn`,code:t.code||``,message:n}))},applyUsage(e,t){if(!e||!t)return;let n=e=>Number.isFinite(Number(e))?Number(e):0;e.usage={steps:n(t.steps),promptTokens:n(t.promptTokens),completionTokens:n(t.completionTokens),cachedTokens:n(t.cachedTokens),cacheMissTokens:n(t.cacheMissTokens),hitRate:n(t.hitRate),reported:t.reported!==!1}},loadCompact(){try{this.compactSteps=localStorage.getItem(kN)===`1`}catch{}},setCompact(e){let t=!!e;if(this.compactSteps!==t){this.compactSteps=t;try{t?localStorage.setItem(kN,`1`):localStorage.removeItem(kN)}catch{}this.$nextTick(()=>this.scrollToBottom())}},toggleCompact(){this.setCompact(!this.compactSteps)},onLocateNode(e){e&&this.$emit(`locate-node`,String(e))},onRollbackTurn(e){if(this.busy)return;let t=this.cardId;!t||!e||this.$emit(`rollback-turn`,{cardId:t,ts:Number(e.ts)||0,msgId:e.id})},notify(e,t){this.notice={type:e,text:t},this._noticeTimer&&clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this.notice=null},6e3)}}},LN={class:`aichat__head`},RN={class:`aichat__titles`},zN={class:`aichat__sub`},BN={class:`aichat__acts`},VN=[`title`,`aria-pressed`],HN={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},UN=[`href`],WN=[`disabled`],GN={key:0,class:`aichat__banner`},KN={class:`aichat__scroll`},qN={key:0,class:`aichat__archnote`,title:`长对话记录超出落盘体积上限时,较早的工具参数与结果会被裁剪归档;正文、思考与过程事件都完整保留`},JN={key:1,class:`aichat__loading`},YN={key:2,class:`aichat__empty`},XN={class:`aichat__empty-title`},ZN={class:`aichat__empty-desc`},QN={class:`aichat__suggests`},$N=[`title`,`data-suggest-id`,`onClick`],eP={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},tP=[`href`],nP={class:`aichat__suggest-text`},rP={class:`aichat__suggest-label`},iP={class:`aichat__suggest-hint`},aP={key:0,class:`aichat__suggest-badge`,title:`该操作会改动卡片`},oP={class:`aichat__live-text`},sP={key:1,class:`aichat__quick`},cP=[`title`,`data-suggest-id`,`onClick`],lP={viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},uP=[`href`],dP={class:`ni-panel modal-card ccsw-dlg`,role:`dialog`,"aria-modal":`true`,"aria-label":`从 cc-switch 导入模型`},fP={class:`ni-head`},pP={class:`ni-body`},mP={class:`ni-scroll`},hP={key:0,class:`ccsw-dlg__msg`},gP={class:`ccsw-dlg__msg ccsw-dlg__msg--err`},_P={class:`ccsw-dlg__list`},vP=[`onClick`],yP={key:0,viewBox:`0 0 16 16`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linecap":`round`,"stroke-linejoin":`round`},bP={class:`ccsw-dlg__info`},xP={class:`ccsw-dlg__name`},SP={key:0,class:`ccsw-dlg__badge ccsw-dlg__badge--cur`,title:`cc-switch 中当前生效`},CP={key:1,class:`ccsw-dlg__badge ccsw-dlg__badge--dup`,title:`模型库中已存在同名模型`},wP={class:`ccsw-dlg__meta`},TP={class:`ccsw-dlg__model`},EP={class:`ccsw-dlg__host`},DP={class:`ni-foot`},OP={class:`ni-tip`},kP={class:`ni-foot-btns`},AP=[`disabled`];function jP(e,t,n,r,i,a){let o=L(`ChatMessage`),s=L(`ChatComposer`),c=L(`ModelList`),l=L(`AiSettings`),u=L(`ConfirmDialog`),d=L(`AiCommonSettings`);return B(),V(`aside`,{class:j([`aichat`,{"is-open":n.visible}]),style:A(a.panelStyle),role:`complementary`,"aria-label":`AI 开发助手`,onKeydown:t[23]||=vl((...e)=>a.onEscape&&a.onEscape(...e),[`esc`]),onClick:t[24]||=(...e)=>a.onImageClick&&a.onImageClick(...e)},[K(` 左缘拖拽把手:调宽(双击恢复默认 33%) `),U(`div`,{class:j([`aichat__grip`,{"is-dragging":i.resizing,"is-armed":i.gripArmed}]),title:`拖拽调整宽度(双击恢复默认)`,onMouseenter:t[0]||=(...e)=>a.armGrip&&a.armGrip(...e),onMouseleave:t[1]||=(...e)=>a.disarmGrip&&a.disarmGrip(...e),onPointerdown:t[2]||=q((...e)=>a.startResize&&a.startResize(...e),[`prevent`]),onDblclick:t[3]||=q((...e)=>a.resetWidth&&a.resetWidth(...e),[`prevent`])},null,34),K(` 头部:标题 + 当前卡片 / 模型 + 清空 / 设置 / 关闭 `),U(`header`,LN,[t[29]||=U(`span`,{class:`aichat__logo`},[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-sparkles`})])],-1),U(`span`,RN,[t[25]||=U(`span`,{class:`aichat__title`},`AI 开发助手`,-1),U(`span`,zN,[n.cardId?(B(),V(z,{key:0},[G(M(n.cardName||n.cardId),1)],64)):(B(),V(z,{key:1},[G(`未选择卡片`)],64)),i.config.model?(B(),V(z,{key:2},[G(` · `+M(i.config.model),1)],64)):K(`v-if`,!0)])]),U(`span`,BN,[K(` 紧凑视图(面板级):长任务里读取类调用能刷几十行,把写入与门禁挤到折叠线以下 `),U(`button`,{type:`button`,class:j([`aichat__iconbtn`,{"is-on":i.compactSteps}]),title:i.compactSteps?`紧凑视图已开启:已折叠读取类调用,点击显示全部步骤`:`只看关键步骤:折叠读取类调用(写入 / 跑脚本 / 报错始终显示)`,"aria-pressed":i.compactSteps?`true`:`false`,onClick:t[4]||=(...e)=>a.toggleCompact&&a.toggleCompact(...e)},[(B(),V(`svg`,HN,[U(`use`,{href:i.compactSteps?`#icon-eye-off`:`#icon-eye`},null,8,UN)]))],10,VN),U(`button`,{type:`button`,class:`aichat__iconbtn`,title:`清空本卡片对话记录`,disabled:!i.messages.length||i.busy,onClick:t[5]||=(...e)=>a.askClear&&a.askClear(...e)},[...t[26]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-trash`})],-1)]],8,WN),U(`button`,{type:`button`,class:`aichat__iconbtn`,title:`模型库`,onClick:t[6]||=(...e)=>a.openModelList&&a.openModelList(...e)},[...t[27]||=[U(`svg`,{class:`is-solid-icon`,viewBox:`0 0 1024 1024`,"aria-hidden":`true`},[U(`use`,{href:`#icon-model`})],-1)]]),U(`button`,{type:`button`,class:`aichat__iconbtn`,title:`关闭(Esc)`,onClick:t[7]||=t=>e.$emit(`close`)},[...t[28]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])])]),K(` 未配置模型:常驻提示条,一键打开设置 `),a.configReady?K(`v-if`,!0):(B(),V(`div`,GN,[t[30]||=U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-alert-triangle`})],-1),t[31]||=U(`span`,null,`尚未配置模型,无法对话。`,-1),U(`button`,{type:`button`,class:`aichat__banner-btn`,onClick:t[8]||=(...e)=>a.openModelList&&a.openModelList(...e)},`去设置`)])),K(` 消息区:滚动容器与悬浮「回到底部」共处一个定位上下文,按钮只贴消息区底缘,
|
|
281
|
+
输入区拖高 / 反馈条出现都不会把它盖住或悬空 `),U(`div`,KN,[U(`div`,{ref:`listEl`,class:`aichat__list`,onScroll:t[12]||=(...e)=>a.onScroll&&a.onScroll(...e)},[K(` 体积治理痕迹:较早的工具结果被裁剪过就说清楚,别让人以为记录丢了 `),i.archiveTrimmed?(B(),V(`div`,qN,[...t[32]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-activity`})],-1),U(`span`,null,`较早的工具参数 / 结果已裁剪归档(对话正文与过程事件完整保留)`,-1)]])):K(`v-if`,!0),i.loadingHistory?(B(),V(`div`,JN,`正在加载对话记录…`)):i.messages.length?(B(),V(z,{key:3},[K(` compact = 面板级「只看关键步骤」;can-rollback 只对当前卡片、非流式中开放(切了卡再回滚会写错对象) `),(B(!0),V(z,null,R(i.messages,(e,r)=>(B(),H(o,{key:e.id,msg:e,streaming:i.busy&&r===i.messages.length-1,"can-regenerate":e.role===`assistant`&&r===i.messages.length-1,compact:i.compactSteps,"can-rollback":e.role===`assistant`&&!i.busy&&!!n.cardId,"now-ts":i.busy&&r===i.messages.length-1?i.nowTs:0,onRegenerate:a.regenerate,onApproval:a.onApproval,onContinue:a.onContinue,onRollback:a.onRollbackTurn,onOpenSettings:a.openModelList,onShowAllSteps:t[10]||=e=>a.setCompact(!1),onLocateNode:a.onLocateNode},null,8,[`msg`,`streaming`,`can-regenerate`,`compact`,`can-rollback`,`now-ts`,`onRegenerate`,`onApproval`,`onContinue`,`onRollback`,`onOpenSettings`,`onLocateNode`]))),128)),K(` 面板级进度:步数 / 已用时长 / 建卡阶段 / 最近收到数据多久前。
|
|
282
|
+
长任务里「还活着吗」全靠这一行——旧版只有一句「生成中…」,网关静默与真在跑无从区分 `),i.busy?(B(),V(`div`,{key:0,class:j([`aichat__live`,{"is-stalled":a.stalled}]),role:`status`,"aria-live":`polite`},[t[35]||=U(`span`,{class:`aichat__live-dot`},null,-1),U(`span`,oP,M(a.liveText),1),a.stalled?(B(),V(`button`,{key:0,type:`button`,class:`aichat__live-act`,title:`连接可能已中断,终止本轮(已落盘的产物会保留)`,onClick:t[11]||=(...e)=>a.stop&&a.stop(...e)},` 终止 `)):K(`v-if`,!0)],2)):K(`v-if`,!0)],64)):(B(),V(`div`,YN,[t[34]||=U(`span`,{class:`aichat__empty-logo`},[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-sparkles`})])],-1),U(`p`,XN,M(a.emptyTitle),1),U(`p`,ZN,M(a.emptyDesc),1),U(`div`,QN,[(B(!0),V(z,null,R(a.suggestions,e=>(B(),V(`button`,{key:e.id,type:`button`,class:j([`aichat__suggest`,`is-${e.weight}`]),title:e.text,"data-suggest-id":e.id,onClick:t=>a.useSuggestion(e)},[(B(),V(`svg`,eP,[U(`use`,{href:e.icon},null,8,tP)])),U(`span`,nP,[U(`span`,rP,M(e.label),1),U(`span`,iP,M(e.hint),1)]),e.weight===`write`?(B(),V(`span`,aP,`改卡`)):K(`v-if`,!0)],10,$N))),128)),a.canShuffle?(B(),V(`button`,{key:0,type:`button`,class:`aichat__suggest-shuffle`,onClick:t[9]||=(...e)=>a.shuffleSuggestions&&a.shuffleSuggestions(...e)},[...t[33]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-refresh`})],-1),U(`span`,null,`换一批`,-1)]])):K(`v-if`,!0)])]))],544),K(` 回到底部:脱离底部吸附时出现 `),I(U(`button`,{type:`button`,class:`aichat__jump`,title:`回到底部`,onClick:t[13]||=e=>a.scrollToBottom(!0)},[...t[36]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-arrow-down`})],-1)]],512),[[Sc,!i.pinned&&i.messages.length]])]),K(` 常驻「常用」指令:有对话后空态建议区不再出现,这里保留一排轻量入口,随上下文同源 `),a.quickChips.length&&i.messages.length&&!i.busy?(B(),V(`div`,sP,[(B(!0),V(z,null,R(a.quickChips,e=>(B(),V(`button`,{key:e.id,type:`button`,class:j([`aichat__chip`,`is-${e.weight}`]),title:e.text,"data-suggest-id":e.id,onClick:t=>a.useSuggestion(e)},[(B(),V(`svg`,lP,[U(`use`,{href:e.icon},null,8,uP)])),U(`span`,null,M(e.label),1)],10,cP))),128))])):K(`v-if`,!0),K(` 操作反馈(附件解析失败 / 历史保存失败等) `),i.notice?(B(),V(`div`,{key:2,class:j([`aichat__notice`,`aichat__notice--${i.notice.type}`])},[U(`span`,null,M(i.notice.text),1),U(`button`,{type:`button`,class:`aichat__notice-x`,title:`关闭`,onClick:t[14]||=e=>i.notice=null},[...t[37]||=[U(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-x`})],-1)]])],2)):K(`v-if`,!0),W(s,{ref:`composerEl`,busy:i.busy,model:i.config.model,attachments:i.draftAttachments,placeholder:a.configReady?`描述你要改的卡片,Enter 发送 / Shift+Enter 换行`:`请先在设置中配置模型…`,context:i.contextUsage,onSend:a.onSend,onStop:a.stop,onPick:a.onPick,onAddPath:a.onAddPath,onRemoveAttachment:a.removeAttachment,onDropFiles:a.onDropFiles,onPasteImage:a.onPasteImage,onEscape:a.onEscape},null,8,[`busy`,`model`,`attachments`,`placeholder`,`context`,`onSend`,`onStop`,`onPick`,`onAddPath`,`onRemoveAttachment`,`onDropFiles`,`onPasteImage`,`onEscape`]),K(` 一级面板:模型库。从齿轮 / 横幅 / 消息内「去设置」进入 `),i.modelListOpen?(B(),H(c,{key:3,models:i.models,"active-id":i.activeId,"turn-running":i.turnRunning,onClose:a.closeModelList,onAdd:a.onModelAdd,onEdit:a.onModelEdit,onDelete:a.onModelDelete,onActivate:a.onModelActivate,onImportCcswitch:a.onImportCcSwitch,onOpenCommon:a.openCommon},null,8,[`models`,`active-id`,`turn-running`,`onClose`,`onAdd`,`onEdit`,`onDelete`,`onActivate`,`onImportCcswitch`,`onOpenCommon`])):K(`v-if`,!0),K(` 新增 / 编辑模型:复用 AiSettings(modelId 区分,initialModel 预填) `),i.modelEditOpen?(B(),H(l,{key:4,config:i.config,"model-id":i.editModelId,"initial-model":i.editInitialModel,onClose:a.onModelEditClose,onSaved:a.onModelSaved},null,8,[`config`,`model-id`,`initial-model`,`onClose`,`onSaved`])):K(`v-if`,!0),K(` 删除模型确认:二次确认后才真正落盘删除 `),W(u,{visible:!!i.confirmDeleteModel,"close-on-mask":!1,title:`删除模型`,message:a.deleteModelMessage,"confirm-text":`删除`,severity:`danger`,onConfirm:a.doDeleteModel,onCancel:t[15]||=e=>i.confirmDeleteModel=null},null,8,[`visible`,`message`,`onConfirm`]),K(` cc-switch 导入弹窗:列出 cc-switch 的 Codex 类供应商,勾选后批量导入模型库(按 model 去重) `),W(ic,{name:`modal`},{default:Lr(()=>[i.ccSwitchOpen?(B(),V(`div`,{key:0,class:`ni-overlay`,onClick:t[19]||=q(e=>i.ccSwitchOpen=!1,[`self`])},[U(`div`,dP,[U(`div`,fP,[t[38]||=U(`span`,{class:`ni-title`},`从 cc-switch 导入`,-1),U(`button`,{class:`ni-close`,type:`button`,title:`关闭`,onClick:t[16]||=e=>i.ccSwitchOpen=!1})]),U(`div`,pP,[U(`div`,mP,[K(` 加载中 `),i.ccSwitchLoading?(B(),V(`p`,hP,`正在读取 cc-switch 供应商…`)):i.ccSwitchReason?(B(),V(z,{key:1},[K(` 无可导入项 `),U(`p`,gP,M(i.ccSwitchReason),1)],2112)):(B(),V(z,{key:2},[K(` 供应商列表 `),U(`ul`,_P,[(B(!0),V(z,null,R(i.ccSwitchProviders,e=>(B(),V(`li`,{key:e.id,class:j([`ccsw-dlg__item`,{"is-active":i.ccSwitchSelected[e.id],"is-dup":e.duplicate}]),onClick:t=>a.toggleCcSwitchItem(e)},[U(`span`,{class:j([`ccsw-dlg__check`,{"is-on":i.ccSwitchSelected[e.id]}])},[i.ccSwitchSelected[e.id]?(B(),V(`svg`,yP,[...t[39]||=[U(`use`,{href:`#icon-check`},null,-1)]])):K(`v-if`,!0)],2),U(`span`,bP,[U(`span`,xP,[G(M(e.name||e.model)+` `,1),e.isCurrent?(B(),V(`span`,SP,`当前`)):K(`v-if`,!0),e.duplicate?(B(),V(`span`,CP,`已存在`)):K(`v-if`,!0)]),U(`span`,wP,[U(`span`,TP,M(e.model),1),t[40]||=U(`span`,{class:`ccsw-dlg__dot`},`·`,-1),U(`span`,EP,M(e.baseUrl),1)])])],10,vP))),128))])],2112))])]),U(`div`,DP,[U(`span`,OP,M(a.ccSwitchDupCount>0?`已有 ${a.ccSwitchDupCount} 个重复模型被自动跳过`:`勾选要导入的供应商,批量加入模型库`),1),U(`div`,kP,[U(`button`,{class:`ni-btn ni-btn--ghost`,type:`button`,onClick:t[17]||=e=>i.ccSwitchOpen=!1},`取消`),U(`button`,{class:`ni-btn`,type:`button`,disabled:i.ccSwitchLoading||!i.ccSwitchProviders.length||a.ccSwitchCheckedCount===0,onClick:t[18]||=(...e)=>a.confirmImportCcSwitch&&a.confirmImportCcSwitch(...e)},M(a.ccSwitchCheckedCount>0?`导入选中 ${a.ccSwitchCheckedCount} 项`:`导入`),9,AP)])])])])):K(`v-if`,!0)]),_:1}),K(` 通用设置:所有模型共享的执行策略 / 环境参数 `),i.commonOpen?(B(),H(d,{key:5,onClose:t[20]||=e=>i.commonOpen=!1,onSaved:a.onCommonSaved},null,8,[`onSaved`])):K(`v-if`,!0),W(u,{visible:i.confirmClear,"close-on-mask":!1,title:`清空对话记录`,message:`将删除卡片「${n.cardName||n.cardId||`当前卡片`}」的全部对话记录,此操作不可撤销。`,"confirm-text":`清空`,severity:`danger`,onConfirm:a.doClear,onCancel:t[21]||=e=>i.confirmClear=!1},null,8,[`visible`,`message`,`onConfirm`]),K(` 终止确认:生成中按 Esc 会走到这里。几十分钟的建卡被一次误按抹掉代价太大,故加一道确认 `),W(u,{visible:i.confirmStop,"close-on-mask":!1,title:`终止本次生成`,message:`已执行的写入与落盘产物都会保留,上下文也留在对话里,之后回复「继续」可从中断处接着做。确定现在终止?`,"confirm-text":`终止生成`,severity:`danger`,onConfirm:a.doStop,onCancel:t[22]||=e=>i.confirmStop=!1},null,8,[`visible`,`onConfirm`])],38)}var MP=X(IN,[[`render`,jP],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/ChatPanel.vue`]]),NP=`/assets/site-icon-CFMif8z4.png`,PP={includeMocks:!0},FP=2500,IP=new eu,LP=au({},IP);typeof window<`u`&&(window.__rt=LP);var RP=188,zP=320,BP=200,VP=160,HP={name:`App`,components:{RenderTree:ap,DebugPanel:wy,ApiCallPanel:By,CardSelect:ib,AlertCardLayer:mb,DeviceOverlay:Yb,PickerOverlay:ix,DatePickerOverlay:yx,SelectionOverlay:Cx,HoverGuides:kx,RemotePreview:_S,AppToast:TS,ImageLightbox:GS,ConfirmDialog:_p,CardGallery:fC,NewCardDialog:MC,ComponentPalette:qC,Switch:ZC,ChatPanel:MP},provide(){return{adapter:IP,cardRuntime:LP,customComponents:{}}},data(){return{adapter:IP,rt:LP,logoUrl:NP,appVersion:`0.33.2`,cardList:[],cardCount:0,galleryOpen:!1,cardDialog:{visible:!1,mode:`create`,cardId:``,cardDesc:``},selectedId:``,externalReloadNote:``,externalReloadTimer:null,selfSaveId:``,selfSaveAt:0,preview:null,chromeOff:!1,theme:`dark`,cardReady:!1,reloadToken:0,moveCollapseToken:0,refreshing:!1,loadingCard:!1,currentSchema:null,currentCard:null,cardImportMeta:null,localSchema:null,localData:null,selectedNodeId:``,activeTab:`vars`,apiPanelOpen:!0,addNodePanelOpen:!1,addNodeTarget:null,validateBadge:{state:`idle`,errors:0,warnings:0,renderOk:null,ts:0},validateTimer:null,copiedSchema:!1,copyTimer:null,savedCard:!1,savingCard:!1,saveTimer:null,savingRemote:!1,savedRemote:!1,verifiedRemote:null,saveRemoteTimer:null,syncingRemote:!1,syncedRemote:!1,remotePreviewOpen:!1,syncTarget:null,syncTimer:null,uploadingSlices:!1,loginModal:!1,loginName:``,loginPassword:``,loginSubmitting:!1,loginError:``,confirm:{show:!1,title:``,message:``,confirmText:`继续`,cancelText:`取消`,severity:`primary`,onConfirm:null},past:[],future:[],baseline:null,_commitTimer:null,viewportHeight:700,canvasBg:`gray`,refreshing:!1,bgOptions:[{key:`checker`,label:`棋盘`},{key:`white`,label:`白色`},{key:`gray`,label:`浅灰`},{key:`black`,label:`黑色`}],_previewWidthPx:372,_apiPanelWidthPx:360,presetSizes:[{key:375,value:`375`},{key:430,value:`430`},{key:188,value:`188`}],stageWidth:typeof window<`u`?window.innerWidth:1280,colsWidth:0,stageHeight:typeof window<`u`?window.innerHeight-52:748,dragging:!1,apiDragging:!1,armedLeft:!1,armedApi:!1,_armTimerLeft:null,_armTimerApi:null,_stageObserver:null,devServiceOpen:!1,aiChatOpen:(()=>{try{return sessionStorage.getItem(`cardbuddy:ai-chat-open`)===`1`}catch{return!1}})(),chatBusy:!1,chatProgress:null,devServiceForm:Nl(),apiBaseResolved:Fl(),devSvcLive:`unknown`,devSvcDown:!1,_unsubCardsChanged:null}},computed:{fabTitle(){if(this.aiChatOpen)return`AI 开发助手(已打开)`;if(!this.chatBusy)return`AI 开发助手`;let e=this.chatProgress,t=e&&e.startedAt?`${MD(e.startedAt)} 开始 · `:``;return`AI 开发助手正在生成(${e?`${t}第 ${e.steps} 步 · 已用 ${jD(e.ms)}${e.stage?` · ${e.stage}`:``}${e.stalled?` · 疑似断流`:``}`:``}),点击展开查看`},fabBadge(){return this.chatProgress&&this.chatProgress.stalled?`!`:String(this.chatProgress&&this.chatProgress.steps||0)},currentBg(){return this.bgOptions.find(e=>e.key===this.canvasBg)||this.bgOptions[0]},cardIds(){return this.cardList.map(e=>e&&e.id).filter(Boolean)},canUndo(){return this.past.length>0},canRedo(){return this.future.length>0},devSvcBlockReason(){let e=this.devServiceForm||{};return String(e.baseUrl||``).trim()?e.enabled?null:`disabled`:`empty`},canPaste(){return!!Hu()},hasCardSource(){return!!(this.cardImportMeta&&this.cardImportMeta.source)},historyDirty(){return!this.localSchema||!this.currentSchema?!1:!this.structuralEqual(this.currentSchema,this.localSchema)||!this.dataEqual(this.rt&&this.rt.rootScope,this.localData)},devSvcConn(){return this.apiBaseResolved===null?`unconfigured`:this.devSvcLive===`open`?`open`:this.devSvcDown?`closed`:`connecting`},devSvcTitle(){if(this.apiBaseResolved===null)return this.devSvcBlockReason===`disabled`?`已填地址但未开启用本地服务`:`未配置本地开发服务(部署态必填)`;let e=this.apiBaseResolved===``?`同源开发服务`:`本地开发服务`;return this.devSvcLive===`open`?e+`已连接`:this.devSvcDown?e+`已断开(连接失败或服务已停止,重连中…)`:e+`连接中 / 重连中…`},devSvcClass(){return this.apiBaseResolved===null?`app__btn--warn`:this.devSvcLive===`open`?`app__btn--connected`:this.devSvcDown?`app__btn--disconnected`:`app__btn--reconnecting`},devSvcLabel(){return this.apiBaseResolved===null?`未配置本地服务`:this.devSvcLive===`open`?`本地服务已连接`:this.devSvcDown?`本地服务已断开`:`本地服务连接中…`},badgeText(){return{idle:`待校验`,pending:`校验中…`,ok:`校验通过`,error:`校验未通过`,nopython:`未配置校验`,fail:`校验服务异常`}[this.validateBadge.state]||`待校验`},badgeTitle(){let e=this.validateBadge;if(e.state===`ok`)return`结构合法 + 渲染不抛错(不保证画得对,视觉正确性见截图)`;if(e.state===`error`){let t=[];return e.errors&&t.push(`契约错误 ${e.errors} 个`),e.renderOk===!1&&t.push(`渲染抛出异常`),`校验未通过:`+(t.join(`;`)||`详见 /__validate 与 /__render-status`)}return e.state===`nopython`?`未找到 python3/python,无法跑契约校验(请安装 Python 或设置 DSL_PYTHON)`:e.state===`fail`?`校验服务异常(dev server 未启动或端点不可用)`:``},previewWidth(){if(this.chromeOff)return this.stageWidth;let{min:e,max:t}=this.previewBounds,n=this._previewWidthPx||RP;return Math.max(e,Math.min(t,n))},viewportWidth(){return this.stageWidth,typeof window<`u`?window.innerWidth:1280},debugSoftWidth(){return Math.max(BP,Math.floor(this.viewportWidth/3))},previewBounds(){let e=this.stageWidth||0,t=Math.floor(e/2),n=e-zP-this.debugSoftWidth;return{min:RP,max:Math.max(RP,Math.min(t,n))}},debugMinWidth(){let e=this.colsWidth||Math.max(0,(this.stageWidth||0)-this.previewWidth);return Math.max(BP,Math.min(this.debugSoftWidth,Math.floor(e)-zP))},apiPanelBounds(){let e=this.colsWidth||Math.max(0,(this.stageWidth||0)-this.previewWidth),t=Math.max(VP,Math.floor(e)-this.debugMinWidth);return{min:Math.min(zP,t),max:t}},canvasW(){return Math.round(this.previewWidth||375)},selectedCardName(){let e=this.cardList.find(e=>e.id===this.selectedId);return e&&e.name||this.selectedId||``},cardEmpty(){let e=this.currentSchema;if(!e||!e.view)return!0;let t=e.view.components;return!Array.isArray(t)||t.length===0},apiPanelWidth(){let{min:e,max:t}=this.apiPanelBounds,n=this._apiPanelWidthPx||360;return Math.max(e,Math.min(t,n))},frameStyle(){return{}}},watch:{activeTab(e){e!==`structure`&&(this.selectedNodeId=``,Ex())},aiChatOpen(e){try{sessionStorage.setItem(`cardbuddy:ai-chat-open`,e?`1`:`0`)}catch{}},theme(e){document.documentElement.dataset.theme=e},apiPanelOpen(e){try{localStorage.setItem(`cardbuddy:api-panel-open`,e?`1`:`0`)}catch{}}},beforeUnmount(){this.viewportObserver&&this.viewportObserver.disconnect(),this._stageObserver&&this._stageObserver.disconnect(),this.saveTimer&&clearTimeout(this.saveTimer),this.syncTimer&&clearTimeout(this.syncTimer),this.saveRemoteTimer&&clearTimeout(this.saveRemoteTimer),window.removeEventListener(`keydown`,this.onKeydown)},mounted(){this.viewportObserver=new ResizeObserver(e=>{for(let t of e)this.viewportHeight=Math.round(t.contentRect.height)}),this.$refs.phoneViewport&&this.viewportObserver.observe(this.$refs.phoneViewport),this.loadPreviewWidth(),this.loadApiPanelWidth(),this._stageObserver=new ResizeObserver(e=>{for(let t of e){if(t.target===this.$refs.colsEl){this.colsWidth=Math.round(t.contentRect.width);continue}this.stageWidth=Math.round(t.contentRect.width),this.stageHeight=Math.round(t.contentRect.height)}}),this.$refs.stageEl&&this._stageObserver.observe(this.$refs.stageEl),this.$refs.colsEl&&this._stageObserver.observe(this.$refs.colsEl),window.addEventListener(`keydown`,this.onKeydown)},async created(){Ib(LP);let e=new URLSearchParams(location.search).get(`chrome`);this.chromeOff=e===`off`||e===``;try{let e=localStorage.getItem(`cardbuddy:theme`);(e===`light`||e===`dark`)&&(this.theme=e)}catch{}document.documentElement.dataset.theme=this.theme;try{localStorage.getItem(`cardbuddy:api-panel-open`)===`0`&&(this.apiPanelOpen=!1)}catch{}await this.fetchCardList();let t=new URLSearchParams(location.search).get(`card`),n=null;try{let e=localStorage.getItem(`cardbuddy:selected-card`);e&&this.cardList.some(t=>t.id===e)&&(n=e)}catch{}let r=t&&this.cardList.some(e=>e.id===t)?t:n||this.cardList[0]&&this.cardList[0].id;r&&(this.selectedId=r,await this.loadCard(this.selectedId)),this.$watch(()=>this.rt.rootScope,()=>{this.syncDataToSchema()},{deep:!0}),this.setupCardsChanged()},methods:{setupCardsChanged(){if(this._unsubCardsChanged){try{this._unsubCardsChanged()}catch{}this._unsubCardsChanged=null}this.devSvcLive=`connecting`,this._unsubCardsChanged=Vl(e=>this.onCardsChanged(e),e=>this.onDevServiceState(e))},onDevServiceState(e){let t=this.devSvcLive===`connecting`;this.devSvcLive=e,e===`open`?this.devSvcDown=!1:e===`closed`&&(this.devSvcDown=!0),e===`connecting`?!t&&!this._svcWatchdog&&(this._svcWatchdog=setTimeout(()=>{this.devSvcLive===`connecting`&&(this.devSvcLive=`closed`,this.devSvcDown=!0),this._svcWatchdog=null},8e3)):this._svcWatchdog&&=(clearTimeout(this._svcWatchdog),null)},saveDevService(){Pl(this.devServiceForm),this.apiBaseResolved=Fl(),this.setupCardsChanged(),this.devServiceOpen=!1,Z(`本地开发服务配置已保存`,`ok`),this.fetchCardList()},beginColumnDrag(e,t,n){let r=e&&e.currentTarget;if(!r)return;let i=e.pointerId;try{r.setPointerCapture(i)}catch{}let a=()=>{r.removeEventListener(`pointermove`,t),r.removeEventListener(`pointerup`,a),r.removeEventListener(`pointercancel`,a),window.removeEventListener(`blur`,a);try{r.hasPointerCapture?.(i)&&r.releasePointerCapture(i)}catch{}document.body.style.cursor=``,document.body.style.userSelect=``,n()};document.body.style.cursor=`col-resize`,document.body.style.userSelect=`none`,r.addEventListener(`pointermove`,t),r.addEventListener(`pointerup`,a),r.addEventListener(`pointercancel`,a),window.addEventListener(`blur`,a)},armSplitter(e){let t=e===`api`?`_armTimerApi`:`_armTimerLeft`;clearTimeout(this[t]),this[t]=setTimeout(()=>{e===`api`?this.armedApi=!0:this.armedLeft=!0},600)},disarmSplitter(e){let t=e===`api`?`_armTimerApi`:`_armTimerLeft`;if(clearTimeout(this[t]),this[t]=null,e===`api`){if(this.apiDragging)return;this.armedApi=!1}else{if(this.dragging)return;this.armedLeft=!1}},startDrag(e){if(this.chromeOff||!this.armedLeft)return;let t=this.$refs.stageEl;if(!t)return;let n=t.getBoundingClientRect().left;this.dragging=!0,this.beginColumnDrag(e,e=>{let{min:t,max:r}=this.previewBounds;this._previewWidthPx=Math.max(t,Math.min(r,Math.round(e.clientX-n)))},()=>{this.dragging=!1,this.savePreviewWidth()})},startApiDrag(e){if(this.chromeOff||!this.apiPanelOpen||!this.armedApi)return;let t=this.$refs.colsEl;if(!t)return;let n=t.getBoundingClientRect().right;this.apiDragging=!0,this.beginColumnDrag(e,e=>{let{min:t,max:r}=this.apiPanelBounds;this._apiPanelWidthPx=Math.max(t,Math.min(r,Math.round(n-e.clientX)))},()=>{this.apiDragging=!1,this.saveApiPanelWidth()})},loadPreviewWidth(){try{let e=localStorage.getItem(`cardbuddy:preview-width`);if(e!=null){let t=parseInt(e,10);!Number.isNaN(t)&&t>=188&&(this._previewWidthPx=t)}}catch{}},savePreviewWidth(){try{localStorage.setItem(`cardbuddy:preview-width`,String(Math.round(this._previewWidthPx)))}catch{}},setPresetWidth(e){if(this.chromeOff)return;let{min:t,max:n}=this.previewBounds;this._previewWidthPx=Math.max(t,Math.min(n,e)),this.savePreviewWidth()},loadApiPanelWidth(){try{let e=localStorage.getItem(`cardbuddy:api-panel-width`);if(e!=null){let t=parseInt(e,10);!Number.isNaN(t)&&t>=320&&(this._apiPanelWidthPx=t)}}catch{}},saveApiPanelWidth(){try{localStorage.setItem(`cardbuddy:api-panel-width`,String(Math.round(this.apiPanelWidth)))}catch{}},chooseBg(e){this.canvasBg=e},onSelect(e){this.loadingCard=!0,this.selectedId=e,this.loadCard(e,{clearAll:!0})},selectCard(e){this.selectedId=e;try{localStorage.setItem(`cardbuddy:selected-card`,e)}catch{}},openGallery(){this.cardList.length&&(this.galleryOpen=!0)},openNewCard(){this.cardDialog.mode=`create`,this.cardDialog.cardId=``,this.cardDialog.cardDesc=``,this.cardDialog.visible=!0,this.fetchCardList()},openRenameCard(){this.selectedId&&(this.cardDialog.mode=`rename`,this.cardDialog.cardId=this.selectedId,this.cardDialog.cardDesc=this.currentSchema&&this.currentSchema.desc||``,this.cardDialog.visible=!0,this.fetchCardList())},async onCardRenamed({oldId:e,id:t}){if(this.cardDialog.visible=!1,Z(t===e?`已更新卡片描述`:`已重命名卡片 ${e} → ${t}`,`ok`),t!==e)return this.applyCardRename(e,t);await this.fetchCardList(),await this.loadCard(t)},async applyCardRename(e,t){if(!e||!t||e===t)return;let n=`${e}->${t}`;if(this._renameAppliedKey===n)return;this._renameAppliedKey=n,setTimeout(()=>{this._renameAppliedKey===n&&(this._renameAppliedKey=``)},1e3);let r=this.selectedId===e;if(this.$refs.chatPanel?.migrateCard(e,t),r&&this.selectCard(t),this.selfSaveId=t,this.selfSaveAt=Date.now(),await this.fetchCardList(),r){if(this.historyDirty&&!this.confirm.show){this.requestConfirm({title:`卡片已重命名`,message:`卡片「${e}」已重命名为「${t}」,而编辑器内还有未保存的改动。\n重新载入会放弃这些未保存改动并显示磁盘版本;保留改动则继续用当前编辑器内容(后续保存会写到新目录 ${t})。`,confirmText:`重新载入`,cancelText:`保留我的改动`,onConfirm:()=>this.loadCard(t)});return}await this.loadCard(t)}},closeGallery(){this.galleryOpen=!1},async openCardFolder(){if(this.selectedId)try{let e=await J(`/__open-folder`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:this.selectedId})}),t=(e.headers.get(`content-type`)||``).includes(`application/json`)?await e.json().catch(()=>({})):{};!e.ok||!t.ok?Z(t.error||`打开文件夹失败`,`err`):Z(`已打开卡片文件夹`,`ok`)}catch{Z(`无法连接本地开发服务,请确认已启动`,`err`)}},async refreshCard(){if(!(!this.selectedId||this.refreshing)){this.refreshing=!0;try{await this.loadCard(this.selectedId)}finally{this.refreshing=!1}}},toggleTheme(){this.theme=this.theme===`light`?`dark`:`light`;try{localStorage.setItem(`cardbuddy:theme`,this.theme)}catch{}},toggleApiPanel(){this.apiPanelOpen=!this.apiPanelOpen},async refreshValidateBadge(){let e=this.selectedId;if(!(!e||!this.preview)&&(this.validateTimer&&clearTimeout(this.validateTimer),this.validateBadge={...this.validateBadge,state:`pending`},await new Promise(e=>{this.validateTimer=setTimeout(e,120)}),this.selectedId===e))try{let[t,n]=await Promise.all([J(`/__validate/${encodeURIComponent(e)}`),J(`/__render-status/${encodeURIComponent(e)}`)]);if(!t.ok){this.validateBadge={...this.validateBadge,state:t.status===503?`nopython`:`fail`};return}let r=await t.json().catch(()=>null),i=n.ok?await n.json().catch(()=>null):null;if(!r){this.validateBadge={...this.validateBadge,state:`fail`};return}let a=!!r.ok,o=!i||!!i.renderOk,s=a&&o?`ok`:`error`,c=this.validateBadge.state!==s;this.validateBadge={state:s,errors:(r.errors||[]).length,warnings:(r.warnings||[]).length,renderOk:o,ts:Date.now()},c&&(s===`ok`||s===`error`)&&this.celebrateValidate(s)}catch{this.validateBadge={...this.validateBadge,state:`fail`}}},celebrateValidate(e=`ok`){let t=this.$refs.validateBadgeEl;if(!t||window.matchMedia&&window.matchMedia(`(prefers-reduced-motion: reduce)`).matches)return;t.classList.remove(`is-celebrating`),t.offsetWidth,t.classList.add(`is-celebrating`),setTimeout(()=>t.classList.remove(`is-celebrating`),600);let n=t.getBoundingClientRect(),r={ok:`--ok`,error:`--danger`,pending:`--warn`,fail:`--text-faint`,nopython:`--text-faint`}[e]||`--ok`,i={ok:`#52c41a`,error:`#F5222D`,pending:`#FAAD14`,fail:`#8c8c8c`,nopython:`#8c8c8c`}[e]||`#52c41a`,a=getComputedStyle(t).getPropertyValue(r).trim()||i,o=document.createElement(`div`);o.className=`app__confetti`,o.style.left=n.left+n.width/2+`px`,o.style.top=n.top+n.height/2+`px`;let s=[`polygon(50% 0%, 0% 100%, 100% 100%)`,`polygon(62% 0%, 100% 40%, 45% 100%, 0% 52%)`,`polygon(0% 0%, 100% 18%, 82% 100%, 12% 70%)`,`polygon(22% 0%, 100% 8%, 88% 100%, 0% 76%)`,`polygon(0% 32%, 100% 0%, 76% 100%, 18% 86%)`,`polygon(8% 0%, 100% 22%, 70% 100%, 0% 64%)`,`polygon(0% 12%, 100% 0%, 100% 78%, 30% 100%, 12% 55%)`],c=n.width/2,l=n.height/2;for(let e=0;e<22;e++){let e=document.createElement(`span`);e.className=`app__confetti-bit`;let t=Math.random()*4|0,n,r;t===0?(n=(Math.random()*2-1)*c,r=-l):t===1?(n=c,r=(Math.random()*2-1)*l):t===2?(n=(Math.random()*2-1)*c,r=l):(n=-c,r=(Math.random()*2-1)*l);let i=Math.hypot(n,r)||1,u=Math.atan2(r/i,n/i)+(Math.random()-.5)*.5,d=16+Math.random()*26;e.style.setProperty(`--sx`,n.toFixed(1)+`px`),e.style.setProperty(`--sy`,r.toFixed(1)+`px`),e.style.setProperty(`--tx`,(Math.cos(u)*d).toFixed(1)+`px`),e.style.setProperty(`--ty`,(Math.sin(u)*d).toFixed(1)+`px`),e.style.setProperty(`--rot`,(Math.random()*720-360).toFixed(0)+`deg`),e.style.setProperty(`--clip`,s[Math.random()*s.length|0]),e.style.setProperty(`--c`,a),e.style.setProperty(`--o`,(.68+Math.random()*.27).toFixed(2));let f=Math.random(),p,m;f<.35?(p=1.5+Math.random()*2,m=10+Math.random()*10):f<.75?(p=4+Math.random()*5,m=p*(.6+Math.random()*.8)):(p=2+Math.random()*2.5,m=p),e.style.width=p.toFixed(0)+`px`,e.style.height=m.toFixed(0)+`px`,o.appendChild(e)}document.body.appendChild(o),setTimeout(()=>o.remove(),800)},async loadCard(e,t={}){if(e){this.loadingCard=!0;try{let n=await J(`/__card/${encodeURIComponent(e)}`);if(!n.ok){this.rt.pushError(`loadCard`,`HTTP `+n.status);return}let r=await n.json();if(!r.schema){this.rt.pushError(`loadCard`,`schema 读取失败`);return}this.selectCard(e),t.clearAll?this.rt.clearErrors():this.rt.clearBindingErrors(),this.rt.clearApiCalls(),t.keepScope||this.rt.setRootScope(Xg(r.schema,PP)),this.currentCard={schema:r.schema},this.currentSchema=r.schema,this.cardImportMeta=null,this.fetchImportMeta(e),this.localSchema=this.cloneSchema(r.schema),this.localData=this.cloneData(Xg(r.schema,PP)),this.preview=Pu(r.schema),typeof window<`u`&&(window.__cardModel=Bu(r.schema)),this.cardReady=!1,this.$nextTick(()=>{this.cardReady=!0}),this.syncDataToSchema(),this.selectedNodeId=``,this.baseline={schema:this.cloneSchema(this.currentSchema)},this.reloadToken+=1,ub(),Lb(),this.refreshValidateBadge(),await this.loadHistory(e)}finally{this.loadingCard=!1}}},cloneSchema(e){return e?JSON.parse(JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t)):null},normalizeForCompare(e){let t=this.cloneSchema(e);if(t&&t.dictionary&&Array.isArray(t.dictionary.inputParams))for(let e of t.dictionary.inputParams)e&&typeof e==`object`&&(e.defaultValue=void 0);return t},structuralEqual(e,t){return!e||!t?e===t:JSON.stringify(this.normalizeForCompare(e))===JSON.stringify(this.normalizeForCompare(t))},cloneData(e){return e==null?e:JSON.parse(JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t))},dataEqual(e,t){return JSON.stringify(e)===JSON.stringify(t)},applySchemaSnapshot(e){if(!this.selectedId||!e)return;let t=e.schema||e,n=e.data==null?Xg(t,PP):e.data;this.currentSchema=this.cloneSchema(t),this.rt.setRootScope(this.cloneData(n)),this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``,this.reloadToken+=1,this.refreshValidateBadge()},commitHistory(){if(!this.currentSchema||!this.baseline)return;let e=this.structuralEqual(this.currentSchema,this.baseline.schema),t=this.dataEqual(this.rt.rootScope,Xg(this.baseline.schema,PP));if(e&&t)return;let n={schema:this.baseline.schema};this.past.push(n),this.past.length>30&&this.past.shift(),this.future=[],this.baseline={schema:this.cloneSchema(this.currentSchema)},this.persistSnapshot(n)},scheduleCommit(){this._commitTimer&&clearTimeout(this._commitTimer),this._commitTimer=setTimeout(()=>{this._commitTimer=null,this.commitHistory()},500)},persistSnapshot(e){let t=this.selectedId;if(!t)return;let n=e.schema||e;J(`/__history/${encodeURIComponent(t)}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({schema:n},(e,t)=>e===`_schemaNode`?void 0:t,2)}).catch(e=>console.warn(`[历史快照落盘失败]`,e))},async loadHistory(e){this.past=[],this.future=[];try{let t=await J(`/__history/${encodeURIComponent(e)}`);if(!t.ok)return;let n=await t.json().catch(()=>null),r=n&&n.snapshots||[];this.past=r.slice(-30).map(e=>({schema:e.schema,data:e.data==null?Xg(e.schema,PP):e.data}))}catch(e){console.warn(`[加载编辑历史失败]`,e)}},undo(){if(!this.canUndo)return;let e=this.past.pop();this.future.push(this.baseline),this.future.length>30&&this.future.shift(),this.baseline=e,this.applySchemaSnapshot(e)},redo(){if(!this.canRedo)return;let e=this.future.pop();this.past.push(this.baseline),this.past.length>30&&this.past.shift(),this.baseline=e,this.applySchemaSnapshot(e)},async applyHistoryToLocal(){this.loadingCard||!this.historyDirty||!this.preview||!this.selectedId||await this.saveCard()&&Z(`已将该版本保存到本地`,`ok`)},onSchemaChanged(){!this.selectedId||!this.currentSchema||(this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``)},onSchemaCommit(){!this.selectedId||!this.currentSchema||(this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``,this.commitHistory())},syncDataToSchema(){let e=this.currentSchema;if(!e||!e.dictionary||!Array.isArray(e.dictionary.inputParams))return;let t=this.rt&&this.rt.rootScope;if(!t||typeof t!=`object`)return;let n=e.dictionary.inputParams,r=Zg(e);for(let e of Object.keys(t)){let i=n.find(t=>t&&(t.key===e||t.name===e));if(!i)continue;let a=JSON.parse(JSON.stringify(t[e],(e,t)=>e===`_schemaNode`?void 0:t));r&&Object.prototype.hasOwnProperty.call(r,e)?r[e]=a:i.defaultValue=a}},onSelectNode(e){this.selectedNodeId=e||``},findPreviewNodeById(e,t){if(!e||t==null)return null;let n=String(t),r=e=>{if(!e)return null;if(String(e.id)===n)return e;let t=[];if(e.components&&t.push(...e.components),e.slots)for(let n of e.slots)n.components&&t.push(...n.components);for(let e of t){let t=r(e);if(t)return t}return null};return r(e)},copySelectedNode(){let e=this.selectedNodeId;if(!e||e===`_root`||!this.currentSchema||!this.preview)return;let t=this.findPreviewNodeById(this.preview.view,e);if(!t)return;let n=this.findSchemaNodeByComponentId(this.currentSchema.view,t.componentId);n&&(Wu(n.node,this.selectedId),Z(`已复制节点(含子节点)`,`ok`))},pasteNode(){let e=Hu();if(!e||!this.currentSchema)return;let t=Gu(e),n=[...new Set(t.filter(e=>!vu[e]))];if(n.length){Z(`粘贴失败:含未知组件类型 `+n.join(`、`),`err`);return}let r=JSON.parse(JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t));Ku(r);let i=this.selectedNodeId&&this.selectedNodeId!==`_root`?this.findPreviewNodeById(this.preview.view,this.selectedNodeId):null,a=`root`;i&&(a=ju(i.className)?`into`:`after`),this.insertClone(r,i,a);let o=Uu();o&&o!==this.selectedId?Z(`已从卡片「${o}」跨卡片粘贴到「${this.selectedId}」`,`ok`):Z(`已粘贴节点(含子节点)`,`ok`)},duplicateNode(){let e=this.selectedNodeId;if(!e||e===`_root`||!this.currentSchema||!this.preview)return;let t=this.findPreviewNodeById(this.preview.view,e);if(!t)return;let n=this.findSchemaNodeByComponentId(this.currentSchema.view,t.componentId);if(!n)return;let r=JSON.parse(JSON.stringify(n.node,(e,t)=>e===`_schemaNode`?void 0:t));Ku(r),n.parentArr.splice(n.index+1,0,r),this.afterStructuralEdit(r.componentId)},insertClone(e,t,n){let r=this.currentSchema;if(n===`root`)r.view.components||(r.view.components=[]),r.view.components.push(e);else if(n===`into`){let n=t&&t._schemaNode;if(!n){r.view.components||(r.view.components=[]),r.view.components.push(e),this.afterStructuralEdit(e.componentId);return}let i=Mu(t.className),a=(n.slots||[]).find(e=>e.slotKey===i);a||(n.slots||=[],a={slotKey:i,slotScope:!1,slotSwitch:`1`,components:[]},n.slots.push(a)),a.components||(a.components=[]),a.components.push(e)}else{let n=this.findSchemaNodeByComponentId(r.view,t.componentId);n?n.parentArr.splice(n.index+1,0,e):(r.view.components||(r.view.components=[]),r.view.components.push(e))}this.afterStructuralEdit(e.componentId)},afterStructuralEdit(e){let t=this.currentSchema;this.reloadToken+=1,this.preview=Pu(t),typeof window<`u`&&(window.__cardModel=Bu(t)),this.syncDataToSchema(),this.selectedNodeId=e&&this.findViewIdByComponentId(this.preview.view,e)||``,this.scheduleCommit()},deleteSelectedNode(){let e=this.selectedNodeId;if(!e||e===`_root`||!this.currentSchema||!this.preview)return;let t=this.findPreviewNodeById(this.preview.view,e);if(!t)return;let n=this.findSchemaNodeByComponentId(this.currentSchema.view,t.componentId);n&&(n.parentArr.splice(n.index,1),this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema(),this.selectedNodeId=``,Ex(),this.scheduleCommit())},hasTextSelection(){if(typeof window>`u`||!window.getSelection)return!1;let e=window.getSelection();return!!e&&!e.isCollapsed&&e.toString().trim()!==``},hasNodeSelection(){return!!this.selectedNodeId&&this.selectedNodeId!==`_root`},isEditableTarget(e){let t=e.target;if(!t)return!1;let n=t.tagName;return!!(n===`INPUT`||n===`TEXTAREA`||n===`SELECT`||t.isContentEditable)},onKeydown(e){if(this.chromeOff||!this.preview)return;let t=this.isEditableTarget(e),n=e.ctrlKey||e.metaKey,r=e.key;if(n&&(r===`c`||r===`C`)){if(t||this.hasTextSelection()||!this.hasNodeSelection())return;this.copySelectedNode(),e.preventDefault();return}if(n&&(r===`v`||r===`V`)){if(t||this.hasTextSelection()||!this.hasNodeSelection()||!Hu())return;this.pasteNode(),e.preventDefault();return}if(n&&(r===`d`||r===`D`)){if(t||this.hasTextSelection()||!this.hasNodeSelection())return;this.duplicateNode(),e.preventDefault();return}if(n&&(r===`z`||r===`Z`)){if(t)return;e.preventDefault(),e.shiftKey?this.redo():this.undo();return}if(n&&(r===`y`||r===`Y`)){if(t)return;e.preventDefault(),this.redo();return}if(r===`Delete`||r===`Backspace`){if(t||!this.selectedNodeId||this.selectedNodeId===`_root`)return;e.preventDefault(),this.deleteSelectedNode();return}if(r===`Escape`){this.selectedNodeId&&(this.selectedNodeId=``,e.preventDefault());return}},onHoverNode(e){if(!e){Ex();return}if(e.leave){Ex(e.id);return}let t=typeof document<`u`?document.querySelector(`.phone__screen`):null;if(!t){Ex(e.id);return}let n=e=>window.CSS&&CSS.escape?CSS.escape(String(e)):String(e).replace(/["\\\]]/g,`\\$&`),r=null;e.componentId!=null&&(r=t.querySelector(`[data-cid="`+n(e.componentId)+`"]`)),!r&&e.id!=null&&(r=t.querySelector(`[data-cid="`+n(e.id)+`"]`)),r?Tx(r,e.id):Ex(e.id)},onCanvasClick(e){if(!e.ctrlKey&&!e.metaKey||this.chromeOff)return;let t=e.target&&e.target.closest?e.target.closest(`[data-cid]`):null;if(!t)return;let n=t.getAttribute(`data-cid`);if(!n)return;let r=this.findPreviewNodeByCid(n);r&&(this.activeTab=`structure`,this.selectedNodeId=r.id)},onAiLocateNode(e){let t=e?this.findPreviewNodeByCid(e):null;if(!t){Z(`没找到组件 ${e||``}:卡片可能已被改动,重新校验一次即可`,`err`);return}this.activeTab=`structure`,this.selectedNodeId=t.id},findPreviewNodeByCid(e){let t=this.preview&&this.preview.view;if(!t)return null;let n=String(e),r=e=>{if(!e)return null;if(String(e.componentId==null?e.id:e.componentId)===n)return e;let t=[];if(e.components&&t.push(...e.components),e.slots)for(let n of e.slots)n.components&&t.push(...n.components);for(let e of t){let t=r(e);if(t)return t}return null};return r(t)},onAddNode(e){this.currentSchema&&(this.addNodeTarget=e||null,this.addNodePanelOpen=!0)},cancelAddNode(){this.addNodePanelOpen=!1,this.addNodeTarget=null},findSchemaLocation(e,t){let n=e=>{for(let r=0;r<e.length;r++){let i=e[r];if(i===t)return{containerArr:e,index:r};let a=i.slots||[];for(let e of a){let t=n(e.components||[]);if(t)return t}}return null};return n(e&&e.components||[])},findViewIdByComponentId(e,t){if(!e)return null;if(e.componentId===t)return e.id;let n=[];if(e.components&&n.push(...e.components),e.slots)for(let t of e.slots)t.components&&n.push(...t.components);for(let e of n){let n=this.findViewIdByComponentId(e,t);if(n)return n}return null},findSchemaNodeByComponentId(e,t){let n=(e,r)=>{for(let i=0;i<e.length;i++){let a=e[i];if(a.componentId===t)return{node:a,parentArr:e,index:i,owner:r};let o=a.slots||[];for(let e of o){let t=n(e.components||[],a);if(t)return t}}return null};return n(e&&e.components||[],`root`)},isDescendantCompId(e,t){if(!t||!t.componentId)return!1;if(t.componentId===e)return!0;let n=[];if(t.components&&n.push(...t.components),t.slots)for(let e of t.slots)e.components&&n.push(...e.components);for(let t of n)if(this.isDescendantCompId(e,t))return!0;return!1},moveNode(e,t,n){let r=this.currentSchema;if(!r||!r.view||e===t)return!1;let i=this.findSchemaNodeByComponentId(r.view,e);if(!i)return!1;let a=i.node;if(this.isDescendantCompId(t,a))return!1;let o,s;if(t===`__root__`)r.view.components||(r.view.components=[]),o=r.view.components,s=o.length;else{let e=this.findSchemaNodeByComponentId(r.view,t);if(!e)return!1;let i=e.node;if(n===`inside`){if(!ju(i.className))return!1;let e=Mu(i.className),t=(i.slots||[]).find(t=>t.slotKey===e);t||(i.slots||=[],t={slotKey:e,slotScope:!1,slotSwitch:`1`,components:[]},i.slots.push(t)),t.components||(t.components=[]),o=t.components,s=o.length}else o=e.parentArr,s=n===`before`?e.index:e.index+1}let c=o===i.parentArr&&i.index<s;return i.parentArr.splice(i.index,1),c&&--s,o.splice(s,0,a),a},onMoveNode({sourceCompId:e,targetCompId:t,position:n}){if(!this.currentSchema||!this.moveNode(e,t,n))return;this.reloadToken+=1,this.preview=Pu(this.currentSchema),typeof window<`u`&&(window.__cardModel=Bu(this.currentSchema)),this.syncDataToSchema();let r=this.findViewIdByComponentId(this.preview.view,e);this.selectedNodeId=r||``,r&&(this.moveCollapseToken+=1)},onPickComponent(e){let t=this.addNodeTarget||{},n=t.node||null,r=t.mode||`auto`,i=this.currentSchema;if(!i){this.cancelAddNode();return}let a;try{a=Nu(e)}catch(e){console.error(`[创建组件节点失败]`,e),this.rt.pushError(`addNode`,String(e&&e.message)),this.cancelAddNode();return}let o=!n||n.className===`Root`;if((r===`before`||r===`after`)&&!o){let e=n._schemaNode,t=e?this.findSchemaLocation(i.view,e):null;if(!t)i.view.components||(i.view.components=[]),i.view.components.push(a);else{let e=r===`before`?t.index:t.index+1;t.containerArr.splice(e,0,a)}}else if(o)i.view.components||(i.view.components=[]),i.view.components.push(a);else{let e=n._schemaNode;if(!e){this.cancelAddNode();return}if(ju(n.className)){let t=Mu(n.className),r=(e.slots||[]).find(e=>e.slotKey===t);r||(e.slots||=[],r={slotKey:t,slotScope:!1,slotSwitch:`1`,components:[]},e.slots.push(r)),r.components||(r.components=[]),r.components.push(a)}else{let t=this.findSchemaLocation(i.view,e);t?t.containerArr.splice(t.index+1,0,a):(i.view.components||(i.view.components=[]),i.view.components.push(a))}}this.cancelAddNode(),this.reloadToken+=1,this.preview=Pu(i),typeof window<`u`&&(window.__cardModel=Bu(i)),this.syncDataToSchema();let s=this.findViewIdByComponentId(this.preview.view,a.componentId);this.selectedNodeId=s||``,this.scheduleCommit()},async copySchema(){if(!this.currentSchema)return;this.syncDataToSchema();let e=``;try{let t={...this.currentSchema};this.rt&&this.rt.rootScope&&(t.data=this.rt.rootScope),e=JSON.stringify(t,(e,t)=>{if(e!==`_schemaNode`)return t},2)}catch{e=`(无法序列化)`}await this.doCopy(e)&&(this.copiedSchema=!0,this.copyTimer&&clearTimeout(this.copyTimer),this.copyTimer=setTimeout(()=>{this.copiedSchema=!1},1500))},async doCopy(e){try{if(navigator.clipboard&&navigator.clipboard.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.select();let n=document.execCommand(`copy`);return document.body.removeChild(t),n}catch{return!1}},async runSync(e){if(!this.syncingRemote&&!(e&&!this.selectedId)){this.syncingRemote=!0,this.syncedRemote=!1,this.syncTarget=e?`selected`:`full`;try{let t=await J(`/__sync`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e?{cardCode:e}:{})});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.message||e.error||`HTTP `+t.status)}let n=await t.json();if(n.needCredentials){this.openLoginModal();return}if(!n.success){let e=(n.failed||[]).map(e=>`${e.id}: ${e.error}`).join(`; `);throw Error(e||`同步失败`)}this.syncedRemote=!0,this.syncTimer&&clearTimeout(this.syncTimer),this.syncTimer=setTimeout(()=>{this.syncedRemote=!1,this.syncTarget=null},1800),await this.onRefresh(),Z(this.syncTarget===`selected`?`已同步当前卡片到本地`:`全量同步完成`,`ok`)}catch(e){console.error(`[同步远程数据失败]`,e),Z(`同步失败:`+(e&&e.message),`err`)}finally{this.syncingRemote=!1}}},syncRemote(){return this.runSync()},syncSelected(){return this.runSync(this.selectedId)},openLoginModal(){this.loginModal=!0,this.loginName=``,this.loginPassword=``,this.loginError=``},closeLoginModal(){this.loginSubmitting||(this.loginModal=!1,this.loginPassword=``,this.loginError=``)},async submitLogin(){if(this.loginSubmitting)return;let e=this.loginName.trim(),t=this.loginPassword;if(!e||!t){this.loginError=`账号与密码均不能为空`;return}this.loginSubmitting=!0,this.loginError=``;try{let n=await J(`/__login-credentials`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({loginName:e,loginPassword:t})}),r=await n.json().catch(()=>({}));if(!n.ok||!r.ok)throw Error(r.message||r.error||`HTTP `+n.status);this.loginModal=!1,this.loginPassword=``,Z(`凭据已保存,正在重试同步…`,`ok`),await this.runSync(this.syncTarget===`selected`?this.selectedId:void 0)}catch(e){this.loginError=`保存失败:`+(e&&e.message)}finally{this.loginSubmitting=!1}},chooseSync(e){if(e===`full`){if(this.syncingRemote)return;this.requestConfirm({title:`全量同步`,message:`即将从远端 FinMall 拉取完整卡片列表,并逐张覆盖本地同名卡片。本地独有卡片会保留,但被覆盖卡片的未保存改动将丢失,且无法撤销。是否继续?`,confirmText:`继续同步`,severity:`warn`,onConfirm:()=>this.syncRemote()});return}!this.preview||!this.selectedId||this.syncingRemote||this.requestConfirm({title:`当前同步`,message:`即将从远端 FinMall 拉取当前卡片「${this.selectedId}」的最新版本并覆盖本地。本地未保存的改动将丢失,且无法撤销。是否继续?`,confirmText:`继续同步`,onConfirm:()=>this.syncSelected()})},chooseRsave(e){if(e===`save`){if(!this.preview||!this.selectedId||this.savingRemote||!this.hasCardSource)return;this.requestConfirm({title:`版本推送`,message:`即将把本地卡片「${this.selectedId}」的当前版本推送并覆盖到远端 FinMall。线上版本会被立即更新,且该操作不可撤销。是否继续?`,confirmText:`继续推送`,severity:`warn`,onConfirm:()=>this.saveToRemote()});return}if(e===`slices`){if(!this.preview||!this.selectedId||this.uploadingSlices)return;this.requestConfirm({title:`切图上传`,message:`即将把当前卡片「${this.selectedId}」引用的本地切图(src/slices/)上传到 FinMall 图片库,并把卡片里的 /slices/ 引用替换为线上地址(@filestore/…)。本地切图文件保留不动;内容未变的切图会直接复用已有线上地址,不重复上传。`+(this.historyDirty?`
|
|
283
283
|
当前卡片有未保存的改动,会先保存到本地再执行,避免被随后的重载丢弃。`:``)+`
|
|
284
|
-
是否继续?`,confirmText:`继续上传`,onConfirm:()=>this.uploadCardSlices()});return}!this.preview||!this.selectedId||!this.hasCardSource||(this.remotePreviewOpen=!0)},requestConfirm({title:e,message:t,confirmText:n,cancelText:r,severity:i,onConfirm:a}){this.confirm={show:!0,title:e,message:t,confirmText:n||`继续`,cancelText:r||`取消`,severity:[`primary`,`warn`,`danger`].includes(i)?i:`primary`,onConfirm:a}},onConfirmDialog(){let e=this.confirm.onConfirm;this.confirm.show=!1,this.confirm.onConfirm=null,typeof e==`function`&&e()},onCancelDialog(){this.confirm.show=!1,this.confirm.onConfirm=null},async saveCard(){if(!this.preview||!this.selectedId)return;this.savingCard=!0;let e=this.selectedId;this.selfSaveId=e,this.selfSaveAt=Date.now();try{try{let e=await this.fetchDiskCard(this.selectedId);if(e&&e.schema){let t=e.schema,n=this.currentSchema;n&&(t.pageId&&(n.pageId=t.pageId),t.name&&(n.name=t.name),t.desc!==void 0&&(n.desc=t.desc))}}catch{}this.syncDataToSchema();let e={schema:this.currentSchema},t=JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t,2),n=await J(`/__card/${encodeURIComponent(this.selectedId)}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:t});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.message||`HTTP `+n.status)}return this.currentCard={schema:e.schema},this.localSchema=this.cloneSchema(this.currentSchema),this.localData=this.cloneData(Xg(this.currentSchema,kP)),this.savedCard=!0,this.refreshValidateBadge(),this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.savedCard=!1},1800),!0}catch(e){return console.error(`[本地保存失败]`,e),this.rt.pushError(`saveCard`,String(e&&e.message)),this.selfSaveId=``,this.selfSaveAt=0,!1}finally{this.savingCard=!1}},async fetchDiskCard(e){let t=await J(`/__card/${encodeURIComponent(e)}`);if(!t.ok)throw Error(`HTTP `+t.status);return t.json()},async fetchImportMeta(e){if(!e){this.cardImportMeta=null;return}try{let t=await J(`/__import-meta/${encodeURIComponent(e)}`);if(!t.ok){this.cardImportMeta=null;return}let n=await t.json().catch(()=>({}));this.cardImportMeta=n&&n.meta||null}catch{this.cardImportMeta=null}},async saveToRemote(){if(!(!this.preview||!this.selectedId||this.savingRemote)){this.savingRemote=!0,this.savedRemote=!1,this.verifiedRemote=null;try{try{let e=await this.fetchDiskCard(this.selectedId);e&&e.schema&&e.schema.pageId&&this.currentSchema&&(this.currentSchema.pageId=e.schema.pageId)}catch{}this.syncDataToSchema(),this.selfSaveId=this.selectedId,this.selfSaveAt=Date.now();let e=await J(`/__save`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({code:this.selectedId,schema:this.currentSchema},(e,t)=>e===`_schemaNode`?void 0:t,2)});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.message||t.error||`HTTP `+e.status)}let t=await e.json();if(!t.ok)throw Error(t.error||`远端保存失败`);if(this.verifiedRemote=t.verified?!!t.verified.ok:null,this.savedRemote=!0,this.verifiedRemote===!1){let e=t.verified||{};e.diff&&e.diff.length?``+e.diff.join(`;`):e.readBackError,console.warn(`[保存校验不符]`,e),Z(`已保存至远端,但读回校验未通过`,`err`)}else Z(`已保存至远端`,`ok`);this.saveRemoteTimer&&clearTimeout(this.saveRemoteTimer),this.saveRemoteTimer=setTimeout(()=>{this.savedRemote=!1,this.verifiedRemote=null},2500)}catch(e){console.error(`[保存至远端失败]`,e),Z(`保存至远端失败:`+(e&&e.message),`err`),this.selfSaveId=``,this.selfSaveAt=0}finally{this.savingRemote=!1}}},async uploadCardSlices(){if(!this.preview||!this.selectedId||this.uploadingSlices)return;let e=this.selectedId;this.uploadingSlices=!0;try{if(this.historyDirty&&!await this.saveCard())throw Error(`本地保存失败,已中止切图上传`);this.selfSaveId=e,this.selfSaveAt=Date.now();let t=await J(`/__slice-upload`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({cardId:e})});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.message||e.error||`HTTP `+t.status)}let n=await t.json();if(n.needCredentials){this.openLoginModal();return}if(this.selfSaveAt=Date.now(),!n.success){let e=(n.failed||[]).map(e=>`${e.name}: ${e.error}`).join(`; `);throw Error(e||`切图上传失败`)}await this.onRefresh();let r=(n.rewritten||[]).reduce((e,t)=>e+t.count,0);n.referenced?Z(`切图上传完成:新上传 ${n.uploaded.length} 张、复用 ${n.skipped.length} 张,替换引用 ${r} 处`,`ok`):Z(`当前卡片没有引用本地切图,无需上传`,`ok`),n.dangling&&n.dangling.length&&Z(`有 ${n.dangling.length} 处引用的切图在 src/slices 下不存在:${n.dangling.join(`、`)}`,`err`)}catch(e){console.error(`[切图上传失败]`,e),Z(`切图上传失败:`+(e&&e.message),`err`),this.selfSaveId=``,this.selfSaveAt=0}finally{this.uploadingSlices=!1}},async syncCardMeta(e){let t=await this.fetchCardMeta(e);if(!t)return;let n=this.cardList.findIndex(t=>t.id===e);n>=0?this.cardList.splice(n,1,t):this.cardList.push(t),this.cardCount=this.cardList.length},async fetchCardMeta(e){try{let t=await J(`/__card/`+encodeURIComponent(e)+`/meta`);return t.ok?await t.json():null}catch(e){return console.error(`[读取卡片列表项失败]`,e),null}},async fetchCardList(){try{let e=await J(`/__cards`);if(!e.ok)return;let t=await e.json(),n=t&&t.cards||[];this.cardList=n,this.cardCount=n.length}catch(e){console.error(`[加载卡片列表失败]`,e)}},async onGalleryDelete(e){try{let t=await J(`/__card/${encodeURIComponent(e)}`,{method:`DELETE`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n&&(n.message||n.error)||`HTTP ${t.status}`);if(Z(`已删除本地卡片 ${e}`,`ok`),this.$refs.chatPanel?.discardCard(e),await this.fetchCardList(),this.selectedId===e){let e=this.cardList[0];e?await this.loadCard(e.id):(this.selectedId=``,this.currentSchema=null,this.preview=null)}}catch(e){Z(`删除卡片失败:${e.message}`,`err`)}},async onNewCardCreated(e){this.cardDialog.visible=!1,Z(`已创建空白卡片 ${e}`,`ok`),await this.fetchCardList(),await this.loadCard(e)},async onRefresh(){let e=this.selectedId;if(!(!e||this.refreshing)){this.refreshing=!0;try{await this.loadCard(e),await this.syncCardMeta(e);let t=this.cardList.find(t=>t.id===e);t&&this.currentSchema&&this.currentSchema.name&&(t.name=this.currentSchema.name)}catch(e){console.error(`[刷新卡片失败]`,e),this.rt.pushError(`refresh`,String(e&&e.message))}finally{this.refreshing=!1}}},onChatTurnFinished(e){if(this.chatProgress=null,this.aiChatOpen)return;let t=e&&e.steps||0,n=jD(e&&e.ms||0),r=MD(e&&e.finishedAt||Date.now());if(e&&e.status===`error`){Z(`AI 助手本轮报错(${r} · ${t} 步 / ${n}),展开面板查看原因`,`err`);return}if(e&&e.status===`aborted`){Z(`AI 助手本轮已终止(${r} · ${t} 步):展开面板可「从中断处继续」`,`ok`);return}Z(`AI 助手已完成本轮(${r} · ${t} 步 / ${n})`,`ok`)},async onChatRollbackTurn(e){let t=e&&e.cardId||this.selectedId;if(!t||this.loadingCard)return;if(t!==this.selectedId){Z(`请先切换到那张卡片再回滚`,`err`);return}let n=[];try{let e=await J(`/__history/${encodeURIComponent(t)}`);if(!e.ok)throw Error(`HTTP ${e.status}`);let r=await e.json().catch(()=>null);n=r&&r.snapshots||[]}catch(e){Z(`读取历史快照失败:${e.message||e}`,`err`);return}let r=Number(e&&e.ts)||0,i=r?n.filter(e=>Number(e.ts)>=r-2e3):[],a=i.length?i[0]:n[n.length-1];if(!a||!a.schema){Z(`没找到本轮之前的历史快照(可能已被 30 张上限裁掉,或本轮没写入过卡片)`,`err`);return}let o=new Date(Number(a.ts)||Date.now()).toLocaleString(`zh-CN`,{hour12:!1});this.requestConfirm({title:`回滚到 AI 动手之前`,message:`将把卡片「${this.selectedCardName||t}」恢复到 ${o} 的版本,本轮及其后的 ${i.length||1} 张快照都会被撤销。回滚只改当前编辑态,可用 Ctrl+Z 撤回;确认无误后仍需点顶栏「保存到本地」才写盘。`,confirmText:`回滚`,severity:`warn`,onConfirm:()=>this.applyTurnRollback(a)})},applyTurnRollback(e){!this.currentSchema||!e||(this.past.push({schema:this.cloneSchema(this.currentSchema)}),this.past.length>30&&this.past.shift(),this.future=[],this.baseline={schema:this.cloneSchema(e.schema)},this.applySchemaSnapshot({schema:e.schema,data:e.data}),Z(`已回滚到本轮之前的版本(未落盘,可撤销;确认后点「保存到本地」)`,`ok`))},onCardsChanged(e){let t=e&&e.file||``,n=e&&e.type||`change`;if(n===`rename`&&e.oldId&&e.id&&e.oldId!==e.id)return this.applyCardRename(e.oldId,e.id);if(/\.history[\\/]/.test(t)||/data\.json$/i.test(t))return;let r=t.match(/src[\\/]cards[\\/]([^\\/]+)[\\/]/),i=r?r[1]:null;this._ccIds||=new Set,this._ccTypes||={},i&&(this._ccIds.add(i),this._ccTypes[i]=n),!this._ccTimer&&(this._ccTimer=setTimeout(async()=>{this._ccTimer=null;let e=this._ccIds,t=this._ccTypes;if(this._ccIds=new Set,this._ccTypes={},!e.size)return;let n=Array.from(e),r=n[n.length-1];if(e.size===1&&r&&r===this.selectedId){if(this.selfSaveId===r&&Date.now()-this.selfSaveAt<AP){this.selfSaveId=``,this.selfSaveAt=0;return}if(this.historyDirty)this.promptExternalReload(r);else{let e=this.currentSchema&&this.currentSchema.name||r;this.showExternalReloadNote(this.chatBusy?`AI 助手已写入卡片「${e}」,预览已自动刷新`:`卡片「${e}」已在编辑器外被修改,已自动重新载入预览`),this.loadCard(this.selectedId)}return}if(e.size>1){await this.fetchCardList();return}if((t[r]||`change`)===`unlink`){let e=this.cardList.findIndex(e=>e.id===r);e>=0&&(this.cardList.splice(e,1),this.cardCount=this.cardList.length);return}let i=await this.fetchCardMeta(r);if(!i){await this.fetchCardList();return}let a=this.cardList.findIndex(e=>e.id===r);a>=0?this.cardList.splice(a,1,i):this.cardList.push(i),this.cardCount=this.cardList.length},120))},promptExternalReload(e){if(this.confirm.show)return;let t=this.currentSchema&&this.currentSchema.name||e;this.requestConfirm({title:`卡片已在编辑器外被修改`,message:`卡片「${t}」的 schema / data 在编辑器外发生了变更(例如 IDE 或其他工具覆盖了文件)。\n当前编辑器存在未保存的改动,是否放弃本地未保存改动并重新载入磁盘版本?`,confirmText:`重新载入`,cancelText:`保留我的改动`,onConfirm:()=>this.loadCard(e)})},showExternalReloadNote(e){this.externalReloadNote=e,this.externalReloadTimer&&clearTimeout(this.externalReloadTimer),this.externalReloadTimer=setTimeout(()=>{this.externalReloadNote=``,this.externalReloadTimer=null},3500)}}},RP={class:`app__bar`},zP={class:`app__logo`},BP=[`src`],VP={class:`app__logo-version`},HP={class:`csel-combo`},UP=[`disabled`],WP=[`disabled`],GP=[`title`],KP={class:`app__badge-text`},qP={class:`app__bar-actions`},JP={class:`app__op-group`,role:`group`,"aria-label":`编辑历史与本地操作`},YP=[`disabled`],XP=[`disabled`],ZP=[`disabled`,`title`],QP=[`disabled`],$P=[`disabled`],eF={key:0,class:`app__icon app__icon--spin`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},tF={key:1,class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},nF={key:2,class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},rF={key:3,class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},iF={class:`app__remote-pop dd__menu`,role:`menu`},aF=[`title`,`onClick`],oF=[`title`,`onClick`],sF=[`onClick`],cF=[`onClick`],lF=[`title`,`onClick`],uF=[`title`,`aria-pressed`],dF=[`aria-checked`,`title`],fF={class:`theme-toggle__track`},pF={class:`theme-toggle__thumb`},mF={key:0,class:`theme-toggle__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},hF={key:1,class:`theme-toggle__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},gF={class:`app__dev-svc`},_F=[`title`],vF={class:`app__dev-svc-head`},yF={class:`app__dev-svc-body`},bF={class:`app__dev-svc-row`},xF={class:`app__dev-svc-row app__dev-svc-row--col`},SF={class:`app__dev-svc-row app__dev-svc-row--col`},CF={key:0,class:`app__dev-svc-hint`},wF={class:`app__dev-svc-actions`},TF={style:{display:`none`}},EF=[`title`,`aria-expanded`],DF={key:0,class:`app__nosvc-banner`},OF={key:1,class:`app__nosvc-banner app__nosvc-banner--disconnected`},kF={key:2,class:`app__nosvc-banner app__extreload-banner`},AF={class:`app__stage`,ref:`stageEl`},jF={class:`phone__scaler`},MF=[`title`],NF={class:`canvas-bar__txt`},PF={class:`canvas-bar__chip`,title:`画布宽度预设(高度随列高自适应)`},FF={class:`canvas-bar__txt`},IF={class:`canvas-bar__size`,title:`画布实际尺寸(宽 × 高,高度随窗口自适应)`},LF=[`disabled`],RF=[`data-card-ready`],zF={class:`workside`},BF={class:`workside__cols`,ref:`colsEl`},VF={class:`login-modal modal-card`,role:`dialog`,"aria-modal":`true`},HF={class:`login-modal__row`},UF=[`disabled`],WF={class:`login-modal__row`},GF=[`disabled`],KF={key:0,class:`login-modal__error`},qF={class:`login-modal__actions`},JF=[`disabled`],YF=[`disabled`];function XF(e,t,n,r,i,a){let o=L(`CardSelect`),s=L(`Dropdown`),c=L(`Switch`),l=L(`ChatPanel`),u=L(`RenderTree`),d=L(`SelectionOverlay`),f=L(`HoverGuides`),p=L(`AlertCardLayer`),m=L(`DeviceOverlay`),h=L(`PickerOverlay`),g=L(`DatePickerOverlay`),_=L(`DebugPanel`),v=L(`ApiCallPanel`),y=L(`RemotePreview`),b=L(`ComponentPalette`),x=L(`ConfirmDialog`),S=L(`CardGallery`),C=L(`NewCardDialog`),w=L(`AppToast`),T=L(`ImageLightbox`);return B(),V(`div`,{class:j([`app`,{"app--chrome-off":i.chromeOff}]),style:A({"--preview-width":a.previewWidth+`px`,"--api-panel-width":a.apiPanelWidth+`px`,"--debug-min":a.debugMinWidth+`px`})},[I(U(`header`,RP,[U(`strong`,zP,[U(`img`,{class:`app__logo-icon`,src:i.logoUrl,alt:``},null,8,BP),t[41]||=G(` CardBuddy `,-1),U(`span`,VP,`v`+M(i.appVersion),1)]),U(`div`,HP,[W(o,{class:`csel--combo`,value:i.selectedId,options:i.cardList,onChange:a.onSelect},null,8,[`value`,`options`,`onChange`]),U(`button`,{class:`csel-combo__btn`,type:`button`,disabled:!i.selectedId,onClick:t[0]||=(...e)=>a.openCardFolder&&a.openCardFolder(...e),title:`在文件管理器中打开当前卡片所在文件夹`},[...t[42]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`path`,{d:`M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z`}),U(`path`,{d:`M3 9h18`})],-1)]],8,UP)]),K(` 卡片网格预览:图标按钮,打开本地全部卡片的缩略图墙,点击任一张载入工作台 `),U(`button`,{class:`app__btn app__btn--icon`,type:`button`,disabled:!i.cardList.length,onClick:t[1]||=(...e)=>a.openGallery&&a.openGallery(...e),title:`卡片网格预览`},[...t[43]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-grid`})],-1)]],8,WP),K(` 新增空白卡片:紧邻网格预览的图标按钮;弹窗收 ID(必填、本地重名前置拦截)+ 描述(选填),创建成功切换到新卡 `),U(`button`,{class:`app__btn app__btn--icon`,type:`button`,onClick:t[2]||=(...e)=>a.openNewCard&&a.openNewCard(...e),title:`新增空白卡片`},[...t[44]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-folder-plus`})],-1)]]),I(U(`div`,{ref:`validateBadgeEl`,class:j([`app__badge`,`app__badge--`+i.validateBadge.state]),title:a.badgeTitle},[t[45]||=U(`span`,{class:`app__badge-dot`},null,-1),U(`span`,KP,M(a.badgeText),1)],10,GP),[[Sc,!i.chromeOff]]),U(`div`,qP,[U(`div`,JP,[K(` 撤销 / 重做:图标 + 文案;无可回退/重做版本时置灰 `),U(`button`,{class:`app__btn app__btn--hist`,type:`button`,disabled:!i.preview||!a.canUndo,onClick:t[3]||=(...e)=>a.undo&&a.undo(...e),title:`后退一步(撤销)`},[...t[46]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-undo`})],-1),U(`span`,null,`撤销`,-1)]],8,YP),U(`button`,{class:`app__btn app__btn--hist`,type:`button`,disabled:!i.preview||!a.canRedo,onClick:t[4]||=(...e)=>a.redo&&a.redo(...e),title:`前进一步(重做)`},[...t[47]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-redo`})],-1),U(`span`,null,`重做`,-1)]],8,XP),K(` 保存到本地:当前显示版本(撤销/重做导航到的历史版本,或编辑后未本地保存的版本)
|
|
284
|
+
是否继续?`,confirmText:`继续上传`,onConfirm:()=>this.uploadCardSlices()});return}!this.preview||!this.selectedId||!this.hasCardSource||(this.remotePreviewOpen=!0)},requestConfirm({title:e,message:t,confirmText:n,cancelText:r,severity:i,onConfirm:a}){this.confirm={show:!0,title:e,message:t,confirmText:n||`继续`,cancelText:r||`取消`,severity:[`primary`,`warn`,`danger`].includes(i)?i:`primary`,onConfirm:a}},onConfirmDialog(){let e=this.confirm.onConfirm;this.confirm.show=!1,this.confirm.onConfirm=null,typeof e==`function`&&e()},onCancelDialog(){this.confirm.show=!1,this.confirm.onConfirm=null},async saveCard(){if(!this.preview||!this.selectedId)return;this.savingCard=!0;let e=this.selectedId;this.selfSaveId=e,this.selfSaveAt=Date.now();try{try{let e=await this.fetchDiskCard(this.selectedId);if(e&&e.schema){let t=e.schema,n=this.currentSchema;n&&(t.pageId&&(n.pageId=t.pageId),t.name&&(n.name=t.name),t.desc!==void 0&&(n.desc=t.desc))}}catch{}this.syncDataToSchema();let e={schema:this.currentSchema},t=JSON.stringify(e,(e,t)=>e===`_schemaNode`?void 0:t,2),n=await J(`/__card/${encodeURIComponent(this.selectedId)}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:t});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.message||`HTTP `+n.status)}return this.currentCard={schema:e.schema},this.localSchema=this.cloneSchema(this.currentSchema),this.localData=this.cloneData(Xg(this.currentSchema,PP)),this.savedCard=!0,this.refreshValidateBadge(),this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.savedCard=!1},1800),!0}catch(e){return console.error(`[本地保存失败]`,e),this.rt.pushError(`saveCard`,String(e&&e.message)),this.selfSaveId=``,this.selfSaveAt=0,!1}finally{this.savingCard=!1}},async fetchDiskCard(e){let t=await J(`/__card/${encodeURIComponent(e)}`);if(!t.ok)throw Error(`HTTP `+t.status);return t.json()},async fetchImportMeta(e){if(!e){this.cardImportMeta=null;return}try{let t=await J(`/__import-meta/${encodeURIComponent(e)}`);if(!t.ok){this.cardImportMeta=null;return}let n=await t.json().catch(()=>({}));this.cardImportMeta=n&&n.meta||null}catch{this.cardImportMeta=null}},async saveToRemote(){if(!(!this.preview||!this.selectedId||this.savingRemote)){this.savingRemote=!0,this.savedRemote=!1,this.verifiedRemote=null;try{try{let e=await this.fetchDiskCard(this.selectedId);e&&e.schema&&e.schema.pageId&&this.currentSchema&&(this.currentSchema.pageId=e.schema.pageId)}catch{}this.syncDataToSchema(),this.selfSaveId=this.selectedId,this.selfSaveAt=Date.now();let e=await J(`/__save`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({code:this.selectedId,schema:this.currentSchema},(e,t)=>e===`_schemaNode`?void 0:t,2)});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.message||t.error||`HTTP `+e.status)}let t=await e.json();if(!t.ok)throw Error(t.error||`远端保存失败`);if(this.verifiedRemote=t.verified?!!t.verified.ok:null,this.savedRemote=!0,this.verifiedRemote===!1){let e=t.verified||{};e.diff&&e.diff.length?``+e.diff.join(`;`):e.readBackError,console.warn(`[保存校验不符]`,e),Z(`已保存至远端,但读回校验未通过`,`err`)}else Z(`已保存至远端`,`ok`);this.saveRemoteTimer&&clearTimeout(this.saveRemoteTimer),this.saveRemoteTimer=setTimeout(()=>{this.savedRemote=!1,this.verifiedRemote=null},2500)}catch(e){console.error(`[保存至远端失败]`,e),Z(`保存至远端失败:`+(e&&e.message),`err`),this.selfSaveId=``,this.selfSaveAt=0}finally{this.savingRemote=!1}}},async uploadCardSlices(){if(!this.preview||!this.selectedId||this.uploadingSlices)return;let e=this.selectedId;this.uploadingSlices=!0;try{if(this.historyDirty&&!await this.saveCard())throw Error(`本地保存失败,已中止切图上传`);this.selfSaveId=e,this.selfSaveAt=Date.now();let t=await J(`/__slice-upload`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({cardId:e})});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.message||e.error||`HTTP `+t.status)}let n=await t.json();if(n.needCredentials){this.openLoginModal();return}if(this.selfSaveAt=Date.now(),!n.success){let e=(n.failed||[]).map(e=>`${e.name}: ${e.error}`).join(`; `);throw Error(e||`切图上传失败`)}await this.onRefresh();let r=(n.rewritten||[]).reduce((e,t)=>e+t.count,0);n.referenced?Z(`切图上传完成:新上传 ${n.uploaded.length} 张、复用 ${n.skipped.length} 张,替换引用 ${r} 处`,`ok`):Z(`当前卡片没有引用本地切图,无需上传`,`ok`),n.dangling&&n.dangling.length&&Z(`有 ${n.dangling.length} 处引用的切图在 src/slices 下不存在:${n.dangling.join(`、`)}`,`err`)}catch(e){console.error(`[切图上传失败]`,e),Z(`切图上传失败:`+(e&&e.message),`err`),this.selfSaveId=``,this.selfSaveAt=0}finally{this.uploadingSlices=!1}},async syncCardMeta(e){let t=await this.fetchCardMeta(e);if(!t)return;let n=this.cardList.findIndex(t=>t.id===e);n>=0?this.cardList.splice(n,1,t):this.cardList.push(t),this.cardCount=this.cardList.length},async fetchCardMeta(e){try{let t=await J(`/__card/`+encodeURIComponent(e)+`/meta`);return t.ok?await t.json():null}catch(e){return console.error(`[读取卡片列表项失败]`,e),null}},async fetchCardList(){try{let e=await J(`/__cards`);if(!e.ok)return;let t=await e.json(),n=t&&t.cards||[];this.cardList=n,this.cardCount=n.length}catch(e){console.error(`[加载卡片列表失败]`,e)}},async onGalleryDelete(e){try{let t=await J(`/__card/${encodeURIComponent(e)}`,{method:`DELETE`}),n=await t.json().catch(()=>null);if(!t.ok)throw Error(n&&(n.message||n.error)||`HTTP ${t.status}`);if(Z(`已删除本地卡片 ${e}`,`ok`),this.$refs.chatPanel?.discardCard(e),await this.fetchCardList(),this.selectedId===e){let e=this.cardList[0];e?await this.loadCard(e.id):(this.selectedId=``,this.currentSchema=null,this.preview=null)}}catch(e){Z(`删除卡片失败:${e.message}`,`err`)}},async onNewCardCreated(e){this.cardDialog.visible=!1,Z(`已创建空白卡片 ${e}`,`ok`),await this.fetchCardList(),await this.loadCard(e)},async onRefresh(){let e=this.selectedId;if(!(!e||this.refreshing)){this.refreshing=!0;try{await this.loadCard(e),await this.syncCardMeta(e);let t=this.cardList.find(t=>t.id===e);t&&this.currentSchema&&this.currentSchema.name&&(t.name=this.currentSchema.name)}catch(e){console.error(`[刷新卡片失败]`,e),this.rt.pushError(`refresh`,String(e&&e.message))}finally{this.refreshing=!1}}},onChatTurnFinished(e){if(this.chatProgress=null,this.aiChatOpen)return;let t=e&&e.steps||0,n=jD(e&&e.ms||0),r=MD(e&&e.finishedAt||Date.now());if(e&&e.status===`error`){Z(`AI 助手本轮报错(${r} · ${t} 步 / ${n}),展开面板查看原因`,`err`);return}if(e&&e.status===`aborted`){Z(`AI 助手本轮已终止(${r} · ${t} 步):展开面板可「从中断处继续」`,`ok`);return}Z(`AI 助手已完成本轮(${r} · ${t} 步 / ${n})`,`ok`)},async onChatRollbackTurn(e){let t=e&&e.cardId||this.selectedId;if(!t||this.loadingCard)return;if(t!==this.selectedId){Z(`请先切换到那张卡片再回滚`,`err`);return}let n=[];try{let e=await J(`/__history/${encodeURIComponent(t)}`);if(!e.ok)throw Error(`HTTP ${e.status}`);let r=await e.json().catch(()=>null);n=r&&r.snapshots||[]}catch(e){Z(`读取历史快照失败:${e.message||e}`,`err`);return}let r=Number(e&&e.ts)||0,i=r?n.filter(e=>Number(e.ts)>=r-2e3):[],a=i.length?i[0]:n[n.length-1];if(!a||!a.schema){Z(`没找到本轮之前的历史快照(可能已被 30 张上限裁掉,或本轮没写入过卡片)`,`err`);return}let o=new Date(Number(a.ts)||Date.now()).toLocaleString(`zh-CN`,{hour12:!1});this.requestConfirm({title:`回滚到 AI 动手之前`,message:`将把卡片「${this.selectedCardName||t}」恢复到 ${o} 的版本,本轮及其后的 ${i.length||1} 张快照都会被撤销。回滚只改当前编辑态,可用 Ctrl+Z 撤回;确认无误后仍需点顶栏「保存到本地」才写盘。`,confirmText:`回滚`,severity:`warn`,onConfirm:()=>this.applyTurnRollback(a)})},applyTurnRollback(e){!this.currentSchema||!e||(this.past.push({schema:this.cloneSchema(this.currentSchema)}),this.past.length>30&&this.past.shift(),this.future=[],this.baseline={schema:this.cloneSchema(e.schema)},this.applySchemaSnapshot({schema:e.schema,data:e.data}),Z(`已回滚到本轮之前的版本(未落盘,可撤销;确认后点「保存到本地」)`,`ok`))},onCardsChanged(e){let t=e&&e.file||``,n=e&&e.type||`change`;if(n===`rename`&&e.oldId&&e.id&&e.oldId!==e.id)return this.applyCardRename(e.oldId,e.id);if(/\.history[\\/]/.test(t)||/data\.json$/i.test(t))return;let r=t.match(/src[\\/]cards[\\/]([^\\/]+)[\\/]/),i=r?r[1]:null;this._ccIds||=new Set,this._ccTypes||={},i&&(this._ccIds.add(i),this._ccTypes[i]=n),!this._ccTimer&&(this._ccTimer=setTimeout(async()=>{this._ccTimer=null;let e=this._ccIds,t=this._ccTypes;if(this._ccIds=new Set,this._ccTypes={},!e.size)return;let n=Array.from(e),r=n[n.length-1];if(e.size===1&&r&&r===this.selectedId){if(this.selfSaveId===r&&Date.now()-this.selfSaveAt<FP){this.selfSaveId=``,this.selfSaveAt=0;return}if(this.historyDirty)this.promptExternalReload(r);else{let e=this.currentSchema&&this.currentSchema.name||r;this.showExternalReloadNote(this.chatBusy?`AI 助手已写入卡片「${e}」,预览已自动刷新`:`卡片「${e}」已在编辑器外被修改,已自动重新载入预览`),this.loadCard(this.selectedId)}return}if(e.size>1){await this.fetchCardList();return}if((t[r]||`change`)===`unlink`){let e=this.cardList.findIndex(e=>e.id===r);e>=0&&(this.cardList.splice(e,1),this.cardCount=this.cardList.length);return}let i=await this.fetchCardMeta(r);if(!i){await this.fetchCardList();return}let a=this.cardList.findIndex(e=>e.id===r);a>=0?this.cardList.splice(a,1,i):this.cardList.push(i),this.cardCount=this.cardList.length},120))},promptExternalReload(e){if(this.confirm.show)return;let t=this.currentSchema&&this.currentSchema.name||e;this.requestConfirm({title:`卡片已在编辑器外被修改`,message:`卡片「${t}」的 schema / data 在编辑器外发生了变更(例如 IDE 或其他工具覆盖了文件)。\n当前编辑器存在未保存的改动,是否放弃本地未保存改动并重新载入磁盘版本?`,confirmText:`重新载入`,cancelText:`保留我的改动`,onConfirm:()=>this.loadCard(e)})},showExternalReloadNote(e){this.externalReloadNote=e,this.externalReloadTimer&&clearTimeout(this.externalReloadTimer),this.externalReloadTimer=setTimeout(()=>{this.externalReloadNote=``,this.externalReloadTimer=null},3500)}}},UP={class:`app__bar`},WP={class:`app__logo`},GP=[`src`],KP={class:`app__logo-version`},qP={class:`csel-combo`},JP=[`disabled`],YP=[`disabled`],XP=[`title`],ZP={class:`app__badge-text`},QP={class:`app__bar-actions`},$P={class:`app__op-group`,role:`group`,"aria-label":`编辑历史与本地操作`},eF=[`disabled`],tF=[`disabled`],nF=[`disabled`,`title`],rF=[`disabled`],iF=[`disabled`],aF={key:0,class:`app__icon app__icon--spin`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},oF={key:1,class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},sF={key:2,class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},cF={key:3,class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},lF={class:`app__remote-pop dd__menu`,role:`menu`},uF=[`title`,`onClick`],dF=[`title`,`onClick`],fF=[`onClick`],pF=[`onClick`],mF=[`title`,`onClick`],hF=[`title`,`aria-pressed`],gF=[`aria-checked`,`title`],_F={class:`theme-toggle__track`},vF={class:`theme-toggle__thumb`},yF={key:0,class:`theme-toggle__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},bF={key:1,class:`theme-toggle__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},xF={class:`app__dev-svc`},SF=[`title`],CF={class:`app__dev-svc-head`},wF={class:`app__dev-svc-body`},TF={class:`app__dev-svc-row`},EF={class:`app__dev-svc-row app__dev-svc-row--col`},DF={class:`app__dev-svc-row app__dev-svc-row--col`},OF={key:0,class:`app__dev-svc-hint`},kF={class:`app__dev-svc-actions`},AF={style:{display:`none`}},jF=[`title`,`aria-expanded`],MF={key:0,class:`app__nosvc-banner`},NF={key:1,class:`app__nosvc-banner app__nosvc-banner--disconnected`},PF={key:2,class:`app__nosvc-banner app__extreload-banner`},FF={class:`app__stage`,ref:`stageEl`},IF={class:`phone__scaler`},LF=[`title`],RF={class:`canvas-bar__txt`},zF={class:`canvas-bar__chip`,title:`画布宽度预设(高度随列高自适应)`},BF={class:`canvas-bar__txt`},VF={class:`canvas-bar__size`,title:`画布实际尺寸(宽 × 高,高度随窗口自适应)`},HF=[`disabled`],UF=[`data-card-ready`],WF={class:`workside`},GF={class:`workside__cols`,ref:`colsEl`},KF={class:`login-modal modal-card`,role:`dialog`,"aria-modal":`true`},qF={class:`login-modal__row`},JF=[`disabled`],YF={class:`login-modal__row`},XF=[`disabled`],ZF={key:0,class:`login-modal__error`},QF={class:`login-modal__actions`},$F=[`disabled`],eI=[`disabled`];function tI(e,t,n,r,i,a){let o=L(`CardSelect`),s=L(`Dropdown`),c=L(`Switch`),l=L(`ChatPanel`),u=L(`RenderTree`),d=L(`SelectionOverlay`),f=L(`HoverGuides`),p=L(`AlertCardLayer`),m=L(`DeviceOverlay`),h=L(`PickerOverlay`),g=L(`DatePickerOverlay`),_=L(`DebugPanel`),v=L(`ApiCallPanel`),y=L(`RemotePreview`),b=L(`ComponentPalette`),x=L(`ConfirmDialog`),S=L(`CardGallery`),C=L(`NewCardDialog`),w=L(`AppToast`),T=L(`ImageLightbox`);return B(),V(`div`,{class:j([`app`,{"app--chrome-off":i.chromeOff}]),style:A({"--preview-width":a.previewWidth+`px`,"--api-panel-width":a.apiPanelWidth+`px`,"--debug-min":a.debugMinWidth+`px`})},[I(U(`header`,UP,[U(`strong`,WP,[U(`img`,{class:`app__logo-icon`,src:i.logoUrl,alt:``},null,8,GP),t[41]||=G(` CardBuddy `,-1),U(`span`,KP,`v`+M(i.appVersion),1)]),U(`div`,qP,[W(o,{class:`csel--combo`,value:i.selectedId,options:i.cardList,onChange:a.onSelect},null,8,[`value`,`options`,`onChange`]),U(`button`,{class:`csel-combo__btn`,type:`button`,disabled:!i.selectedId,onClick:t[0]||=(...e)=>a.openCardFolder&&a.openCardFolder(...e),title:`在文件管理器中打开当前卡片所在文件夹`},[...t[42]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`path`,{d:`M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z`}),U(`path`,{d:`M3 9h18`})],-1)]],8,JP)]),K(` 卡片网格预览:图标按钮,打开本地全部卡片的缩略图墙,点击任一张载入工作台 `),U(`button`,{class:`app__btn app__btn--icon`,type:`button`,disabled:!i.cardList.length,onClick:t[1]||=(...e)=>a.openGallery&&a.openGallery(...e),title:`卡片网格预览`},[...t[43]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-grid`})],-1)]],8,YP),K(` 新增空白卡片:紧邻网格预览的图标按钮;弹窗收 ID(必填、本地重名前置拦截)+ 描述(选填),创建成功切换到新卡 `),U(`button`,{class:`app__btn app__btn--icon`,type:`button`,onClick:t[2]||=(...e)=>a.openNewCard&&a.openNewCard(...e),title:`新增空白卡片`},[...t[44]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-folder-plus`})],-1)]]),I(U(`div`,{ref:`validateBadgeEl`,class:j([`app__badge`,`app__badge--`+i.validateBadge.state]),title:a.badgeTitle},[t[45]||=U(`span`,{class:`app__badge-dot`},null,-1),U(`span`,ZP,M(a.badgeText),1)],10,XP),[[Sc,!i.chromeOff]]),U(`div`,QP,[U(`div`,$P,[K(` 撤销 / 重做:图标 + 文案;无可回退/重做版本时置灰 `),U(`button`,{class:`app__btn app__btn--hist`,type:`button`,disabled:!i.preview||!a.canUndo,onClick:t[3]||=(...e)=>a.undo&&a.undo(...e),title:`后退一步(撤销)`},[...t[46]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-undo`})],-1),U(`span`,null,`撤销`,-1)]],8,eF),U(`button`,{class:`app__btn app__btn--hist`,type:`button`,disabled:!i.preview||!a.canRedo,onClick:t[4]||=(...e)=>a.redo&&a.redo(...e),title:`前进一步(重做)`},[...t[47]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-redo`})],-1),U(`span`,null,`重做`,-1)]],8,tF),K(` 保存到本地:当前显示版本(撤销/重做导航到的历史版本,或编辑后未本地保存的版本)
|
|
285
285
|
与本地磁盘版本不一致时高亮可用;一致时置灰。点击把当前版本真正写回磁盘,
|
|
286
|
-
使下一次重新打开加载的是这个「真实版本」,而非任意历史记录。 `),U(`button`,{class:j([`app__btn app__btn--history-save`,{"is-dirty":a.historyDirty}]),type:`button`,disabled:!i.preview||!a.historyDirty||i.savingCard||i.loadingCard,onClick:t[5]||=(...e)=>a.applyHistoryToLocal&&a.applyHistoryToLocal(...e),title:a.historyDirty?`当前版本与本地不一致,点击将该版本保存到本地`:`当前版本已与本地一致`},[...t[48]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-save`})],-1),U(`span`,null,`保存`,-1)]],10,
|
|
286
|
+
使下一次重新打开加载的是这个「真实版本」,而非任意历史记录。 `),U(`button`,{class:j([`app__btn app__btn--history-save`,{"is-dirty":a.historyDirty}]),type:`button`,disabled:!i.preview||!a.historyDirty||i.savingCard||i.loadingCard,onClick:t[5]||=(...e)=>a.applyHistoryToLocal&&a.applyHistoryToLocal(...e),title:a.historyDirty?`当前版本与本地不一致,点击将该版本保存到本地`:`当前版本已与本地一致`},[...t[48]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-save`})],-1),U(`span`,null,`保存`,-1)]],10,nF),U(`button`,{class:`app__btn app__btn--op`,disabled:!i.preview,onClick:t[6]||=(...e)=>a.copySchema&&a.copySchema(...e),title:`复制 schema(含变量 mock 编辑后的数据)`},[t[49]||=U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-copy`})],-1),U(`span`,null,M(i.copiedSchema?`已复制 ✓`:`复制`),1)],8,rF)]),K(` 远端:合并「远端保存 / 远端预览 / 切图上传 / 全量同步 / 选中卡片同步」为一个分组,组名「远端」,云图标 `),W(s,{class:`app__remote-menu`,size:`md`,placement:`bottom-end`,disabled:i.savingRemote||i.syncingRemote||i.uploadingSlices,title:i.savingRemote?`正在保存至远端…`:i.syncingRemote?`同步中…`:i.uploadingSlices?`正在上传切图…`:`远端操作:保存到 FinMall / 真机预览 / 切图上传 / 全量或选中卡片同步`,"data-testid":`remote-group`},{trigger:Lr(({open:e})=>[U(`button`,{type:`button`,class:j([`app__btn app__btn--remote`,{"app__btn--warn":i.savedRemote&&i.verifiedRemote===!1,"app__remote-trigger--active":e,"is-processing":i.savingRemote||i.syncingRemote||i.uploadingSlices}]),disabled:i.savingRemote||i.syncingRemote||i.uploadingSlices},[i.savingRemote||i.syncingRemote||i.uploadingSlices?(B(),V(`svg`,aF,[...t[50]||=[U(`use`,{href:`#icon-loading`},null,-1)]])):i.savedRemote&&i.verifiedRemote!==!1?(B(),V(`svg`,oF,[...t[51]||=[U(`use`,{href:`#icon-cloud-check`},null,-1)]])):i.savedRemote&&i.verifiedRemote===!1?(B(),V(`svg`,sF,[...t[52]||=[U(`use`,{href:`#icon-cloud-alert`},null,-1)]])):(B(),V(`svg`,cF,[...t[53]||=[U(`use`,{href:`#icon-cloud`},null,-1)]])),t[55]||=U(`span`,null,`远端`,-1),(B(),V(`svg`,{class:j([`app__icon app__icon--chev`,{"app__icon--chev--open":e}]),viewBox:`0 0 16 16`,width:`12`,height:`12`,"aria-hidden":`true`},[...t[54]||=[U(`use`,{href:`#icon-chevron`},null,-1)]],2))],10,iF)]),default:Lr(({close:e})=>[U(`ul`,lF,[U(`li`,{class:j([`app__remote-item app__remote-item--save`,{"is-disabled":!i.preview||!i.selectedId||i.savingRemote||!a.hasCardSource}]),title:a.hasCardSource?`版本推送:把本地卡片版本覆盖到远端 FinMall`:`该卡未经「同步远程」导入,无远端来源信息,无法推送版本`,"data-testid":`save-remote`,role:`menuitem`,onClick:t=>{a.chooseRsave(`save`),e()}},[...t[56]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-upload-cloud`})],-1),U(`span`,null,`版本推送`,-1)]],10,uF),U(`li`,{class:j([`app__remote-item`,{"is-disabled":!i.preview||!i.selectedId||!a.hasCardSource}]),title:a.hasCardSource?`在线预览:生成真机预览二维码(FinMall App 扫码)`:`该卡未经「同步远程」导入,无远端来源信息,无法生成真机预览二维码`,"data-testid":`remote-preview`,role:`menuitem`,onClick:t=>{a.chooseRsave(`preview`),e()}},[...t[57]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-grid`})],-1),U(`span`,null,`在线预览`,-1)]],10,dF),U(`li`,{class:j([`app__remote-item app__remote-item--sync`,{"is-disabled":!i.preview||!i.selectedId||i.syncingRemote}]),"data-testid":`sync-selected`,role:`menuitem`,onClick:t=>{a.chooseSync(`selected`),e()}},[...t[58]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-sync-box`})],-1),U(`span`,null,`当前同步`,-1)]],10,fF),U(`li`,{class:j([`app__remote-item app__remote-item--sync`,{"is-disabled":i.syncingRemote}]),"data-testid":`sync-full`,role:`menuitem`,onClick:t=>{a.chooseSync(`full`),e()}},[...t[59]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-refresh`})],-1),U(`span`,null,`全量同步`,-1)]],10,pF),K(` 切图上传:仅点击时执行,把「当前卡片引用到的」src/slices 切图上传到 FinMall 图片库
|
|
287
287
|
(CC0000.do),并把该卡 schema/data 里的 /slices/ 引用改写为返回的 @filestore/ 线上地址。
|
|
288
288
|
没有任何自动上传路径;共享切图若已上传过(sha256 命中 src/slices/manifest.json)直接复用地址。
|
|
289
|
-
不要求 hasCardSource:本地自建卡同样需要先把切图传上去,才能推版本 / 出真机预览。 `),U(`li`,{class:j([`app__remote-item app__remote-item--upload`,{"is-disabled":!i.preview||!i.selectedId||i.uploadingSlices}]),title:i.uploadingSlices?`正在上传切图…`:`切图上传:把当前卡片引用的本地切图(src/slices)上传到 FinMall 图片库,并把卡片里的 /slices/ 引用替换为线上地址(@filestore/…);本地切图文件保留`,"data-testid":`slice-upload`,role:`menuitem`,onClick:t=>{a.chooseRsave(`slices`),e()}},[...t[60]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-image-upload`})],-1),U(`span`,null,`切图上传`,-1)]],10,
|
|
289
|
+
不要求 hasCardSource:本地自建卡同样需要先把切图传上去,才能推版本 / 出真机预览。 `),U(`li`,{class:j([`app__remote-item app__remote-item--upload`,{"is-disabled":!i.preview||!i.selectedId||i.uploadingSlices}]),title:i.uploadingSlices?`正在上传切图…`:`切图上传:把当前卡片引用的本地切图(src/slices)上传到 FinMall 图片库,并把卡片里的 /slices/ 引用替换为线上地址(@filestore/…);本地切图文件保留`,"data-testid":`slice-upload`,role:`menuitem`,onClick:t=>{a.chooseRsave(`slices`),e()}},[...t[60]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-image-upload`})],-1),U(`span`,null,`切图上传`,-1)]],10,mF)])]),_:1},8,[`disabled`,`title`]),K(` 接口调用面板开关:右侧常驻面板的展开/收起,状态持久化 `),U(`button`,{class:j([`app__btn app__btn--icon`,{"app__btn--active":i.apiPanelOpen}]),type:`button`,title:i.apiPanelOpen?`收起接口调用面板`:`打开接口调用面板`,"aria-pressed":i.apiPanelOpen,onClick:t[7]||=(...e)=>a.toggleApiPanel&&a.toggleApiPanel(...e)},[...t[61]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`rect`,{x:`3`,y:`4`,width:`18`,height:`16`,rx:`2`}),U(`line`,{x1:`15`,y1:`4`,x2:`15`,y2:`20`})],-1)]],10,hF),K(` 主题切换:深色(当前)/ 浅色,复用同名 CSS 变量整体换肤,状态持久化 `),U(`button`,{class:`theme-toggle`,type:`button`,role:`switch`,"aria-checked":i.theme===`light`,title:i.theme===`light`?`切换到深色主题`:`切换到浅色主题`,onClick:t[8]||=(...e)=>a.toggleTheme&&a.toggleTheme(...e)},[U(`span`,_F,[U(`span`,vF,[i.theme===`light`?(B(),V(`svg`,yF,[...t[62]||=[as(`<circle cx="12" cy="12" r="4.2"></circle><line x1="12" y1="2.5" x2="12" y2="5"></line><line x1="12" y1="19" x2="12" y2="21.5"></line><line x1="2.5" y1="12" x2="5" y2="12"></line><line x1="19" y1="12" x2="21.5" y2="12"></line><line x1="4.9" y1="4.9" x2="6.8" y2="6.8"></line><line x1="17.2" y1="17.2" x2="19.1" y2="19.1"></line><line x1="4.9" y1="19.1" x2="6.8" y2="17.2"></line><line x1="17.2" y1="6.8" x2="19.1" y2="4.9"></line>`,9)]])):(B(),V(`svg`,bF,[...t[63]||=[U(`path`,{d:`M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z`},null,-1)]]))])])],8,gF),K(` 本地开发服务设置入口 `),U(`div`,xF,[U(`button`,{class:j([`app__btn app__btn--icon`,a.devSvcClass]),type:`button`,title:a.devSvcTitle,onClick:t[9]||=e=>i.devServiceOpen=!i.devServiceOpen},[...t[64]||=[U(`svg`,{class:`app__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-link`})],-1)]],10,SF),K(` 点遮罩关闭:与事件帮助气泡等轻量浮层同一交互 `),i.devServiceOpen?(B(),V(`div`,{key:0,class:`app__dev-svc-mask`,onClick:t[10]||=e=>i.devServiceOpen=!1})):K(`v-if`,!0),W(ic,{name:`pop`},{default:Lr(()=>[i.devServiceOpen?(B(),V(`div`,{key:0,class:`app__dev-svc-panel`,onClick:t[17]||=q(()=>{},[`stop`])},[U(`div`,CF,[t[65]||=U(`span`,{class:`app__dev-svc-title`},`本地开发服务`,-1),U(`button`,{class:`app__dev-svc-close`,type:`button`,title:`关闭`,onClick:t[11]||=e=>i.devServiceOpen=!1})]),U(`div`,wF,[U(`label`,TF,[t[66]||=U(`span`,null,`启用`,-1),W(c,{modelValue:i.devServiceForm.enabled,"onUpdate:modelValue":t[12]||=e=>i.devServiceForm.enabled=e},null,8,[`modelValue`])]),U(`label`,EF,[t[67]||=U(`span`,null,`服务地址`,-1),I(U(`input`,{type:`text`,"onUpdate:modelValue":t[13]||=e=>i.devServiceForm.baseUrl=e,placeholder:`http://127.0.0.1:8787`},null,512),[[il,i.devServiceForm.baseUrl]])]),U(`label`,DF,[t[68]||=U(`span`,null,`访问令牌(可选)`,-1),I(U(`input`,{type:`text`,"onUpdate:modelValue":t[14]||=e=>i.devServiceForm.token=e,placeholder:`留空则不校验`},null,512),[[il,i.devServiceForm.token]])]),i.apiBaseResolved===null?(B(),V(`p`,OF,[a.devSvcBlockReason===`disabled`?(B(),V(z,{key:0},[G(`已填写服务地址,但「启用」开关未打开。请开启「启用」开关并点击保存,本地开发服务才会生效。`)],64)):(B(),V(z,{key:1},[G(`请填写本机 cardbuddy 服务地址(默认 http://127.0.0.1:8787),打开「启用」开关并保存后,编辑功能才会生效。`)],64))])):K(`v-if`,!0),U(`div`,kF,[U(`button`,{class:`ni-btn ni-btn--ghost`,type:`button`,onClick:t[15]||=e=>i.devServiceOpen=!1},`关闭`),U(`button`,{class:`ni-btn`,type:`button`,onClick:t[16]||=(...e)=>a.saveDevService&&a.saveDevService(...e)},`保存`)])])])):K(`v-if`,!0)]),_:1})])]),U(`span`,AF,M(i.rt.revision),1)],512),[[Sc,!i.chromeOff]]),K(` AI 开发助手悬浮入口:右下角圆形按钮(尺寸 / 配色走规范 Token,图标取自 sprite) `),U(`button`,{class:j([`ai-fab`,{"ai-fab--active":i.aiChatOpen,"ai-fab--busy":i.chatBusy}]),type:`button`,title:a.fabTitle,"aria-expanded":i.aiChatOpen?`true`:`false`,"data-testid":`ai-fab`,onClick:t[18]||=e=>i.aiChatOpen=!i.aiChatOpen},[t[69]||=U(`svg`,{class:`ai-fab__icon`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`use`,{href:`#icon-sparkles`})],-1),K(` 收起态的生成进度徽标:关面板不打断生成,没有它几十分钟的建卡看着像已经死了 `),i.chatBusy&&!i.aiChatOpen?(B(),V(`span`,{key:0,class:j([`ai-fab__badge`,{"is-stalled":i.chatProgress&&i.chatProgress.stalled}])},M(a.fabBadge),3)):K(`v-if`,!0)],10,jF),K(` AI 开发助手对话面板:右侧抽屉,宽度可拖(320px ~ 视口 50%,默认 33%),对话记录按卡片落盘 `),W(l,{ref:`chatPanel`,visible:i.aiChatOpen,"card-id":i.selectedId,"card-name":a.selectedCardName,"card-empty":a.cardEmpty,onClose:t[19]||=e=>i.aiChatOpen=!1,onBusy:t[20]||=e=>i.chatBusy=e,onTurnProgress:t[21]||=e=>i.chatProgress=e,onTurnFinished:a.onChatTurnFinished,onRollbackTurn:a.onChatRollbackTurn,onLocateNode:a.onAiLocateNode},null,8,[`visible`,`card-id`,`card-name`,`card-empty`,`onTurnFinished`,`onRollbackTurn`,`onLocateNode`]),K(` 部署态但未配置本地开发服务:顶部提示条(chrome=off 截图模式不显示) `),i.apiBaseResolved===null&&!i.chromeOff?(B(),V(`div`,MF,[a.devSvcBlockReason===`disabled`?(B(),V(z,{key:0},[G(` ⚠ 本地开发服务未生效:已填写地址,但未打开「启用」开关。请点击右上角 「连接」图标打开「本地开发服务」设置,开启「启用」开关并保存后,编辑功能才会生效。 `)],64)):(B(),V(z,{key:1},[G(` ⚠ 未配置本地开发服务:当前为部署态,编辑功能不可用。请点击右上角 「连接」图标打开「本地开发服务」设置,填写本机 cardbuddy 地址、打开「启用」开关并保存后,才能编辑卡片。 `)],64))])):K(`v-if`,!0),K(` 已配置本地服务但实时连接已断开:顶部提示条(chrome=off 截图模式不显示) `),i.apiBaseResolved!==null&&i.devSvcDown&&!i.chromeOff?(B(),V(`div`,NF,` ⚠ 本地开发服务已断开:连接失败或服务已停止,编辑 / 同步功能暂不可用。请确认本地 cardbuddy 是否运行,或点击右上角「连接」图标重新保存配置。 `)):K(`v-if`,!0),K(` 外部改了当前卡、无未保存改动 → 自动重载后的非阻塞轻提示(chrome=off 截图模式不显示) `),i.externalReloadNote&&!i.chromeOff?(B(),V(`div`,PF,` ↻ `+M(i.externalReloadNote),1)):K(`v-if`,!0),U(`main`,FF,[U(`div`,{class:j([`phone`,{"phone--dragging":i.dragging}]),style:A({width:a.previewWidth+`px`})},[K(` 缩放外框:占满整列(宽高由 CSS flex 填满);画布不做 transform 缩放,直接按实际尺寸布局 `),U(`div`,{class:`phone__frame`,style:A(a.frameStyle)},[K(` 画布层:直接按实际列宽/列高布局(width/height 100%),不再使用 transform 缩放 `),U(`div`,IF,[K(` 画布工具条:原 device-bar(顶 28px)+ preview-statusbar(底 28px)合并为一条 32px,
|
|
290
290
|
竖向空间还给手机视口。左组=改变画布(背景 / 宽度预设),右组=画布现状与动作(尺寸读数 / 刷新);
|
|
291
|
-
预览列窄于 300px 时收起读数与文案只留图标(188 预设下仍单行可用)。 `),I(U(`div`,{class:j([`canvas-bar`,{"canvas-bar--tight":a.previewWidth<300}])},[K(` 画布背景:触发器带当前底色小样,不展开下拉也可见当前模式 `),W(s,{borderless:``,size:`xs`,placement:`bottom-start`,value:i.canvasBg,options:i.bgOptions.map(e=>({key:e.key,value:e.label+`背景`})),onChange:a.chooseBg},{trigger:Lr(()=>[U(`span`,{class:`canvas-bar__chip`,title:`画布背景:`+a.currentBg.label},[U(`i`,{class:j([`canvas-bar__swatch`,`canvas-bar__swatch--`+i.canvasBg])},null,2),U(`span`,
|
|
291
|
+
预览列窄于 300px 时收起读数与文案只留图标(188 预设下仍单行可用)。 `),I(U(`div`,{class:j([`canvas-bar`,{"canvas-bar--tight":a.previewWidth<300}])},[K(` 画布背景:触发器带当前底色小样,不展开下拉也可见当前模式 `),W(s,{borderless:``,size:`xs`,placement:`bottom-start`,value:i.canvasBg,options:i.bgOptions.map(e=>({key:e.key,value:e.label+`背景`})),onChange:a.chooseBg},{trigger:Lr(()=>[U(`span`,{class:`canvas-bar__chip`,title:`画布背景:`+a.currentBg.label},[U(`i`,{class:j([`canvas-bar__swatch`,`canvas-bar__swatch--`+i.canvasBg])},null,2),U(`span`,RF,M(a.currentBg.label)+`背景`,1),t[70]||=U(`svg`,{class:`canvas-bar__chev`,viewBox:`0 0 16 16`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron`})],-1)],8,LF)]),_:1},8,[`value`,`options`,`onChange`]),K(` 宽度预设:触发器直接显示当前宽度,省去独立的「宽度」标签 `),W(s,{borderless:``,size:`xs`,placement:`bottom-start`,value:a.canvasW,options:i.presetSizes,onChange:a.setPresetWidth},{trigger:Lr(()=>[U(`span`,zF,[t[71]||=U(`svg`,{class:`canvas-bar__icn`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`polyline`,{points:`8 7 4 12 8 17`}),U(`polyline`,{points:`16 7 20 12 16 17`}),U(`line`,{x1:`4`,y1:`12`,x2:`20`,y2:`12`})],-1),U(`span`,BF,M(a.canvasW)+` px`,1),t[72]||=U(`svg`,{class:`canvas-bar__chev`,viewBox:`0 0 16 16`,"aria-hidden":`true`},[U(`use`,{href:`#icon-chevron`})],-1)])]),_:1},8,[`value`,`options`,`onChange`]),t[74]||=U(`span`,{class:`canvas-bar__spacer`},null,-1),U(`span`,VF,M(a.canvasW)+` × `+M(i.viewportHeight),1),U(`button`,{class:j([`canvas-bar__iconbtn`,{"is-loading":i.refreshing}]),type:`button`,disabled:!i.selectedId||i.refreshing,title:`刷新卡片,重新加载`,onClick:t[22]||=(...e)=>a.refreshCard&&a.refreshCard(...e)},[...t[73]||=[U(`svg`,{class:`canvas-bar__icn`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`,"stroke-linejoin":`round`,"aria-hidden":`true`},[U(`path`,{d:`M21 12a9 9 0 1 1-2.64-6.36`}),U(`path`,{d:`M21 3v6h-6`})],-1)]],10,HF)],2),[[Sc,!i.chromeOff]]),K(`
|
|
292
292
|
固定视口:弹层(alertCard / alertDialog / toast)相对此容器 absolute inset:0 定位,
|
|
293
293
|
不随内层 phone__screen 的卡片内容滚动,保证遮罩始终精确覆盖可视区域。
|
|
294
294
|
`),U(`div`,{ref:`phoneViewport`,class:`phone-viewport`,onClick:t[23]||=(...e)=>a.onCanvasClick&&a.onCanvasClick(...e)},[U(`div`,{class:j([`phone__screen`,`phone__screen--bg-`+(i.chromeOff?`white`:i.canvasBg)]),style:A(i.chromeOff&&i.preview?{width:(i.preview.view.width||375)+`px`}:null),"data-card-ready":i.cardReady?`1`:null},[K(`
|
|
@@ -296,12 +296,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
296
296
|
等场景时强制 RenderTree 重新挂载,从而保证新卡片/新数据的「初始化动作」
|
|
297
297
|
(onReady 等生命周期事件,如 assetOverview 计算 ratio)一定在 created 阶段
|
|
298
298
|
执行,不会出现重载后 init 不跑、依赖字段为 undefined 而渲染成 NaN% 的问题。
|
|
299
|
-
`),i.preview?(B(),H(u,{key:i.selectedId+`:`+i.reloadToken,node:i.preview.view,scope:i.rt.state,"selected-node-id":i.selectedNodeId},null,8,[`node`,`scope`,`selected-node-id`])):K(`v-if`,!0),K(` 节点选中遮罩覆盖层:作为滚动容器子节点,随内容滚动并精确贴合选中元素 `),W(d),K(` 结构树 hover 参考线:贯穿画布的荧光绿辅助线(左/右竖线、上/下横线),仅 hover 时显示 `),W(f)],14,
|
|
299
|
+
`),i.preview?(B(),H(u,{key:i.selectedId+`:`+i.reloadToken,node:i.preview.view,scope:i.rt.state,"selected-node-id":i.selectedNodeId},null,8,[`node`,`scope`,`selected-node-id`])):K(`v-if`,!0),K(` 节点选中遮罩覆盖层:作为滚动容器子节点,随内容滚动并精确贴合选中元素 `),W(d),K(` 结构树 hover 参考线:贯穿画布的荧光绿辅助线(左/右竖线、上/下横线),仅 hover 时显示 `),W(f)],14,UF),K(` 弹窗卡片图层:alertCard / closeAlertCard 的展现层(在预览区域内弹出) `),W(p,{"main-rt":i.rt},null,8,[`main-rt`]),K(` 设备级模拟 UI:alertDialog 对话框 / showToast 弱提示 / showPicker 选择器 / showDatePicker 日期选择器 `),W(m),W(h),W(g)],512)])],4)],6),K(` 左分隔条:预览列 | 工作区 接缝。底面板 / 状态栏的左缘即此缝(随预览宽度联动),
|
|
300
300
|
故定位在 .app__stage 通到底部,全程可拖;右分隔条才收进两栏容器内。 `),I(U(`div`,{class:j([`splitter`,{"is-dragging":i.dragging,"is-armed":i.armedLeft}]),onMouseenter:t[24]||=e=>a.armSplitter(`left`),onMouseleave:t[25]||=e=>a.disarmSplitter(`left`),onPointerdown:t[26]||=q((...e)=>a.startDrag&&a.startDrag(...e),[`prevent`]),title:`拖拽调整预览区域宽度`},null,34),[[Sc,!i.chromeOff]]),K(` 中右工作区:上为「调试面板 + 接口调用面板」两栏,下为贯穿两栏的共同状态栏。
|
|
301
301
|
状态栏与底部弹出面板(运行态 / 事件 / 变量绑定)均由 DebugPanel 内 Teleport 注入
|
|
302
302
|
#app-workside-bar / #app-workside-panels,宽度贯穿中右两栏;Teleport 目标须在 DOM 中
|
|
303
|
-
先于面板挂载,故两个空容器写在前面,以 flex order 视觉置底。 `),I(U(`div`,
|
|
303
|
+
先于面板挂载,故两个空容器写在前面,以 flex order 视觉置底。 `),I(U(`div`,WF,[t[75]||=U(`div`,{id:`app-workside-bar`,class:`workside__bar`},null,-1),t[76]||=U(`div`,{id:`app-workside-panels`,class:`workside__panels`},null,-1),U(`div`,GF,[K(` 拖拽分隔条:置于两栏容器内(定位上下文),只贯穿列区高度,不穿过底部弹出面板与状态栏 `),K(` 中右分隔条:调试面板 | 接口调用面板 接缝,拖动调整右栏宽度。
|
|
304
304
|
约束:中栏最小宽度 ≥ 屏宽 1/3,右栏最小宽度 ≥ 320px(见 startApiDrag) `),I(U(`div`,{class:j([`splitter splitter--api`,{"is-dragging":i.apiDragging,"is-armed":i.armedApi}]),onMouseenter:t[27]||=e=>a.armSplitter(`api`),onMouseleave:t[28]||=e=>a.disarmSplitter(`api`),onPointerdown:t[29]||=q((...e)=>a.startApiDrag&&a.startApiDrag(...e),[`prevent`]),title:`拖拽调整接口调用面板宽度`},null,34),[[Sc,!i.chromeOff&&i.apiPanelOpen]]),W(_,{"chrome-off":i.chromeOff,rt:i.rt,preview:i.preview,schema:i.currentSchema,"card-id":i.selectedId,"reload-token":i.reloadToken,"card-count":i.cardCount,"selected-node-id":i.selectedNodeId,"move-collapse-token":i.moveCollapseToken,"active-tab":i.activeTab,onSchemaChanged:a.onSchemaChanged,onSchemaCommit:a.onSchemaCommit,onSelectNode:a.onSelectNode,"onUpdate:activeTab":t[30]||=e=>i.activeTab=e,onAddNode:a.onAddNode,onMoveNode:a.onMoveNode,onHoverNode:a.onHoverNode,onCopySelected:a.copySelectedNode,onPaste:a.pasteNode,onDuplicate:a.duplicateNode,onDeleteSelected:a.deleteSelectedNode,onRenameCard:a.openRenameCard,onResetImport:a.onRefresh,"dev-svc-class":a.devSvcClass,"dev-svc-title":a.devSvcTitle,"dev-svc-label":a.devSvcLabel,"dev-svc-conn":a.devSvcConn},null,8,`chrome-off.rt.preview.schema.card-id.reload-token.card-count.selected-node-id.move-collapse-token.active-tab.onSchemaChanged.onSchemaCommit.onSelectNode.onAddNode.onMoveNode.onHoverNode.onCopySelected.onPaste.onDuplicate.onDeleteSelected.onRenameCard.onResetImport.dev-svc-class.dev-svc-title.dev-svc-label.dev-svc-conn`.split(`.`)),K(` 右侧常驻「接口调用」面板:与预览列 / 调试面板呈左中右布局,
|
|
305
|
-
展开/收起由顶栏按钮与面板内 ✕ 控制,初始状态持久化 `),i.apiPanelOpen?(B(),H(v,{key:0,rt:i.rt,onClose:t[31]||=e=>i.apiPanelOpen=!1},null,8,[`rt`])):K(`v-if`,!0)],512)],512),[[Sc,!i.chromeOff]])],512),K(` 远端预览二维码弹层:点击顶栏「远端预览」按钮打开,手机(FinMall App)扫码真机查看 `),W(y,{visible:i.remotePreviewOpen,"page-id":i.currentSchema?i.currentSchema.pageId:``,schema:i.currentSchema,onClose:t[32]||=e=>i.remotePreviewOpen=!1},null,8,[`visible`,`page-id`,`schema`]),K(` 登录凭据弹窗:远程同步检测到缺凭据时弹出,填写账号密码(MD5 后)写入 .local/credentials.json `),W(ic,{name:`modal`},{default:Lr(()=>[i.loginModal?(B(),V(`div`,{key:0,class:`login-mask`,onClick:t[39]||=q((...e)=>a.closeLoginModal&&a.closeLoginModal(...e),[`self`])},[U(`div`,VF,[t[79]||=U(`div`,{class:`login-modal__title`},`FinMall 登录凭据`,-1),t[80]||=U(`div`,{class:`login-modal__desc`},` 本地登录凭据缺失,请填写账号与密码。密码仅做 MD5 后保存,不落明文。 `,-1),U(`label`,HF,[t[77]||=U(`span`,{class:`login-modal__label`},`账号`,-1),I(U(`input`,{class:`login-modal__input`,type:`text`,"onUpdate:modelValue":t[33]||=e=>i.loginName=e,placeholder:`FinMall 登录账号`,disabled:i.loginSubmitting,onKeyup:t[34]||=vl((...e)=>a.submitLogin&&a.submitLogin(...e),[`enter`])},null,40,UF),[[il,i.loginName]])]),U(`label`,WF,[t[78]||=U(`span`,{class:`login-modal__label`},`密码`,-1),I(U(`input`,{class:`login-modal__input`,type:`password`,"onUpdate:modelValue":t[35]||=e=>i.loginPassword=e,placeholder:`FinMall 登录密码`,disabled:i.loginSubmitting,onKeyup:t[36]||=vl((...e)=>a.submitLogin&&a.submitLogin(...e),[`enter`])},null,40,GF),[[il,i.loginPassword]])]),i.loginError?(B(),V(`div`,KF,M(i.loginError),1)):K(`v-if`,!0),U(`div`,qF,[U(`button`,{class:`login-modal__btn login-modal__btn--ghost`,type:`button`,disabled:i.loginSubmitting,onClick:t[37]||=(...e)=>a.closeLoginModal&&a.closeLoginModal(...e)},` 取消 `,8,JF),U(`button`,{class:`login-modal__btn login-modal__btn--primary`,type:`button`,disabled:i.loginSubmitting,onClick:t[38]||=(...e)=>a.submitLogin&&a.submitLogin(...e)},M(i.loginSubmitting?`保存中…`:`保存并同步`),9,YF)])])])):K(`v-if`,!0)]),_:1}),K(` 组件选择面板:点击结构树每行的「+」后弹出,选择类型即插入对应节点 `),W(ic,{name:`modal`},{default:Lr(()=>[i.addNodePanelOpen?(B(),H(b,{key:0,onPick:a.onPickComponent,onClose:a.cancelAddNode},null,8,[`onPick`,`onClose`])):K(`v-if`,!0)]),_:1}),K(` 二次确认弹窗:版本推送 / 当前同步 / 全量同步 等写/覆盖类操作前弹出,确认后才执行 `),W(x,{visible:i.confirm.show,title:i.confirm.title,message:i.confirm.message,"confirm-text":i.confirm.confirmText,"cancel-text":i.confirm.cancelText,severity:i.confirm.severity,onConfirm:a.onConfirmDialog,onCancel:a.onCancelDialog},null,8,[`visible`,`title`,`message`,`confirm-text`,`cancel-text`,`severity`,`onConfirm`,`onCancel`]),K(` 卡片网格预览弹窗:点击顶栏「网格预览」图标按钮打开,选择卡片即载入工作台 `),W(S,{visible:i.galleryOpen,cards:i.cardList,"selected-id":i.selectedId,onSelect:a.onSelect,onClose:a.closeGallery,onDelete:a.onGalleryDelete},null,8,[`visible`,`cards`,`selected-id`,`onSelect`,`onClose`,`onDelete`]),K(` 卡片表单弹窗(新增空白卡片 / 卡片重命名 共用一个弹窗):成功后关弹窗 + 刷列表 + 加载目标卡;existing-ids 供 ID 重名前置判定 `),W(C,{visible:i.cardDialog.visible,mode:i.cardDialog.mode,"card-id":i.cardDialog.cardId,"card-desc":i.cardDialog.cardDesc,"existing-ids":a.cardIds,onClose:t[40]||=e=>i.cardDialog.visible=!1,onCreated:a.onNewCardCreated,onRenamed:a.onCardRenamed},null,8,[`visible`,`mode`,`card-id`,`card-desc`,`existing-ids`,`onCreated`,`onRenamed`]),K(` App 级弱提示:顶栏异步操作(远端保存 / 同步)完成反馈,浮于 App 外壳顶部居中 `),W(w),K(` 对话图片大图查看器:AI 面板里点预览图后全屏缩放查看,Teleport 到 body `),W(T)],6)}var ZF=X(LP,[[`render`,XF],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/App.vue`]]),QF={name:`SetText`,props:{...jg,multiline:{type:Boolean,default:!1}},emits:Mg,computed:{text(){return this.value===void 0||this.value===null?``:String(this.value)},rows(){let e=this.options.autosize;return e&&typeof e==`object`&&e.minRows?e.minRows:4}},methods:{onInput(e){this.$emit(`input`,e)}}},$F=[`rows`,`placeholder`,`disabled`,`value`],eI=[`placeholder`,`disabled`,`value`];function tI(e,t,n,r,i,a){return n.multiline?(B(),V(`textarea`,{key:0,class:`st-textarea`,rows:a.rows,placeholder:e.options.placeholder||``,disabled:e.disabled,value:a.text,onInput:t[0]||=e=>a.onInput(e.target.value),onChange:t[1]||=t=>e.$emit(`change`)},null,40,$F)):(B(),V(`input`,{key:1,class:`ni-input`,type:`text`,placeholder:e.options.placeholder||``,disabled:e.disabled,value:a.text,onInput:t[2]||=e=>a.onInput(e.target.value),onChange:t[3]||=t=>e.$emit(`change`)},null,40,eI))}var nI=X(QF,[[`render`,tI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetText.vue`]]),rI={integer:/^-?(0|[1-9][0-9]*)?$/,"+integer":/^(0|[1-9][0-9]*)?$/,"-integer":/^(0|-[1-9]?[0-9]*)?$/,float:/^-?([0-9]*|(0|[1-9][0-9]*)\.[0-9]*)?$/,"+float":/^([0-9]*|(0|[1-9][0-9]*)\.[0-9]*)?$/,"-float":/^(0|-[0-9]*|-(0|[1-9][0-9]*)\.[0-9]*)?$/},iI={name:`SetNumber`,props:jg,emits:Mg,data(){return{inputValue:``,sugOpen:!1}},computed:{suggestions(){return this.options.iParamList||[]},pattern(){return rI[this.options.type]||rI.integer}},watch:{value:{immediate:!0,handler(e){this.inputValue=e==null?``:String(e)}}},methods:{onInput(e){if(!this.pattern.test(e)){this.$refs.field.value=this.inputValue;return}this.inputValue=e,this.$emit(`input`,e)},step(e){let t=parseFloat(this.inputValue),n=String((Number.isNaN(t)?0:t)+e);this.pattern.test(n)&&(this.inputValue=n,this.$emit(`input`,n),this.emitChange())},pick(e){this.sugOpen=!1,this.inputValue=String(e.key),this.$emit(`input`,this.inputValue),this.emitChange()},closeSug(){setTimeout(()=>this.sugOpen=!1,0)},emitChange(){this.$emit(`change`)}}},aI={class:`st-number-wrap`},oI={class:`st-number`},sI=[`placeholder`,`disabled`,`value`],cI={key:0,class:`st-number__symbol st-number__symbol--btn`},lI={key:1,class:`st-number__symbol`},uI={key:0,class:`st-pop st-pop--sug`},dI=[`onMousedown`];function fI(e,t,n,r,i,a){return B(),V(`div`,aI,[U(`div`,oI,[U(`input`,{ref:`field`,class:`st-number__field`,type:`text`,placeholder:e.options.placeholder||`请输入`,disabled:e.disabled,value:i.inputValue,onInput:t[0]||=e=>a.onInput(e.target.value),onChange:t[1]||=e=>a.emitChange(),onKeydown:[t[2]||=vl(q(e=>a.step(1),[`prevent`]),[`up`]),t[3]||=vl(q(e=>a.step(-1),[`prevent`]),[`down`])],onBlur:t[4]||=e=>a.closeSug()},null,40,sI),e.$slots.symbol?(B(),V(`span`,cI,[Qi(e.$slots,`symbol`)])):e.options.symbol&&e.options.symbol!==!0?(B(),V(`span`,lI,M(e.options.symbol),1)):K(`v-if`,!0),a.suggestions.length?(B(),V(`span`,{key:2,class:`st-number__caret`,title:`预设值`,onMousedown:t[5]||=q(e=>i.sugOpen=!i.sugOpen,[`prevent`])},`▾`,32)):K(`v-if`,!0)]),K(` 预设值浮层:移出 .st-number,避免被 overflow:hidden 裁切 `),i.sugOpen&&a.suggestions.length?(B(),V(`div`,uI,[(B(!0),V(z,null,R(a.suggestions,e=>(B(),V(`div`,{key:e.key,class:j([`st-pop__item`,{"st-pop__item--on":String(e.key)===String(i.inputValue)}]),onMousedown:q(t=>a.pick(e),[`prevent`])},M(e.value),43,dI))),128))])):K(`v-if`,!0)])}var pI=X(iI,[[`render`,fI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetNumber.vue`]]),mI={name:`SetSelect`,props:jg,emits:Mg,computed:{list(){return this.options.iParamList||this.options.iTypeList||[]},placeholder(){return this.options.placeholder||`请选择`},optionList(){return this.list.map(e=>({key:String(e.key),value:e.value}))},current(){return this.value===void 0||this.value===null?``:String(this.value)}},methods:{onChange(e){this.$emit(`input`,e),this.$emit(`change`)}}};function hI(e,t,n,r,i,a){let o=L(`Dropdown`);return B(),H(o,{value:a.current,options:a.optionList,placeholder:a.placeholder,clearable:``,size:`sm`,block:``,disabled:e.disabled,onInput:a.onChange},null,8,[`value`,`options`,`placeholder`,`disabled`,`onInput`])}var gI=X(mI,[[`render`,hI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetSelect.vue`]]),_I={name:`SetSwitch`,props:{...jg,boolean:{type:Boolean,default:!1}},emits:Mg,computed:{activeValue(){return this.options.activeValue===void 0?this.boolean?!0:`1`:this.options.activeValue},inactiveValue(){return this.options.inactiveValue===void 0?!this.boolean&&`0`:this.options.inactiveValue},on(){return this.value===this.activeValue},activeText(){return this.options.activeText||`开`},inactiveText(){return this.options.inactiveText||`关`}},methods:{toggle(){this.disabled||(this.$emit(`input`,this.on?this.inactiveValue:this.activeValue),this.$emit(`change`))}}},vI={class:`st-switch__text`};function yI(e,t,n,r,i,a){return B(),V(`div`,{class:j([`st-switch`,{"st-switch--on":a.on}]),onClick:t[0]||=(...e)=>a.toggle&&a.toggle(...e)},[t[1]||=U(`span`,{class:`st-switch__track`},[U(`span`,{class:`st-switch__knob`})],-1),U(`span`,vI,M(a.on?a.activeText:a.inactiveText),1)],2)}var bI=X(_I,[[`render`,yI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetSwitch.vue`]]);function xI(e,t){t===void 0&&(t={});var n=t.insertAt;if(!(!e||typeof document>`u`)){var r=document.head||document.getElementsByTagName(`head`)[0],i=document.createElement(`style`);i.type=`text/css`,n===`top`&&r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(document.createTextNode(e))}}var SI=function(e,t){let{componentPrefix:n=``}=t||{};e.component(`${n}${this.name}`,this)},CI={},wI={name:`Checkboard`,props:{size:{type:[Number,String],default:8},white:{type:String,default:`#fff`},grey:{type:String,default:`#e6e6e6`}},computed:{bgStyle(){return{"background-image":`url(${EI(this.white,this.grey,this.size)})`}}}};function TI(e,t,n){if(typeof document>`u`)return null;let r=document.createElement(`canvas`);r.width=r.height=n*2;let i=r.getContext(`2d`);return i?(i.fillStyle=e,i.fillRect(0,0,r.width,r.height),i.fillStyle=t,i.fillRect(0,0,n,n),i.translate(n,n),i.fillRect(0,0,n,n),r.toDataURL()):null}function EI(e,t,n){let r=`${e},${t},${n}`;if(CI[r])return CI[r];let i=TI(e,t,n);return CI[r]=i,i}function DI(e,t,n,r,i,a){return B(),V(`div`,{class:`vc-checkerboard`,style:A(a.bgStyle)},null,4)}xI(`.vc-checkerboard{background-size:contain;bottom:0;left:0;position:absolute;right:0;top:0}`),wI.render=DI,wI.__file=`src/components/checkboard/checkboard.vue`,wI.install=SI;var OI={name:`Alpha`,components:{Checkboard:wI},props:{value:Object,onChange:Function},computed:{colors(){return this.value},gradientColor(){let{rgba:e}=this.colors,t=[e.r,e.g,e.b].join(`,`);return`linear-gradient(to right, rgba(${t}, 0) 0%, rgba(${t}, 1) 100%)`}},methods:{handleChange(e,t){!t&&e.preventDefault();let{container:n}=this.$refs;if(!n)return;let r=n.clientWidth,i=n.getBoundingClientRect().left+window.pageXOffset,a=(e.pageX||(e.touches?e.touches[0].pageX:0))-i,o;o=a<0?0:a>r?1:Math.round(a*100/r)/100,this.colors.a!==o&&this.$emit(`change`,{h:this.colors.hsl.h,s:this.colors.hsl.s,l:this.colors.hsl.l,a:o,source:`rgba`})},handleMouseDown(e){this.handleChange(e,!0),window.addEventListener(`mousemove`,this.handleChange),window.addEventListener(`mouseup`,this.handleMouseUp)},handleMouseUp(){this.unbindEventListeners()},unbindEventListeners(){window.removeEventListener(`mousemove`,this.handleChange),window.removeEventListener(`mouseup`,this.handleMouseUp)}}},kI={class:`vc-alpha`},AI={class:`vc-alpha-checkboard-wrap`},jI=[U(`div`,{class:`vc-alpha-picker`},null,-1)];function MI(e,t,n,r,i,a){let o=L(`Checkboard`);return B(),V(`div`,kI,[U(`div`,AI,[W(o)]),U(`div`,{class:`vc-alpha-gradient`,style:A({background:a.gradientColor})},null,4),U(`div`,{ref:`container`,class:`vc-alpha-container`,onMousedown:t[0]||=(...e)=>a.handleMouseDown&&a.handleMouseDown(...e),onTouchmove:t[1]||=(...e)=>a.handleChange&&a.handleChange(...e),onTouchstart:t[2]||=(...e)=>a.handleChange&&a.handleChange(...e)},[U(`div`,{class:`vc-alpha-pointer`,style:A({left:`${a.colors.a*100}%`})},jI,4)],544)])}xI(`.vc-alpha,.vc-alpha-checkboard-wrap{bottom:0;left:0;position:absolute;right:0;top:0}.vc-alpha-checkboard-wrap{overflow:hidden}.vc-alpha-gradient{bottom:0;left:0;position:absolute;right:0;top:0}.vc-alpha-container{cursor:pointer;height:100%;margin:0 3px;position:relative;z-index:2}.vc-alpha-pointer{position:absolute;z-index:2}.vc-alpha-picker{background:#fff;border-radius:1px;box-shadow:0 0 2px rgba(0,0,0,.6);cursor:pointer;height:8px;margin-top:1px;transform:translateX(-2px);width:4px}`),OI.render=MI,OI.__file=`src/components/alpha/alpha.vue`,OI.install=SI;function NI(e,t){FI(e)&&(e=`100%`);var n=II(e);return e=t===360?e:Math.min(t,Math.max(0,parseFloat(e))),n&&(e=parseInt(String(e*t),10)/100),Math.abs(e-t)<1e-6?1:(e=t===360?(e<0?e%t+t:e%t)/parseFloat(String(t)):e%t/parseFloat(String(t)),e)}function PI(e){return Math.min(1,Math.max(0,e))}function FI(e){return typeof e==`string`&&e.indexOf(`.`)!==-1&&parseFloat(e)===1}function II(e){return typeof e==`string`&&e.indexOf(`%`)!==-1}function LI(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function RI(e){return e<=1?`${Number(e)*100}%`:e}function zI(e){return e.length===1?`0`+e:String(e)}function BI(e,t,n){return{r:NI(e,255)*255,g:NI(t,255)*255,b:NI(n,255)*255}}function VI(e,t,n){e=NI(e,255),t=NI(t,255),n=NI(n,255);var r=Math.max(e,t,n),i=Math.min(e,t,n),a=0,o=0,s=(r+i)/2;if(r===i)o=0,a=0;else{var c=r-i;switch(o=s>.5?c/(2-r-i):c/(r+i),r){case e:a=(t-n)/c+(t<n?6:0);break;case t:a=(n-e)/c+2;break;case n:a=(e-t)/c+4}a/=6}return{h:a,s:o,l:s}}function HI(e,t,n){return n<0&&(n+=1),n>1&&--n,n<1/6?e+(t-e)*(6*n):n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function UI(e,t,n){var r,i,a;if(e=NI(e,360),t=NI(t,100),n=NI(n,100),t===0)i=n,a=n,r=n;else{var o=n<.5?n*(1+t):n+t-n*t,s=2*n-o;r=HI(s,o,e+1/3),i=HI(s,o,e),a=HI(s,o,e-1/3)}return{r:r*255,g:i*255,b:a*255}}function WI(e,t,n){e=NI(e,255),t=NI(t,255),n=NI(n,255);var r=Math.max(e,t,n),i=Math.min(e,t,n),a=0,o=r,s=r-i,c=r===0?0:s/r;if(r===i)a=0;else{switch(r){case e:a=(t-n)/s+(t<n?6:0);break;case t:a=(n-e)/s+2;break;case n:a=(e-t)/s+4}a/=6}return{h:a,s:c,v:o}}function GI(e,t,n){e=NI(e,360)*6,t=NI(t,100),n=NI(n,100);var r=Math.floor(e),i=e-r,a=n*(1-t),o=n*(1-i*t),s=n*(1-(1-i)*t),c=r%6,l=[n,o,a,a,s,n][c],u=[s,n,n,o,a,a][c],d=[a,a,s,n,n,o][c];return{r:l*255,g:u*255,b:d*255}}function KI(e,t,n,r){var i=[zI(Math.round(e).toString(16)),zI(Math.round(t).toString(16)),zI(Math.round(n).toString(16))];return r&&i[0].startsWith(i[0].charAt(1))&&i[1].startsWith(i[1].charAt(1))&&i[2].startsWith(i[2].charAt(1))?i[0].charAt(0)+i[1].charAt(0)+i[2].charAt(0):i.join(``)}function qI(e,t,n,r,i){var a=[zI(Math.round(e).toString(16)),zI(Math.round(t).toString(16)),zI(Math.round(n).toString(16)),zI(JI(r))];return i&&a[0].startsWith(a[0].charAt(1))&&a[1].startsWith(a[1].charAt(1))&&a[2].startsWith(a[2].charAt(1))&&a[3].startsWith(a[3].charAt(1))?a[0].charAt(0)+a[1].charAt(0)+a[2].charAt(0)+a[3].charAt(0):a.join(``)}function JI(e){return Math.round(parseFloat(e)*255).toString(16)}function YI(e){return XI(e)/255}function XI(e){return parseInt(e,16)}function ZI(e){return{r:e>>16,g:(e&65280)>>8,b:e&255}}var QI={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,goldenrod:`#daa520`,gold:`#ffd700`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,lavenderblush:`#fff0f5`,lavender:`#e6e6fa`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`};function $I(e){var t={r:0,g:0,b:0},n=1,r=null,i=null,a=null,o=!1,s=!1;return typeof e==`string`&&(e=iL(e)),typeof e==`object`&&(aL(e.r)&&aL(e.g)&&aL(e.b)?(t=BI(e.r,e.g,e.b),o=!0,s=String(e.r).substr(-1)===`%`?`prgb`:`rgb`):aL(e.h)&&aL(e.s)&&aL(e.v)?(r=RI(e.s),i=RI(e.v),t=GI(e.h,r,i),o=!0,s=`hsv`):aL(e.h)&&aL(e.s)&&aL(e.l)&&(r=RI(e.s),a=RI(e.l),t=UI(e.h,r,a),o=!0,s=`hsl`),Object.prototype.hasOwnProperty.call(e,`a`)&&(n=e.a)),n=LI(n),{ok:o,format:e.format||s,r:Math.min(255,Math.max(t.r,0)),g:Math.min(255,Math.max(t.g,0)),b:Math.min(255,Math.max(t.b,0)),a:n}}var eL=`(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)`,tL=`[\\s|\\(]+(${eL})[,|\\s]+(${eL})[,|\\s]+(${eL})\\s*\\)?`,nL=`[\\s|\\(]+(${eL})[,|\\s]+(${eL})[,|\\s]+(${eL})[,|\\s]+(${eL})\\s*\\)?`,rL={CSS_UNIT:new RegExp(eL),rgb:RegExp(`rgb`+tL),rgba:RegExp(`rgba`+nL),hsl:RegExp(`hsl`+tL),hsla:RegExp(`hsla`+nL),hsv:RegExp(`hsv`+tL),hsva:RegExp(`hsva`+nL),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/};function iL(e){if(e=e.trim().toLowerCase(),e.length===0)return!1;var t=!1;if(QI[e])e=QI[e],t=!0;else if(e===`transparent`)return{r:0,g:0,b:0,a:0,format:`name`};var n=rL.rgb.exec(e);return n?{r:n[1],g:n[2],b:n[3]}:(n=rL.rgba.exec(e),n?{r:n[1],g:n[2],b:n[3],a:n[4]}:(n=rL.hsl.exec(e),n?{h:n[1],s:n[2],l:n[3]}:(n=rL.hsla.exec(e),n?{h:n[1],s:n[2],l:n[3],a:n[4]}:(n=rL.hsv.exec(e),n?{h:n[1],s:n[2],v:n[3]}:(n=rL.hsva.exec(e),n?{h:n[1],s:n[2],v:n[3],a:n[4]}:(n=rL.hex8.exec(e),n?{r:XI(n[1]),g:XI(n[2]),b:XI(n[3]),a:YI(n[4]),format:t?`name`:`hex8`}:(n=rL.hex6.exec(e),n?{r:XI(n[1]),g:XI(n[2]),b:XI(n[3]),format:t?`name`:`hex`}:(n=rL.hex4.exec(e),n?{r:XI(n[1]+n[1]),g:XI(n[2]+n[2]),b:XI(n[3]+n[3]),a:YI(n[4]+n[4]),format:t?`name`:`hex8`}:(n=rL.hex3.exec(e),n?{r:XI(n[1]+n[1]),g:XI(n[2]+n[2]),b:XI(n[3]+n[3]),format:t?`name`:`hex`}:!1)))))))))}function aL(e){return!!rL.CSS_UNIT.exec(String(e))}var oL=function(){function e(t,n){if(t===void 0&&(t=``),n===void 0&&(n={}),t instanceof e)return t;typeof t==`number`&&(t=ZI(t)),this.originalInput=t;var r=$I(t);this.originalInput=t,this.r=r.r,this.g=r.g,this.b=r.b,this.a=r.a,this.roundA=Math.round(100*this.a)/100,this.format=n.format??r.format,this.gradientType=n.gradientType,this.r<1&&(this.r=Math.round(this.r)),this.g<1&&(this.g=Math.round(this.g)),this.b<1&&(this.b=Math.round(this.b)),this.isValid=r.ok}return e.prototype.isDark=function(){return this.getBrightness()<128},e.prototype.isLight=function(){return!this.isDark()},e.prototype.getBrightness=function(){var e=this.toRgb();return(e.r*299+e.g*587+e.b*114)/1e3},e.prototype.getLuminance=function(){var e=this.toRgb(),t,n,r,i=e.r/255,a=e.g/255,o=e.b/255;return t=i<=.03928?i/12.92:((i+.055)/1.055)**2.4,n=a<=.03928?a/12.92:((a+.055)/1.055)**2.4,r=o<=.03928?o/12.92:((o+.055)/1.055)**2.4,.2126*t+.7152*n+.0722*r},e.prototype.getAlpha=function(){return this.a},e.prototype.setAlpha=function(e){return this.a=LI(e),this.roundA=Math.round(100*this.a)/100,this},e.prototype.isMonochrome=function(){return this.toHsl().s===0},e.prototype.toHsv=function(){var e=WI(this.r,this.g,this.b);return{h:e.h*360,s:e.s,v:e.v,a:this.a}},e.prototype.toHsvString=function(){var e=WI(this.r,this.g,this.b),t=Math.round(e.h*360),n=Math.round(e.s*100),r=Math.round(e.v*100);return this.a===1?`hsv(${t}, ${n}%, ${r}%)`:`hsva(${t}, ${n}%, ${r}%, ${this.roundA})`},e.prototype.toHsl=function(){var e=VI(this.r,this.g,this.b);return{h:e.h*360,s:e.s,l:e.l,a:this.a}},e.prototype.toHslString=function(){var e=VI(this.r,this.g,this.b),t=Math.round(e.h*360),n=Math.round(e.s*100),r=Math.round(e.l*100);return this.a===1?`hsl(${t}, ${n}%, ${r}%)`:`hsla(${t}, ${n}%, ${r}%, ${this.roundA})`},e.prototype.toHex=function(e){return e===void 0&&(e=!1),KI(this.r,this.g,this.b,e)},e.prototype.toHexString=function(e){return e===void 0&&(e=!1),`#`+this.toHex(e)},e.prototype.toHex8=function(e){return e===void 0&&(e=!1),qI(this.r,this.g,this.b,this.a,e)},e.prototype.toHex8String=function(e){return e===void 0&&(e=!1),`#`+this.toHex8(e)},e.prototype.toHexShortString=function(e){return e===void 0&&(e=!1),this.a===1?this.toHexString(e):this.toHex8String(e)},e.prototype.toRgb=function(){return{r:Math.round(this.r),g:Math.round(this.g),b:Math.round(this.b),a:this.a}},e.prototype.toRgbString=function(){var e=Math.round(this.r),t=Math.round(this.g),n=Math.round(this.b);return this.a===1?`rgb(${e}, ${t}, ${n})`:`rgba(${e}, ${t}, ${n}, ${this.roundA})`},e.prototype.toPercentageRgb=function(){var e=function(e){return`${Math.round(NI(e,255)*100)}%`};return{r:e(this.r),g:e(this.g),b:e(this.b),a:this.a}},e.prototype.toPercentageRgbString=function(){var e=function(e){return Math.round(NI(e,255)*100)};return this.a===1?`rgb(${e(this.r)}%, ${e(this.g)}%, ${e(this.b)}%)`:`rgba(${e(this.r)}%, ${e(this.g)}%, ${e(this.b)}%, ${this.roundA})`},e.prototype.toName=function(){if(this.a===0)return`transparent`;if(this.a<1)return!1;for(var e=`#`+KI(this.r,this.g,this.b,!1),t=0,n=Object.entries(QI);t<n.length;t++){var r=n[t],i=r[0];if(e===r[1])return i}return!1},e.prototype.toString=function(e){var t=!!e;e??=this.format;var n=!1,r=this.a<1&&this.a>=0;return!t&&r&&(e.startsWith(`hex`)||e===`name`)?e===`name`&&this.a===0?this.toName():this.toRgbString():(e===`rgb`&&(n=this.toRgbString()),e===`prgb`&&(n=this.toPercentageRgbString()),(e===`hex`||e===`hex6`)&&(n=this.toHexString()),e===`hex3`&&(n=this.toHexString(!0)),e===`hex4`&&(n=this.toHex8String(!0)),e===`hex8`&&(n=this.toHex8String()),e===`name`&&(n=this.toName()),e===`hsl`&&(n=this.toHslString()),e===`hsv`&&(n=this.toHsvString()),n||this.toHexString())},e.prototype.toNumber=function(){return(Math.round(this.r)<<16)+(Math.round(this.g)<<8)+Math.round(this.b)},e.prototype.clone=function(){return new e(this.toString())},e.prototype.lighten=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.l+=t/100,n.l=PI(n.l),new e(n)},e.prototype.brighten=function(t){t===void 0&&(t=10);var n=this.toRgb();return n.r=Math.max(0,Math.min(255,n.r-Math.round(255*-(t/100)))),n.g=Math.max(0,Math.min(255,n.g-Math.round(255*-(t/100)))),n.b=Math.max(0,Math.min(255,n.b-Math.round(255*-(t/100)))),new e(n)},e.prototype.darken=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.l-=t/100,n.l=PI(n.l),new e(n)},e.prototype.tint=function(e){return e===void 0&&(e=10),this.mix(`white`,e)},e.prototype.shade=function(e){return e===void 0&&(e=10),this.mix(`black`,e)},e.prototype.desaturate=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.s-=t/100,n.s=PI(n.s),new e(n)},e.prototype.saturate=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.s+=t/100,n.s=PI(n.s),new e(n)},e.prototype.greyscale=function(){return this.desaturate(100)},e.prototype.spin=function(t){var n=this.toHsl(),r=(n.h+t)%360;return n.h=r<0?360+r:r,new e(n)},e.prototype.mix=function(t,n){n===void 0&&(n=50);var r=this.toRgb(),i=new e(t).toRgb(),a=n/100;return new e({r:(i.r-r.r)*a+r.r,g:(i.g-r.g)*a+r.g,b:(i.b-r.b)*a+r.b,a:(i.a-r.a)*a+r.a})},e.prototype.analogous=function(t,n){t===void 0&&(t=6),n===void 0&&(n=30);var r=this.toHsl(),i=360/n,a=[this];for(r.h=(r.h-(i*t>>1)+720)%360;--t;)r.h=(r.h+i)%360,a.push(new e(r));return a},e.prototype.complement=function(){var t=this.toHsl();return t.h=(t.h+180)%360,new e(t)},e.prototype.monochromatic=function(t){t===void 0&&(t=6);for(var n=this.toHsv(),r=n.h,i=n.s,a=n.v,o=[],s=1/t;t--;)o.push(new e({h:r,s:i,v:a})),a=(a+s)%1;return o},e.prototype.splitcomplement=function(){var t=this.toHsl(),n=t.h;return[this,new e({h:(n+72)%360,s:t.s,l:t.l}),new e({h:(n+216)%360,s:t.s,l:t.l})]},e.prototype.onBackground=function(t){var n=this.toRgb(),r=new e(t).toRgb(),i=n.a+r.a*(1-n.a);return new e({r:(n.r*n.a+r.r*r.a*(1-n.a))/i,g:(n.g*n.a+r.g*r.a*(1-n.a))/i,b:(n.b*n.a+r.b*r.a*(1-n.a))/i,a:i})},e.prototype.triad=function(){return this.polyad(3)},e.prototype.tetrad=function(){return this.polyad(4)},e.prototype.polyad=function(t){for(var n=this.toHsl(),r=n.h,i=[this],a=360/t,o=1;o<t;o++)i.push(new e({h:(r+o*a)%360,s:n.s,l:n.l}));return i},e.prototype.equals=function(t){return this.toRgbString()===new e(t).toRgbString()},e}();function sL(...e){return new oL(...e)}function cL(e,t){let n=e&&e.a,r;r=e&&e.hsl?sL(e.hsl):e&&e.hex&&e.hex.length>0?sL(e.hex):e&&e.hsv?sL(e.hsv):e&&e.rgba?sL(e.rgba):e&&e.rgb?sL(e.rgb):sL(e),r&&(r._a===void 0||r._a===null)&&r.setAlpha(n||r.getAlpha());let i=r.toHsl(),a=r.toHsv();return i.s===0&&(a.h=i.h=e.h||e.hsl&&e.hsl.h||t||0),a.v<.0164&&(a.h=e.h||e.hsv&&e.hsv.h||0,a.s=e.s||e.hsv&&e.hsv.s||0),i.l<.01&&(i.h=e.h||e.hsl&&e.hsl.h||0,i.s=e.s||e.hsl&&e.hsl.s||0),{hsl:i,hex:r.toHexString().toUpperCase(),hex8:r.toHex8String().toUpperCase(),rgba:r.toRgb(),hsv:a,oldHue:e.h||t||i.h,source:e.source,a:r.getAlpha()}}var lL={model:{prop:`modelValue`,event:`update:modelValue`},props:[`modelValue`],data(){return{val:cL(this.modelValue)}},computed:{colors:{get(){return this.val},set(e){this.val=e,this.$emit(`update:modelValue`,e)}}},watch:{modelValue(e){this.val=cL(e)}},methods:{colorChange(e,t){this.oldHue=this.colors.hsl.h,this.colors=cL(e,t||this.oldHue)},isValidHex(e){return sL(e).isValid},simpleCheckForValidColor(e){let t=[`r`,`g`,`b`,`a`,`h`,`s`,`l`,`v`],n=0,r=0;for(let i=0;i<t.length;i++){let a=t[i];e[a]&&(n++,isNaN(e[a])||r++)}if(n===r)return e},paletteUpperCase(e){return e.map(e=>e.toUpperCase())},isTransparent(e){return sL(e).getAlpha()===0}}},uL={name:`EditableInput`,props:{label:String,labelText:String,desc:String,value:[String,Number],max:Number,min:Number,arrowOffset:{type:Number,default:1}},computed:{val:{get(){return this.value},set(e){if(this.max!==void 0&&+e>this.max)this.$refs.input.value=this.max;else return e}},labelId(){return`input__label__${this.label}__${Math.random().toString().slice(2,5)}`},labelSpanText(){return this.labelText||this.label}},methods:{update(e){this.handleChange(e.target.value)},handleChange(e){let t={};t[this.label]=e,(t.hex===void 0&&t[`#`]===void 0||e.length>5)&&this.$emit(`change`,t)},handleKeyDown(e){let{val:t}=this,n=Number(t);if(n){let r=this.arrowOffset||1;e.keyCode===38&&(t=n+r,this.handleChange(t),e.preventDefault()),e.keyCode===40&&(t=n-r,this.handleChange(t),e.preventDefault())}}}},dL={class:`vc-editable-input`},fL=[`aria-labelledby`],pL=[`id`,`for`],mL={class:`vc-input__desc`};function hL(e,t,n,r,i,a){return B(),V(`div`,dL,[I(U(`input`,{ref:`input`,"onUpdate:modelValue":t[0]||=e=>a.val=e,"aria-labelledby":a.labelId,class:`vc-input__input`,onKeydown:t[1]||=(...e)=>a.handleKeyDown&&a.handleKeyDown(...e),onInput:t[2]||=(...e)=>a.update&&a.update(...e)},null,40,fL),[[il,a.val]]),U(`span`,{id:a.labelId,for:n.label,class:`vc-input__label`},M(a.labelSpanText),9,pL),U(`span`,mL,M(n.desc),1)])}xI(`.vc-editable-input{position:relative}.vc-input__input{border:0;outline:none;padding:0}.vc-input__label{text-transform:capitalize}`),uL.render=hL,uL.__file=`src/components/editable-input/editable-input.vue`,uL.install=SI;function gL(e,t,n){return t<n?e<t?t:e>n?n:e:e<n?n:e>t?t:e}var _L={name:`Saturation`,props:{value:Object},computed:{colors(){return this.value},bgColor(){return`hsl(${this.colors.hsv.h}, 100%, 50%)`},pointerTop(){return`${-(this.colors.hsv.v*100)+1+100}%`},pointerLeft(){return`${this.colors.hsv.s*100}%`}},methods:{handleChange(e,t){!t&&e.preventDefault();let{container:n}=this.$refs;if(!n)return;let r=n.clientWidth,i=n.clientHeight,a=n.getBoundingClientRect().left+window.pageXOffset,o=n.getBoundingClientRect().top+window.pageYOffset,s=e.pageX||(e.touches?e.touches[0].pageX:0),c=e.pageY||(e.touches?e.touches[0].pageY:0),l=gL(s-a,0,r),u=gL(c-o,0,i),d=l/r,f=gL(-(u/i)+1,0,1);this.onChange({h:this.colors.hsv.h,s:d,v:f,a:this.colors.hsv.a,source:`hsva`})},onChange(e){this.$emit(`change`,e)},handleMouseDown(e){window.addEventListener(`mousemove`,this.handleChange),window.addEventListener(`mouseup`,this.handleChange),window.addEventListener(`mouseup`,this.handleMouseUp)},handleMouseUp(e){this.unbindEventListeners()},unbindEventListeners(){window.removeEventListener(`mousemove`,this.handleChange),window.removeEventListener(`mouseup`,this.handleChange),window.removeEventListener(`mouseup`,this.handleMouseUp)}}},vL=U(`div`,{class:`vc-saturation--white`},null,-1),yL=U(`div`,{class:`vc-saturation--black`},null,-1),bL=[U(`div`,{class:`vc-saturation-circle`},null,-1)];function xL(e,t,n,r,i,a){return B(),V(`div`,{ref:`container`,class:`vc-saturation`,style:A({background:a.bgColor}),onMousedown:t[0]||=(...e)=>a.handleMouseDown&&a.handleMouseDown(...e),onTouchmove:t[1]||=(...e)=>a.handleChange&&a.handleChange(...e),onTouchstart:t[2]||=(...e)=>a.handleChange&&a.handleChange(...e)},[vL,yL,U(`div`,{class:`vc-saturation-pointer`,style:A({top:a.pointerTop,left:a.pointerLeft})},bL,4)],36)}xI(`.vc-saturation,.vc-saturation--black,.vc-saturation--white{bottom:0;cursor:pointer;left:0;position:absolute;right:0;top:0}.vc-saturation--white{background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.vc-saturation--black{background:linear-gradient(0deg,#000,transparent)}.vc-saturation-pointer{cursor:pointer;position:absolute}.vc-saturation-circle{border-radius:50%;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);cursor:head;height:4px;transform:translate(-2px,-2px);width:4px}`),_L.render=xL,_L.__file=`src/components/saturation/saturation.vue`,_L.install=SI;var SL={name:`Hue`,props:{value:Object,direction:{type:String,default:`horizontal`}},data(){return{oldHue:0,pullDirection:``}},computed:{colors(){return this.value},directionClass(){return{"vc-hue--horizontal":this.direction===`horizontal`,"vc-hue--vertical":this.direction===`vertical`}},pointerTop(){return this.direction===`vertical`?this.colors.hsl.h===0&&this.pullDirection===`right`?0:`${-(this.colors.hsl.h*100/360)+100}%`:0},pointerLeft(){return this.direction===`vertical`?0:this.colors.hsl.h===0&&this.pullDirection===`right`?`100%`:`${this.colors.hsl.h*100/360}%`}},watch:{value:{handler(e,t){let{h:n}=e.hsl;n!==0&&n-this.oldHue>0&&(this.pullDirection=`right`),n!==0&&n-this.oldHue<0&&(this.pullDirection=`left`),this.oldHue=n},deep:!0,immediate:!0}},methods:{handleChange(e,t){!t&&e.preventDefault();let{container:n}=this.$refs;if(!n)return;let r=n.clientWidth,i=n.clientHeight,a=n.getBoundingClientRect().left+window.pageXOffset,o=n.getBoundingClientRect().top+window.pageYOffset,s=e.pageX||(e.touches?e.touches[0].pageX:0),c=e.pageY||(e.touches?e.touches[0].pageY:0),l=s-a,u=c-o,d,f;this.direction===`vertical`?(u<0?d=360:u>i?d=0:(f=-(u*100/i)+100,d=360*f/100),this.colors.hsl.h!==d&&this.$emit(`change`,{h:d,s:this.colors.hsl.s,l:this.colors.hsl.l,a:this.colors.hsl.a,source:`hsl`})):(l<0?d=0:l>r?d=360:(f=l*100/r,d=360*f/100),this.colors.hsl.h!==d&&this.$emit(`change`,{h:d,s:this.colors.hsl.s,l:this.colors.hsl.l,a:this.colors.hsl.a,source:`hsl`}))},handleMouseDown(e){this.handleChange(e,!0),window.addEventListener(`mousemove`,this.handleChange),window.addEventListener(`mouseup`,this.handleChange),window.addEventListener(`mouseup`,this.handleMouseUp)},handleMouseUp(e){this.unbindEventListeners()},unbindEventListeners(){window.removeEventListener(`mousemove`,this.handleChange),window.removeEventListener(`mouseup`,this.handleChange),window.removeEventListener(`mouseup`,this.handleMouseUp)}}},CL=[`aria-valuenow`],wL=[U(`div`,{class:`vc-hue-picker`},null,-1)];function TL(e,t,n,r,i,a){return B(),V(`div`,{class:j([`vc-hue`,[a.directionClass]])},[U(`div`,{ref:`container`,class:`vc-hue-container`,role:`slider`,"aria-valuenow":a.colors.hsl.h,"aria-valuemin":`0`,"aria-valuemax":`360`,onMousedown:t[0]||=(...e)=>a.handleMouseDown&&a.handleMouseDown(...e),onTouchmove:t[1]||=(...e)=>a.handleChange&&a.handleChange(...e),onTouchstart:t[2]||=(...e)=>a.handleChange&&a.handleChange(...e)},[U(`div`,{class:`vc-hue-pointer`,style:A({top:a.pointerTop,left:a.pointerLeft}),role:`presentation`},wL,4)],40,CL)],2)}xI(`.vc-hue{border-radius:2px;bottom:0;left:0;position:absolute;right:0;top:0}.vc-hue--horizontal{background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.vc-hue--vertical{background:linear-gradient(0deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.vc-hue-container{cursor:pointer;height:100%;margin:0 2px;position:relative}.vc-hue-pointer{position:absolute;z-index:2}.vc-hue-picker{background:#fff;border-radius:1px;box-shadow:0 0 2px rgba(0,0,0,.6);cursor:pointer;height:8px;margin-top:1px;transform:translateX(-2px);width:4px}`),SL.render=TL,SL.__file=`src/components/hue/hue.vue`,SL.install=SI;var EL=[`#D0021B`,`#F5A623`,`#F8E71C`,`#8B572A`,`#7ED321`,`#417505`,`#BD10E0`,`#9013FE`,`#4A90E2`,`#50E3C2`,`#B8E986`,`#000000`,`#4A4A4A`,`#9B9B9B`,`#FFFFFF`,`rgba(0,0,0,0)`],DL={name:`Sketch`,components:{Saturation:_L,Hue:SL,Alpha:OI,EdIn:uL,Checkboard:wI},mixins:[lL],props:{presetColors:{type:Array,default(){return EL}},disableAlpha:{type:Boolean,default:!1},disableFields:{type:Boolean,default:!1}},computed:{hex(){let e;return e=this.colors.a<1?this.colors.hex8:this.colors.hex,e.replace(`#`,``)},activeColor(){let{rgba:e}=this.colors;return`rgba(${[e.r,e.g,e.b,e.a].join(`,`)})`}},methods:{handlePreset(e){this.colorChange(e)},childChange(e){this.colorChange(e)},inputChange(e){e&&(e.hex?this.isValidHex(e.hex)&&this.colorChange({hex:e.hex,source:`hex`}):(e.r||e.g||e.b||e.a)&&this.colorChange({r:e.r||this.colors.rgba.r,g:e.g||this.colors.rgba.g,b:e.b||this.colors.rgba.b,a:e.a||this.colors.rgba.a,source:`rgba`}))}}},OL={class:`vc-sketch-saturation-wrap`},kL={class:`vc-sketch-controls`},AL={class:`vc-sketch-sliders`},jL={class:`vc-sketch-hue-wrap`},ML={key:0,class:`vc-sketch-alpha-wrap`},NL={class:`vc-sketch-color-wrap`},PL=[`aria-label`],FL={key:0,class:`vc-sketch-field`},IL={class:`vc-sketch-field--double`},LL={class:`vc-sketch-field--single`},RL={class:`vc-sketch-field--single`},zL={class:`vc-sketch-field--single`},BL={key:0,class:`vc-sketch-field--single`},VL={class:`vc-sketch-presets`,role:`group`,"aria-label":`A color preset, pick one to set as current color`},HL=[`aria-label`,`onClick`],UL=[`aria-label`,`onClick`];function WL(e,t,n,r,i,a){let o=L(`Saturation`),s=L(`Hue`),c=L(`Alpha`),l=L(`Checkboard`),u=L(`EdIn`);return B(),V(`div`,{role:`application`,"aria-label":`Sketch color picker`,class:j([`vc-sketch`,[n.disableAlpha?`vc-sketch__disable-alpha`:``]])},[U(`div`,OL,[W(o,{value:e.colors,onChange:a.childChange},null,8,[`value`,`onChange`])]),U(`div`,kL,[U(`div`,AL,[U(`div`,jL,[W(s,{value:e.colors,onChange:a.childChange},null,8,[`value`,`onChange`])]),n.disableAlpha?K(`v-if`,!0):(B(),V(`div`,ML,[W(c,{value:e.colors,onChange:a.childChange},null,8,[`value`,`onChange`])]))]),U(`div`,NL,[U(`div`,{"aria-label":`Current color is ${a.activeColor}`,class:`vc-sketch-active-color`,style:A({background:a.activeColor})},null,12,PL),W(l)])]),n.disableFields?K(`v-if`,!0):(B(),V(`div`,FL,[K(` rgba `),U(`div`,IL,[W(u,{label:`hex`,value:a.hex,onChange:a.inputChange},null,8,[`value`,`onChange`])]),U(`div`,LL,[W(u,{label:`r`,value:e.colors.rgba.r,onChange:a.inputChange},null,8,[`value`,`onChange`])]),U(`div`,RL,[W(u,{label:`g`,value:e.colors.rgba.g,onChange:a.inputChange},null,8,[`value`,`onChange`])]),U(`div`,zL,[W(u,{label:`b`,value:e.colors.rgba.b,onChange:a.inputChange},null,8,[`value`,`onChange`])]),n.disableAlpha?K(`v-if`,!0):(B(),V(`div`,BL,[W(u,{label:`a`,value:e.colors.a,"arrow-offset":.01,max:1,onChange:a.inputChange},null,8,[`value`,`arrow-offset`,`onChange`])]))])),U(`div`,VL,[(B(!0),V(z,null,R(n.presetColors,t=>(B(),V(z,null,[e.isTransparent(t)?(B(),V(`div`,{key:t,"aria-label":`Color:${t}`,class:`vc-sketch-presets-color`,onClick:e=>a.handlePreset(t)},[W(l)],8,UL)):(B(),V(`div`,{key:`!${t}`,class:`vc-sketch-presets-color`,"aria-label":`Color:${t}`,style:A({background:t}),onClick:e=>a.handlePreset(t)},null,12,HL))],64))),256))])],2)}xI(`.vc-sketch{background:#fff;border-radius:4px;box-shadow:0 0 0 1px rgba(0,0,0,.15),0 8px 16px rgba(0,0,0,.15);box-sizing:initial;padding:10px 10px 0;position:relative;width:200px}.vc-sketch-saturation-wrap{overflow:hidden;padding-bottom:75%;position:relative;width:100%}.vc-sketch-controls{display:flex}.vc-sketch-sliders{flex:1;padding:4px 0}.vc-sketch-sliders .vc-alpha-gradient,.vc-sketch-sliders .vc-hue{border-radius:2px}.vc-sketch-alpha-wrap,.vc-sketch-hue-wrap{height:10px;position:relative}.vc-sketch-alpha-wrap{margin-top:4px;overflow:hidden}.vc-sketch-color-wrap{border-radius:3px;height:24px;margin-left:4px;margin-top:4px;position:relative;width:24px}.vc-sketch-active-color{border-radius:2px;bottom:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15),inset 0 0 4px rgba(0,0,0,.25);left:0;position:absolute;right:0;top:0;z-index:2}.vc-sketch-color-wrap .vc-checkerboard{background-size:auto}.vc-sketch-field{display:flex;padding-top:4px}.vc-sketch-field .vc-input__input{border:none;box-shadow:inset 0 0 0 1px #ccc;font-size:10px;padding:4px 0 3px 10%;width:90%}.vc-sketch-field .vc-input__label{color:#222;display:block;font-size:11px;padding-bottom:4px;padding-top:3px;text-align:center;text-transform:capitalize}.vc-sketch-field--single{flex:1;padding-left:6px}.vc-sketch-field--double{flex:2}.vc-sketch-presets{border-top:1px solid #eee;margin-left:-10px;margin-right:-10px;padding-left:10px;padding-top:10px}.vc-sketch-presets-color{cursor:pointer;display:inline-block;height:16px;margin:0 10px 10px 0;overflow:hidden;position:relative;vertical-align:top;width:16px}.vc-sketch-presets-color,.vc-sketch-presets-color .vc-checkerboard{border-radius:3px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}.vc-sketch__disable-alpha .vc-sketch-color-wrap{height:10px}`),DL.render=WL,DL.__file=`src/components/sketch/sketch.vue`,DL.install=SI;function GL(e){let t=String(e||``).trim();if(!t)return null;let n=t.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:1};if(n=t.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i),n){let e=e=>parseInt(e+e,16);return{r:e(n[1]),g:e(n[2]),b:e(n[3]),a:1}}if(n=t.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i),n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:parseInt(n[4],16)/255};if(n=t.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)$/i),n){let e=n[4]===void 0?1:parseFloat(n[4]);return{r:Math.round(parseFloat(n[1])),g:Math.round(parseFloat(n[2])),b:Math.round(parseFloat(n[3])),a:e}}return null}function KL(e){if(!e)return`#000000`;let t=e=>Math.max(0,Math.min(255,Math.round(e))).toString(16).padStart(2,`0`);return`#`+t(e.r)+t(e.g)+t(e.b)}function qL(e){return e?e.a>=1?KL(e):`rgba(${Math.round(e.r)}, ${Math.round(e.g)}, ${Math.round(e.b)}, ${+e.a.toFixed(2)})`:``}var JL={name:`SetColor`,components:{Sketch:DL},props:jg,emits:Mg,data(){return{_rgb:null,popOpen:!1,popW:240,popStyle:{position:`fixed`,left:`0px`,top:`0px`}}},computed:{text(){return this.value===void 0||this.value===null?``:String(this.value)},parsed(){return GL(this.text)||{r:0,g:0,b:0,a:1}},pickerValue(){return this.text||`#000000`},alpha(){return this.parsed.a},displayColor(){return qL(this.parsed)}},watch:{text(){this._rgb=GL(this.text)}},beforeUnmount(){this.removeDocListener()},methods:{onTextInput(e){this._rgb=GL(e),this.$emit(`input`,e)},onAlphaChange(e){let t=Math.max(0,Math.min(1,parseInt(e,10)/100)),n={...this._rgb||this.parsed,a:t};this._rgb=n,this.$emit(`input`,qL(n)),this.$emit(`change`)},onPicker(e){let t=e&&e.rgba,n,r,i,a;if(Array.isArray(t))[n,r,i,a]=t;else if(t)n=t.r,r=t.g,i=t.b,a=t.a;else{let t=GL(e.hex)||{r:0,g:0,b:0,a:1};n=t.r,r=t.g,i=t.b,a=t.a}a??=1;let o=e.hex||KL({r:n,g:r,b:i,a:1});this._rgb={r:n,g:r,b:i,a},this.$emit(`input`,a>=1?o:`rgba(${Math.round(n)}, ${Math.round(r)}, ${Math.round(i)}, ${+a.toFixed(2)})`),this.$emit(`change`)},clear(){this.disabled||(this._rgb=null,this.closePop(),this.$emit(`input`,``),this.$emit(`change`))},togglePop(){this.disabled||(this.popOpen?this.closePop():this.openPop())},openPop(){let e=this.$refs.swatch;if(!e)return;let t=e.getBoundingClientRect(),n=this.$refs.top&&this.$refs.top.getBoundingClientRect()||t,r=Math.max(220,Math.min(Math.round(n.width),400)),i=window.innerWidth,a=window.innerHeight,o=n.left,s=t.bottom+6;o+r>i-8&&(o=Math.max(8,i-r-8)),s+320>a-8&&(s=Math.max(8,t.top-320-6)),this.popW=r,this.popStyle={position:`fixed`,left:o+`px`,top:s+`px`,width:r+`px`,zIndex:4e3},this.popOpen=!0,this.$nextTick(()=>{document.addEventListener(`mousedown`,this.onDocClick,!0)})},closePop(){this.popOpen&&(this.popOpen=!1,this.removeDocListener())},removeDocListener(){document.removeEventListener(`mousedown`,this.onDocClick,!0)},onDocClick(e){let t=this.$refs.pop,n=this.$refs.swatch;t&&t.contains(e.target)||n&&n.contains(e.target)||this.closePop()}}},YL={class:`st-color`},XL={class:`st-color__top`,ref:`top`},ZL=[`title`,`disabled`],QL=[`disabled`,`value`],$L=[`disabled`],eR={key:0,class:`st-color__alpha-row`},tR=[`disabled`,`value`],nR={class:`st-color__alpha-val`};function rR(e,t,n,r,i,a){let o=L(`Sketch`);return B(),V(`div`,YL,[K(` 色块预览 + 文本输入 + 重置(顶行) `),U(`div`,XL,[U(`button`,{ref:`swatch`,class:`st-color__swatch`,type:`button`,title:a.text||`未设置`,disabled:e.disabled,onClick:t[0]||=(...e)=>a.togglePop&&a.togglePop(...e)},[t[7]||=U(`span`,{class:`st-color__checker`},null,-1),U(`span`,{class:`st-color__fill`,style:A({background:a.displayColor||`transparent`})},null,4)],8,ZL),U(`input`,{class:`ni-input st-color__text`,type:`text`,placeholder:`如 #333333 / rgba(0,0,0,.5)`,disabled:e.disabled,value:a.text,onInput:t[1]||=e=>a.onTextInput(e.target.value),onChange:t[2]||=t=>e.$emit(`change`)},null,40,QL),U(`button`,{class:`st-color__clear`,type:`button`,title:`重置(清空颜色)`,disabled:e.disabled,onClick:t[3]||=(...e)=>a.clear&&a.clear(...e)},[...t[8]||=[U(`svg`,{viewBox:`0 0 16 16`,class:`st-ic`,"aria-hidden":`true`},[U(`use`,{href:`#icon-reset`})],-1)]],8,$L)],512),K(` 透明度滑块(仅当颜色值非空时显示),作为快捷调节 `),a.text?(B(),V(`div`,eR,[t[9]||=U(`span`,{class:`st-color__alpha-label`},`透明度`,-1),U(`input`,{class:`st-color__alpha-slider`,type:`range`,min:`0`,max:`100`,disabled:e.disabled,value:Math.round(a.alpha*100),onInput:t[4]||=e=>a.onAlphaChange(e.target.value),onChange:t[5]||=t=>e.$emit(`change`)},null,40,tR),U(`span`,nR,M(Math.round(a.alpha*100))+`%`,1)])):K(`v-if`,!0),K(` 第三方颜色选择器弹层(挂载到 body,避免被滚动容器裁切) `),(B(),H(ai,{to:`body`},[i.popOpen?(B(),V(`div`,{key:0,ref:`pop`,class:`st-color__pop`,style:A(i.popStyle),onMousedown:t[6]||=q(()=>{},[`stop`])},[W(o,{"model-value":a.pickerValue,"disable-alpha":!1,"onUpdate:modelValue":a.onPicker},null,8,[`model-value`,`onUpdate:modelValue`])],36)):K(`v-if`,!0)]))])}var iR=X(JL,[[`render`,rR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetColor.vue`]]),aR={name:`SetIconSelect`,components:{SvgSymbols:xd},props:jg,emits:Mg,data(){return{open:!1}},computed:{list(){return this.options.iIconList||[]}},methods:{pick(e){this.disabled||(this.open=!1,this.$emit(`input`,e.key),this.$emit(`change`))}}},oR={class:`st-iconsel-wrap`},sR={class:`st-iconsel`},cR={class:`st-iconsel__preview`},lR={key:1,style:{"font-size":`11px`,color:`var(--text-faint)`}},uR=[`disabled`,`value`],dR={key:0,class:`st-iconsel__grid`},fR=[`title`,`onClick`],pR={key:0,class:`st-list__empty`};function mR(e,t,n,r,i,a){let o=L(`SvgSymbols`);return B(),V(`div`,oR,[U(`div`,sR,[U(`span`,cR,[e.value?(B(),H(o,{key:0,icon:String(e.value),color:`currentColor`},null,8,[`icon`])):(B(),V(`span`,lR,`无`))]),U(`input`,{class:`ni-input`,type:`text`,placeholder:`图标 key`,disabled:e.disabled,value:e.value||``,onInput:t[0]||=t=>e.$emit(`input`,t.target.value),onChange:t[1]||=t=>e.$emit(`change`)},null,40,uR),U(`button`,{class:`st-minibtn`,type:`button`,onClick:t[2]||=e=>i.open=!i.open},M(i.open?`收起`:`选择`),1)]),i.open?(B(),V(`div`,dR,[(B(!0),V(z,null,R(a.list,t=>(B(),V(`span`,{key:t.key,class:j([`st-iconsel__cell`,{"st-iconsel__cell--on":t.key===e.value}]),title:t.name||t.value||t.key,onClick:e=>a.pick(t)},[W(o,{icon:t.key,color:`currentColor`},null,8,[`icon`])],10,fR))),128)),a.list.length?K(`v-if`,!0):(B(),V(`p`,pR,`该组件未提供图标列表`))])):K(`v-if`,!0)])}var hR=X(aR,[[`render`,mR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetIconSelect.vue`]]);Prism.languages.javascript=Prism.languages.extend(`clike`,{"class-name":[Prism.languages.clike[`class-name`],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(`(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])`),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript[`class-name`][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore(`javascript`,`keyword`,{regex:{pattern:RegExp(`((?:^|[^$\\w\\xA0-\\uFFFF."'\\])\\s]|\\b(?:return|yield))\\s*)\\/(?:(?:\\[(?:[^\\]\\\\\\r\\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/)*(?:$|[\\r\\n,.;:})\\]]|\\/\\/))`),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:`language-regex`,inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:`function`},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore(`javascript`,`string`,{hashbang:{pattern:/^#!.*/,greedy:!0,alias:`comment`},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:`string`},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:`punctuation`},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:`property`}}),Prism.languages.insertBefore(`javascript`,`operator`,{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:`property`}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined(`script`,`javascript`),Prism.languages.markup.tag.addAttribute(`on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)`,`javascript`)),Prism.languages.js=Prism.languages.javascript,Yg.default.languages.javascript&&!Yg.default.languages.javascript[`binding-var`]&&Yg.default.languages.insertBefore(`javascript`,`keyword`,{"binding-var":/\$[A-Za-z_$][\w$]*/});var gR={name:`SetExpr`,props:{...jg,placeholder:{type:String,default:``}},emits:Mg,data(){return{code:``}},computed:{lines(){return this.code?this.code.split(`
|
|
306
|
-
`).length:0},chars(){return this.code.length}},watch:{value(e){this.syncFromValue(e)}},mounted(){this.code=this.readValue(this.value),this.$nextTick(()=>this.initJar())},beforeUnmount(){this._t&&clearTimeout(this._t),this._jar&&this._jar.destroy&&this._jar.destroy()},methods:{readValue(e){return e==null?``:typeof e==`string`?e:String(e)},syncFromValue(e){let t=this.readValue(e);if(t===this.code)return;let n=this.$refs.editor;n&&document.activeElement===n||(this.code=t,this._jar&&this._jar.updateCode(t))},initJar(){let e=this.$refs.editor;if(!e)return;let t=e=>{e.innerHTML=Yg.default.highlight(e.textContent,Yg.default.languages.javascript,`javascript`)};this._jar=Jg(e,t,{tab:` `,indentOn:/[({[]$/,addClosing:!0,history:!0}),this._jar.updateCode(this.code),this._jar.onUpdate(e=>this.onCode(e))},onCode(e){this.disabled||(this.code=e,this.$emit(`input`,e),this._t&&clearTimeout(this._t),this._t=setTimeout(()=>this.$emit(`change`),400))}}},_R={key:0,class:`st-expr__ph`},vR={class:`st-expr__foot`},yR={class:`st-expr__hint`};function bR(e,t,n,r,i,a){return B(),V(`div`,{class:j([`st-expr`,{"st-expr--disabled":e.disabled}])},[U(`div`,{ref:`editor`,class:j([`st-expr__editor`,{"is-disabled":e.disabled}])},null,2),n.placeholder&&!i.code?(B(),V(`span`,_R,M(n.placeholder),1)):K(`v-if`,!0),U(`div`,vR,[U(`span`,yR,M(a.lines)+` 行 · `+M(a.chars)+` 字符`,1)])],2)}var xR=X(gR,[[`render`,bR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetExpr.vue`]]),SR={name:`SetIfForm`,components:{SetExpr:xR},props:jg,emits:Mg,computed:{obj(){return this.value&&typeof this.value==`object`?this.value:{}},expression(){return this.obj.expression||``},name(){return this.obj.name||``}},methods:{setExpression(e){let t=!this.name||this.name===this.expression;this.$emit(`input`,{name:t?e:this.name,expression:e})},setName(e){this.$emit(`input`,{name:e,expression:this.expression})}}},CR={class:`st-ifform`},wR=[`disabled`,`value`];function TR(e,t,n,r,i,a){let o=L(`SetExpr`);return B(),V(`div`,CR,[W(o,{value:a.expression,disabled:e.disabled,placeholder:`表达式,如 $singleMode 或 $data.count > 0`,onInput:a.setExpression,onChange:t[0]||=t=>e.$emit(`change`)},null,8,[`value`,`disabled`,`onInput`]),U(`input`,{class:`ni-input`,type:`text`,placeholder:`显示名(留空跟随表达式)`,disabled:e.disabled,value:a.name,onInput:t[1]||=e=>a.setName(e.target.value),onChange:t[2]||=t=>e.$emit(`change`)},null,40,wR)])}var ER=X(SR,[[`render`,TR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetIfForm.vue`]]),DR=[{key:`number`,value:`px`},{key:`percent`,value:`%`},{key:`auto`,value:`@`}],OR={name:`SetNumberStyle`,components:{SetNumber:pI},props:jg,emits:Mg,data(){return{unit:`number`,numValue:``,menuOpen:!1}},computed:{unitList(){return this.options.iTypeList||DR},unitLabel(){let e=this.unitList.filter(e=>e.key===this.unit)[0];return e?e.value:`px`},isAuto(){return this.unit===`auto`},numberOptions(){return{...this.options,type:this.unit===`percent`?`integer`:`float`,placeholder:this.options.placeholder||``,symbol:!0}}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=this.value;/%$/.test(String(e))?(this.unit=`percent`,this.numValue=String(e).replace(/%/g,``)):e===`auto`?(this.unit=`auto`,this.numValue=`auto`):(this.unit=`number`,this.numValue=e===0?`0`:e==null?``:String(e))},onNum(e){this.numValue=e,this.emit()},pickUnit(e){this.menuOpen=!1,this.unit=e,this.numValue=e===`percent`?`100`:e===`auto`?`auto`:``,this.emit(),this.$emit(`change`)},emit(){this.unit===`percent`&&this.numValue?this.$emit(`input`,this.numValue+`%`):this.$emit(`input`,this.numValue)}}},kR={class:`st-numberstyle`},AR={key:1,class:`st-pop st-pop--unit`},jR=[`onMousedown`];function MR(e,t,n,r,i,a){let o=L(`SetNumber`);return B(),V(`div`,kR,[W(o,{value:i.numValue,options:a.numberOptions,disabled:e.disabled||a.isAuto,onInput:a.onNum,onChange:t[1]||=t=>e.$emit(`change`)},{symbol:Lr(()=>[U(`span`,{class:`st-unit`,onMousedown:t[0]||=q(e=>i.menuOpen=!i.menuOpen,[`prevent`])},M(a.unitLabel),33)]),_:1},8,[`value`,`options`,`disabled`,`onInput`]),K(` 单位切换浮层:移到 .st-number 之外,避免被 overflow:hidden 裁切 `),i.menuOpen?(B(),V(`div`,{key:0,class:`st-pop-mask`,onMousedown:t[2]||=q(e=>i.menuOpen=!1,[`prevent`])},null,32)):K(`v-if`,!0),i.menuOpen?(B(),V(`div`,AR,[(B(!0),V(z,null,R(a.unitList,e=>(B(),V(`div`,{key:e.key,class:j([`st-pop__item`,{"st-pop__item--on":e.key===i.unit}]),onMousedown:q(t=>a.pickUnit(e.key),[`prevent`])},M(e.value),43,jR))),128))])):K(`v-if`,!0)])}var NR=X(OR,[[`render`,MR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetNumberStyle.vue`]]),PR={name:`SetPadding`,components:{SetNumber:pI},props:jg,emits:Mg,data(){return{form:{top:``,right:``,bottom:``,left:``}}},computed:{brackets(){return this.options.brackets||[`{`,`}`]},seperator(){return this.options.seperator||`,`}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``);this.brackets.length&&(e=e.replace(RegExp(`[${this.brackets.join(``)}]`,`g`),``));let t=e.split(this.seperator);this.form=this.options.normal?{top:t[0]||``,right:t[1]||``,bottom:t[2]||``,left:t[3]||``}:{top:t[0]||``,left:t[1]||``,bottom:t[2]||``,right:t[3]||``}},opt(e){return{type:`integer`,symbol:e,placeholder:`0`}},set(e,t){this.form[e]=t,this.emitValue()},emitValue(){let e=this.form,t=(this.options.normal?[e.top,e.right,e.bottom,e.left]:[e.top,e.left,e.bottom,e.right]).map(e=>e===``||e===void 0?`0`:e).join(this.seperator),[n,r]=this.brackets.length?this.brackets:[``,``];this.$emit(`input`,`${n||``}${t}${r||``}`)},emitOut(){this.$emit(`change`)}}},FR={class:`st-pad`};function IR(e,t,n,r,i,a){let o=L(`SetNumber`);return B(),V(`div`,FR,[W(o,{value:i.form.top,options:a.opt(`上`),disabled:e.disabled,onInput:t[0]||=e=>a.set(`top`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`]),W(o,{value:i.form.right,options:a.opt(`右`),disabled:e.disabled,onInput:t[1]||=e=>a.set(`right`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`]),W(o,{value:i.form.bottom,options:a.opt(`下`),disabled:e.disabled,onInput:t[2]||=e=>a.set(`bottom`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`]),W(o,{value:i.form.left,options:a.opt(`左`),disabled:e.disabled,onInput:t[3]||=e=>a.set(`left`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`])])}var LR=X(PR,[[`render`,IR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetPadding.vue`]]),RR=[{key:`TopLeft`,value:`上左`},{key:`TopCenter`,value:`上中`},{key:`TopRight`,value:`上右`},{key:`CenterLeft`,value:`中左`},{key:`Center`,value:`中间`},{key:`CenterRight`,value:`中右`},{key:`BottomLeft`,value:`下左`},{key:`BottomCenter`,value:`下中`},{key:`BottomRight`,value:`下右`}],zR=[{key:`0% 0%`,value:`左上对齐`},{key:`50% 0%`,value:`中上对齐`},{key:`100% 0%`,value:`右上对齐`},{key:`0% 50%`,value:`左中对齐`},{key:`50% 50%`,value:`居中对齐`},{key:`100% 50%`,value:`右中对齐`},{key:`0% 100%`,value:`左下对齐`},{key:`50% 100%`,value:`中下对齐`},{key:`100% 100%`,value:`右下对齐`}],BR={name:`SetGrid9`,props:{...jg,kind:{type:String,default:`PositionStyle`}},emits:Mg,computed:{cells(){return this.kind===`BackgroundPositionStyle`?zR:RR}},methods:{pick(e){this.disabled||(this.$emit(`input`,e.key),this.$emit(`change`))}}},VR={class:`st-grid9`},HR=[`title`,`onClick`];function UR(e,t,n,r,i,a){return B(),V(`div`,VR,[(B(!0),V(z,null,R(a.cells,n=>(B(),V(`div`,{key:n.key,class:j([`st-grid9__cell`,{"st-grid9__cell--on":String(n.key)===String(e.value)}]),title:n.value,onClick:e=>a.pick(n)},[...t[0]||=[U(`span`,{class:`st-grid9__dot`},null,-1)]],10,HR))),128))])}var WR=X(BR,[[`render`,UR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetGrid9.vue`]]),GR=[{key:`number`,value:`px`},{key:`percent`,value:`%`}],KR={name:`SetBgPosition`,components:{SetGrid9:WR,SetNumberStyle:NR},props:jg,emits:Mg,data(){return{x:``,y:``}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``).split(/\s+/);this.x=e[0]||``,this.y=e[1]||``},numOptions(e){return{placeholder:e,iTypeList:GR}},pickGrid(e){this.$emit(`input`,e)},setX(e){this.x=e,this.emitValue()},setY(e){this.y=e,this.emitValue()},emitValue(){this.$emit(`input`,`${this.x||`0`} ${this.y||`0`}`)},emitOut(){this.$emit(`change`)}}},qR={class:`st-bgpos`},JR={class:`st-bgpos__xy`};function YR(e,t,n,r,i,a){let o=L(`SetGrid9`),s=L(`SetNumberStyle`);return B(),V(`div`,qR,[W(o,{kind:`BackgroundPositionStyle`,value:e.value,disabled:e.disabled,onInput:a.pickGrid,onChange:t[0]||=t=>e.$emit(`change`)},null,8,[`value`,`disabled`,`onInput`]),U(`div`,JR,[W(s,{value:i.x,options:a.numOptions(`X`),disabled:e.disabled,onInput:a.setX,onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onInput`,`onChange`]),W(s,{value:i.y,options:a.numOptions(`Y`),disabled:e.disabled,onInput:a.setY,onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onInput`,`onChange`])])])}var XR=X(KR,[[`render`,YR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetBgPosition.vue`]]),ZR=[{key:`cover`,desc:`cover:保持纵横比,缩放到完全覆盖背景定位区域的最小尺寸`},{key:`contain`,desc:`contain:保持纵横比,缩放到能放进背景定位区域的最大尺寸`}],QR={name:`SetBgSize`,components:{SetNumberStyle:NR,Dropdown:Sg},computed:{bgOptions(){return[{key:``,value:`自定义`}].concat(this.TYPES.map(e=>({key:e.key,value:e.key})))}},props:jg,emits:Mg,data(){return{TYPES:ZR,preset:``,x:``,y:``}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``),t=ZR.map(e=>e.key);this.preset=t.includes(e)?e:``;let n=e.split(/\s+/);n.length>=2?(this.x=n[0]||``,this.y=n[1]||``):(this.x=``,this.y=``)},pickPreset(e){this.preset=e,e||(this.x=`auto`,this.y=`auto`),this.emitValue(),this.$emit(`change`)},setX(e){this.x=e,this.emitValue()},setY(e){this.y=e,this.emitValue()},emitValue(){let e=this.preset?this.preset:`${this.x||`auto`} ${this.y||`auto`}`;this.$emit(`input`,e)},emitOut(){this.$emit(`change`)}}},$R={class:`st-bgsize`},ez={key:0,class:`st-bgsize__xy`};function tz(e,t,n,r,i,a){let o=L(`Dropdown`),s=L(`SetNumberStyle`);return B(),V(`div`,$R,[W(o,{value:i.preset,options:a.bgOptions,size:`sm`,block:``,disabled:e.disabled,onInput:t[0]||=e=>a.pickPreset(e)},null,8,[`value`,`options`,`disabled`]),i.preset?K(`v-if`,!0):(B(),V(`div`,ez,[W(s,{value:i.x,options:{placeholder:`宽`},disabled:e.disabled,onInput:a.setX,onChange:a.emitOut},null,8,[`value`,`disabled`,`onInput`,`onChange`]),W(s,{value:i.y,options:{placeholder:`高`},disabled:e.disabled,onInput:a.setY,onChange:a.emitOut},null,8,[`value`,`disabled`,`onInput`,`onChange`])]))])}var nz=X(QR,[[`render`,tz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetBgSize.vue`]]),rz=[{key:`to bottom`,desc:`从上到下`},{key:`to top`,desc:`从下到上`},{key:`to left`,desc:`从右到左`},{key:`to right`,desc:`从左到右`},{key:`to bottom right`,desc:`从左上到右下`},{key:`to bottom left`,desc:`从右上到左下`},{key:`to top left`,desc:`从右下到左上`},{key:`to top right`,desc:`从左下到右上`}];function iz(e){let t=[],n=0,r=0;for(let i=0;i<e.length;i++){let a=e[i];a===`(`?n++:a===`)`?n--:a===`,`&&n===0&&(t.push(e.slice(r,i).trim()),r=i+1)}return t.push(e.slice(r).trim()),t.filter(e=>e!==``)}var az={name:`SetGradient`,components:{SetColor:iR,Dropdown:Sg},props:jg,emits:Mg,data(){return{DIRECTIONS:rz,direction:`to bottom`,stops:[]}},computed:{preview(){if(!this.stops.length)return`transparent`;let e=this.stops.map(e=>e.color).filter(Boolean);return e.length<2?e[0]||`transparent`:`linear-gradient(${this.direction}, ${e.join(`, `)})`}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``).trim().match(/linear-gradient\((.+)\)$/);if(!e){this.direction=this.options.defaultDirection||rz[0].key,this.stops=[];return}let t=iz(e[1]);this.direction=(t[0]||``).toLowerCase()||rz[0].key,this.stops=t.slice(1).map(e=>({color:e}))},setDirection(e){this.direction=e,this.emitValue(),this.$emit(`change`)},setStop(e,t){this.stops[e].color=t,this.emitValue()},addStop(){this.disabled||(this.stops.push({color:`#ffffff`}),this.emitValue(),this.$emit(`change`))},removeStop(e){this.disabled||(this.stops.splice(e,1),this.emitValue(),this.$emit(`change`))},emitValue(){let e=this.stops.map(e=>e.color).filter(e=>e!==``&&e!==void 0);this.$emit(`input`,e.length?`linear-gradient(${this.direction}, ${e.join(`, `)})`:``)},emitOut(){this.$emit(`change`)}}},oz={class:`st-gradient`},sz=[`onClick`],cz=[`disabled`];function lz(e,t,n,r,i,a){let o=L(`Dropdown`),s=L(`SetColor`);return B(),V(`div`,oz,[U(`div`,{class:`st-gradient__preview`,style:A({background:a.preview})},null,4),W(o,{value:i.direction,options:i.DIRECTIONS.map(e=>({key:e.key,value:e.desc})),size:`sm`,block:``,disabled:e.disabled,onInput:t[0]||=e=>a.setDirection(e)},null,8,[`value`,`options`,`disabled`]),(B(!0),V(z,null,R(i.stops,(t,n)=>(B(),V(`div`,{key:`stop`+n,class:`st-gradient__stop`},[W(s,{value:t.color,disabled:e.disabled,onInput:e=>a.setStop(n,e),onChange:a.emitOut},null,8,[`value`,`disabled`,`onInput`,`onChange`]),U(`button`,{class:`st-gradient__del`,type:`button`,title:`删除该渐变色`,onClick:e=>a.removeStop(n)},`✕`,8,sz)]))),128)),U(`button`,{class:`st-minibtn`,type:`button`,disabled:e.disabled,onClick:t[1]||=(...e)=>a.addStop&&a.addStop(...e)},`+ 新增渐变色`,8,cz)])}var uz=X(az,[[`render`,lz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetGradient.vue`]]),dz=new Set([`width`,`height`,`lineHeight`,`marginRight`,`cursor`,`textAlign`]),fz={name:`SetCustomSelect`,props:jg,emits:[...Mg,`sync`],computed:{list(){return this.options.list||[]}},methods:{normalizeStyle(e){if(!e||typeof e!=`object`)return{};let t={};for(let n in e)dz.has(n)||(t[n]=e[n]);return t},apply(e){if(this.disabled)return;let t=e.sync||{};Object.keys(t).length&&this.$emit(`sync`,t)}}},pz={class:`st-customsel`},mz=[`title`,`onClick`],hz={key:0},gz={key:0,class:`st-list__empty`};function _z(e,t,n,r,i,a){return B(),V(`div`,pz,[(B(!0),V(z,null,R(a.list,(e,t)=>(B(),V(`div`,{key:t,class:`st-customsel__item`,style:A(a.normalizeStyle(e.style)),title:`应用:`+Object.keys(e.sync||{}).join(`、`),onClick:t=>a.apply(e)},[(B(!0),V(z,null,R(e.list||[],(e,t)=>(B(),V(`span`,{key:t,style:A(a.normalizeStyle(e.style))},M(e.innerText),5))),128)),(e.list||[]).length?K(`v-if`,!0):(B(),V(`span`,hz,M(e.innerText||`样式`+(t+1)),1))],12,mz))),128)),a.list.length?K(`v-if`,!0):(B(),V(`p`,gz,`未配置常用样式`))])}var vz=X(fz,[[`render`,_z],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetCustomSelect.vue`]]),yz={name:`SetList`,props:jg,emits:Mg,computed:{list(){let e=this.itemInfo;return e&&e.itemList||[]},addText(){return this.options&&this.options.btnText||`添加项`}},methods:{displayName(e){let t=e.itemName||e.itemKey||``;return{fontStyle:`字体风格`,textDecoration:`文字装饰`}[e.itemKey]||t},add(){if(this.disabled)return;let e=this.itemInfo,t=this.list[0],n;n=t?new du(t.properties.map(e=>({itemId:e.itemId,itemKey:e.itemKey,itemName:e.itemName,itemType:e.itemType,itemOption:e.itemOption,itemParam:e.itemParam,itemDefaultValue:e.itemDefaultValue,itemDesc:e.itemDesc,itemTypeRange:e.itemTypeRange,itemValueFrom:`0`,itemValue:``})),{}):new du((this.options&&this.options.iFieldList||[]).map(e=>({itemId:e.key,itemKey:e.key,itemName:e.value||e.key,itemType:`Input`,itemValueFrom:`0`,itemValue:``})),{}),e.itemList.push(n),this.$emit(`change`)},remove(e){this.disabled||(this.itemInfo.removeAt(e),this.$emit(`change`))},move(e,t){this.disabled||(this.itemInfo.moveItem(e,e+t),this.$emit(`change`))}}},bz={class:`st-list`},xz={class:`st-list__head`},Sz={class:`st-list__idx`},Cz=[`disabled`,`onClick`],wz=[`disabled`,`onClick`],Tz=[`disabled`,`onClick`],Ez={class:`st-list__body`},Dz=[`title`],Oz={class:`st-list__control`},kz={key:0,class:`st-list__empty`},Az={key:0,class:`st-list__empty`},jz=[`disabled`];function Mz(e,t,n,r,i,a){let o=L(`prop-control`);return B(),V(`div`,bz,[(B(!0),V(z,null,R(a.list,(n,r)=>(B(),V(`div`,{key:n.id,class:`st-list__item`},[U(`div`,xz,[U(`span`,Sz,`#`+M(r+1),1),t[4]||=U(`span`,{class:`st-list__head-spacer`},null,-1),U(`button`,{class:`st-list__op`,type:`button`,title:`上移`,disabled:e.disabled||r===0,onClick:e=>a.move(r,-1)},`↑`,8,Cz),U(`button`,{class:`st-list__op`,type:`button`,title:`下移`,disabled:e.disabled||r===a.list.length-1,onClick:e=>a.move(r,1)},`↓`,8,wz),U(`button`,{class:`st-list__op st-list__op--del`,type:`button`,title:`删除`,disabled:e.disabled,onClick:e=>a.remove(r)},[...t[3]||=[U(`svg`,{viewBox:`0 0 16 16`,class:`st-ic`,"aria-hidden":`true`},[U(`use`,{href:`#icon-delete`})],-1)]],8,Tz)]),U(`div`,Ez,[(B(!0),V(z,null,R(n.properties,n=>I((B(),V(`div`,{key:n.itemId,class:`st-list__row`},[U(`label`,{class:`st-list__label`,title:n.itemDesc||a.displayName(n)},M(a.displayName(n)),9,Dz),U(`div`,Oz,[W(o,{property:n,disabled:e.disabled,onChange:t[0]||=t=>e.$emit(`change`),onSync:t[1]||=t=>e.$emit(`sync`,t)},null,8,[`property`,`disabled`])])])),[[Sc,n.itemVisible]])),128)),n.properties.length?K(`v-if`,!0):(B(),V(`p`,kz,`该项无字段`))])]))),128)),a.list.length?K(`v-if`,!0):(B(),V(`p`,Az,`暂无项`)),U(`button`,{class:`st-minibtn st-list__add`,type:`button`,disabled:e.disabled,onClick:t[2]||=(...e)=>a.add&&a.add(...e)},M(a.addText),9,jz)])}var Nz=X(yz,[[`render`,Mz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetList.vue`]]),Pz={name:`SetImage`,props:jg,emits:Mg,methods:{clear(){this.disabled||(this.$emit(`input`,``),this.$emit(`change`))}}},Fz={class:`st-image`},Iz={class:`st-image__row`},Lz=[`disabled`,`value`],Rz=[`disabled`];function zz(e,t,n,r,i,a){return B(),V(`div`,Fz,[U(`div`,Iz,[U(`input`,{class:`ni-input`,type:`text`,disabled:e.disabled,value:e.value||``,placeholder:`图片路径,如 @filestore/...png 或 https://...`,onInput:t[0]||=t=>e.$emit(`input`,t.target.value),onChange:t[1]||=t=>e.$emit(`change`)},null,40,Lz),e.value?(B(),V(`button`,{key:0,class:`st-image__clear`,type:`button`,title:`清空`,disabled:e.disabled,onClick:t[2]||=(...e)=>a.clear&&a.clear(...e)},[...t[3]||=[U(`svg`,{viewBox:`0 0 16 16`,class:`st-ic`,"aria-hidden":`true`},[U(`use`,{href:`#icon-reset`})],-1)]],8,Rz)):K(`v-if`,!0)])])}var Bz=X(Pz,[[`render`,zz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetImage.vue`]]),Vz={name:`SetCode`,props:jg,emits:Mg,data(){return{code:``,bridge:null}},computed:{codeKey(){return this.options.codeKey||`code`},lines(){return this.code?this.code.split(`
|
|
307
|
-
`).length:0},chars(){return this.code.length}},mounted(){this.code=this.readCode(),this.$nextTick(()=>this.initJar())},beforeUnmount(){this._t&&clearTimeout(this._t),this.teardownBridge(!0),this._jar&&this._jar.destroy&&this._jar.destroy()},methods:{readCode(){let e=this.value;return e==null?``:typeof e==`string`?e:String(typeof e==`object`?e[this.codeKey]||``:e)},initJar(){let e=this.$refs.editor;if(!e)return;let t=e=>{e.innerHTML=Yg.default.highlight(e.textContent,Yg.default.languages.javascript,`javascript`)};this._jar=Jg(e,t,{tab:` `,indentOn:/[({[]$/,addClosing:!0,history:!0}),this._jar.updateCode(this.code),this._jar.onUpdate(e=>this.onCode(e))},onCode(e){if(this.disabled||this.bridge)return;this.code=e;let t=this.value&&typeof this.value==`object`?Object.assign({},this.value):{};t[this.codeKey]=e,this.$emit(`input`,t),this._t&&clearTimeout(this._t),this._t=setTimeout(()=>this.$emit(`change`),400)},toggleBridge(){this.bridge?this.teardownBridge(!0):this.setupBridge()},async setupBridge(){if(this.disabled||this.bridge)return;let e=this.itemInfo&&this.itemInfo.itemKey?String(this.itemInfo.itemKey):``;try{let t=await Gl(this.code,e);this.bridge={id:t.id,file:t.file}}catch(e){console.error(`[VSCode 桥接建立失败]`,e);return}this.setEditorEditable(!1),this._hb=setInterval(()=>{this.bridge&&ql(this.bridge.id).catch(()=>{})},5e3),this._bridgeUnsub=Hl(e=>{if(!(!this.bridge||!e||e.id!==this.bridge.id)){if(e.reason)return this.teardownBridge(!1);this.pullBridgeCode()}})},async pullBridgeCode(){if(!this.bridge)return;let e;try{e=await Kl(this.bridge.id)}catch{return}let t=String(e.code==null?``:e.code);t!==this.code&&this.applyExternalCode(t)},applyExternalCode(e){this.code=e,this._jar&&this._jar.updateCode(e,!1);let t=this.value&&typeof this.value==`object`?Object.assign({},this.value):{};t[this.codeKey]=e,this.$emit(`input`,t),this._t&&clearTimeout(this._t),this._t=setTimeout(()=>this.$emit(`change`),400)},teardownBridge(e){let t=this.bridge;this.bridge=null,this._hb&&=(clearInterval(this._hb),null),this._bridgeUnsub&&=(this._bridgeUnsub(),null),this.setEditorEditable(!0),t&&e&&Jl(t.id).catch(()=>{})},setEditorEditable(e){let t=this.$refs.editor;t&&t.setAttribute(`contenteditable`,e?`true`:`false`)}}},Hz={class:`st-code`},Uz={class:`st-code__foot`},Wz={class:`st-code__hint`},Gz={class:`st-code__foot-actions`},Kz=[`title`],qz=[`title`,`disabled`],Jz={key:0,class:`st-code__vscode-label`};function Yz(e,t,n,r,i,a){return B(),V(`div`,Hz,[U(`div`,{ref:`editor`,class:j([`st-code__editor`,{"is-disabled":e.disabled,"is-bridged":!!i.bridge}])},null,2),K(` 右上角语言标签:弱化的只读标识,不参与交互 `),t[2]||=U(`span`,{class:`st-code__lang`,"aria-hidden":`true`},`JS`,-1),U(`div`,Uz,[U(`span`,Wz,M(a.lines)+` 行 · `+M(a.chars)+` 字符`,1),K(` VSCode 代码桥:生成临时 js 用外部编辑器编辑,保存实时回写;断开即删临时文件 `),U(`span`,Gz,[i.bridge?(B(),V(`span`,{key:0,class:`st-code__bridge-tag`,title:i.bridge.file},`VSCode 同步中`,8,Kz)):K(`v-if`,!0),U(`button`,{type:`button`,class:j([`st-code__vscode`,{"is-on":!!i.bridge}]),title:i.bridge?`断开 VSCode 桥接并删除临时文件`:`在 VSCode 中编辑:保存实时同步回编辑区,断开后清除临时文件`,disabled:e.disabled,onClick:t[0]||=(...e)=>a.toggleBridge&&a.toggleBridge(...e)},[K(` 图标左侧小字:未桥接时是动作说明;桥接后由状态徽标接替,避免两段文字挤一行 `),i.bridge?K(`v-if`,!0):(B(),V(`span`,Jz,`在编辑器中打开`)),t[1]||=U(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,"aria-hidden":`true`},[U(`path`,{fill:`currentColor`,d:`M23.15 2.587 18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z`})],-1)],10,qz)])])])}var Xz=X(Vz,[[`render`,Yz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetCode.vue`]]),Zz={0:`常量`,1:`变量`,2:`图片`},Qz={const:`0`,var:`1`,image:`2`};function $z(e){switch(e){case`InputNumber`:return{comp:pI};case`Color`:return{comp:iR};case`Select`:return{comp:gI};case`TabSelect`:return{comp:Kg,kind:`TabSelect`};case`Input`:return{comp:nI};case`Textarea`:return{comp:nI,multiline:!0};case`Switcher`:return{comp:bI};case`BooleanForm`:return{comp:bI,boolean:!0};case`PaddingStyle`:return{comp:LR};case`NumberStyle`:return{comp:NR};case`PositionStyle`:return{comp:WR,kind:`PositionStyle`};case`BackgroundPositionStyle`:return{comp:XR};case`BackgroundSizeStyle`:return{comp:nz};case`GradientStyle`:return{comp:uz};case`FontStyle`:return{comp:Kg,kind:`FontStyle`};case`TextDecorationStyle`:return{comp:Kg,kind:`TextDecorationStyle`};case`JustifyContentStyle`:return{comp:Kg,kind:`JustifyContentStyle`};case`AlignItemsStyle`:return{comp:Kg,kind:`AlignItemsStyle`};case`IconSelect`:return{comp:hR};case`CustomSelect`:return{comp:vz};case`List`:return{comp:Nz};case`IfForm`:return{comp:ER};case`Code`:return{comp:Xz};default:return{comp:nI}}}var eB={name:`PropControl`,components:{SetText:nI,SetNumber:pI,SetSelect:gI,SetSegment:Kg,SetSwitch:bI,SetColor:iR,SetIconSelect:hR,SetIfForm:ER,SetNumberStyle:NR,SetPadding:LR,SetGrid9:WR,SetBgPosition:XR,SetBgSize:nz,SetGradient:uz,SetCustomSelect:vz,SetList:Nz,SetImage:Bz,SetCode:Xz,SetExpr:xR},props:{property:{type:Object,required:!0},watches:{type:Object,default:()=>({})},disabled:{type:Boolean,default:!1},bExchange:{type:Boolean,default:!0}},emits:[`change`,`sync`],computed:{itemType(){return this.property&&this.property.itemType||``},sources(){let e=this.property&&this.property.itemTypeRange||`const`,t=String(e).split(`,`).map(e=>e.trim()).filter(Boolean).map(e=>({key:Qz[e],label:Zz[Qz[e]]})).filter(e=>e.key),n=String(this.property.itemValueFrom);return/^[012]$/.test(n)&&!t.some(e=>e.key===n)&&(t=t.concat([{key:n,label:Zz[n]||`来源`+n}])),t},setterComp(){return $z(this.itemType)}},methods:{onInput(e){this.property.itemValue=e,this.$emit(`change`)},onChange(){this.$emit(`change`)},onSync(e){this.$emit(`sync`,e)},setSource(e){if(this.disabled)return;let t=this.property,n=String(e);t.itemValueFrom!==n&&(t._valuesByFrom||={0:void 0,1:void 0,2:void 0},t._valuesByFrom[t.itemValueFrom]=t.itemValue,t.itemValueFrom=n,t._valuesByFrom[n]===void 0?n===`0`?(t.itemValue=t.itemDefaultValue??this.defaultFor(),t._valuesByFrom[n]=t.itemValue):(t.itemValue=``,t._valuesByFrom[n]=``):t.itemValue=t._valuesByFrom[n],this.$emit(`change`))},defaultFor(){switch(this.itemType){case`Color`:return`#000000`;case`InputNumber`:return 0;case`Switcher`:return`0`;case`BooleanForm`:return!1;case`TabSelect`:case`Select`:{let e=this.property.itemOption||{},t=e.iParamList||e.iTypeList||[];return t.length?t[0].key:``}default:return``}}}},tB={key:0,class:`pc-srcs`},nB=[`disabled`,`onClick`],rB={class:`pc-body`};function iB(e,t,n,r,i,a){let o=L(`SetImage`),s=L(`SetExpr`);return B(),V(`div`,{class:j([`pc`,{"pc--readonly":n.disabled}])},[K(` 值来源切换(仅当 meta 声明了多于一种来源 且 允许切换时显示) `),a.sources.length>1&&n.bExchange?(B(),V(`div`,tB,[(B(!0),V(z,null,R(a.sources,e=>(B(),V(`button`,{key:e.key,type:`button`,class:j([`pc-src`,{"is-active":n.property.itemValueFrom===e.key}]),disabled:n.disabled,onClick:t=>a.setSource(e.key)},M(e.label),11,nB))),128))])):K(`v-if`,!0),U(`div`,rB,[K(` 图片素材来源 `),n.property.itemValueFrom===`2`?(B(),H(o,{key:0,value:n.property.itemValue,options:n.property.itemOption,"item-info":n.property,disabled:n.disabled,onInput:a.onInput,onChange:a.onChange},null,8,[`value`,`options`,`item-info`,`disabled`,`onInput`,`onChange`])):n.property.itemValueFrom===`1`?(B(),V(z,{key:1},[K(` 变量 / 表达式来源:带语法高亮、可拖拽调高度 `),W(s,{value:n.property.itemValue,disabled:n.disabled,"item-info":n.property,onInput:a.onInput,onChange:a.onChange},null,8,[`value`,`disabled`,`item-info`,`onInput`,`onChange`])],2112)):(B(),V(z,{key:2},[K(` 常量来源:按 itemType 分派 `),(B(),H(Yi(a.setterComp.comp),{value:n.property.itemValue,options:n.property.itemOption,watches:n.watches,"item-info":n.property,disabled:n.disabled,kind:a.setterComp.kind,multiline:a.setterComp.multiline,boolean:a.setterComp.boolean,onInput:a.onInput,onChange:a.onChange,onSync:a.onSync},null,40,[`value`,`options`,`watches`,`item-info`,`disabled`,`kind`,`multiline`,`boolean`,`onInput`,`onChange`,`onSync`]))],2112))])],2)}var aB=X(eB,[[`render`,iB],[`__scopeId`,`data-v-910daa70`],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/PropControl.vue`]]),oB={name:`PropTree`,props:{properties:{type:Array,default:()=>[]},mode:{type:String,default:`property`},depth:{type:Number,default:1},chain:{type:Array,default:()=>[]},watches:{type:Object,default:()=>({})},disabled:{type:Boolean,default:!1},bExchange:{type:Boolean,default:!0},plain:{type:Boolean,default:!1}},emits:[`leaf-change`,`leaf-sync`],data(){return{openMap:{}}},methods:{isGroup(e){if(!e)return!1;if(e.itemType===`group`)return!0;let t=e.itemChildren&&e.itemChildren.properties;return!!(t&&t.length)},childCount(e){let t=e.itemChildren&&e.itemChildren.properties;return t?t.length:0},isBlock(e){return e&&e.itemType===`Code`},groupVisible(e){if(e.itemVisible===!1)return!1;let t=e.itemChildren&&e.itemChildren.properties;return!t||!t.length||t.some(e=>e.itemVisible===!1?!1:!this.isGroup(e)||this.groupVisible(e))},isOpen(e){return this.openMap[e.itemId]!==!1},toggle(e){this.openMap[e.itemId]=this.openMap[e.itemId]===!1,this.openMap=Object.assign({},this.openMap)},onLeaf(e){this.$emit(`leaf-change`,this.chain.concat(e))},onSync(e){this.$emit(`leaf-sync`,e)}}},sB={key:0,class:`ptree__group`},cB=[`onClick`],lB={class:`ptree__group-name`},uB={class:`ptree__group-body`},dB=[`title`],fB={class:`ptree__control`};function pB(e,t,n,r,i,a){let o=L(`prop-tree`,!0),s=L(`prop-control`);return B(),V(`div`,{class:j([`ptree`,{"ptree--plain":n.plain}])},[(B(!0),V(z,null,R(n.properties,r=>(B(),V(z,{key:r.itemId},[K(` 分组(自身可见 且 存在可见后代才渲染,避免空分组) `),a.isGroup(r)&&a.groupVisible(r)?(B(),V(`div`,sB,[U(`div`,{class:`ptree__group-head`,type:`button`,onClick:e=>a.toggle(r)},[U(`span`,{class:j([`ptree__caret`,{"is-open":a.isOpen(r)}])},`▸`,2),U(`span`,lB,M(r.itemName||r.itemKey),1)],8,cB),I(U(`div`,uB,[r.itemChildren&&r.itemChildren.properties.length?(B(),H(o,{key:0,properties:r.itemChildren.properties,mode:n.mode,depth:n.depth+1,chain:n.chain.concat(r),watches:n.watches,disabled:n.disabled,"b-exchange":n.bExchange,plain:n.plain,onLeafChange:t[0]||=t=>e.$emit(`leaf-change`,t),onLeafSync:t[1]||=t=>e.$emit(`leaf-sync`,t)},null,8,[`properties`,`mode`,`depth`,`chain`,`watches`,`disabled`,`b-exchange`,`plain`])):K(`v-if`,!0)],512),[[Sc,a.isOpen(r)]])])):r.itemVisible===!1?K(`v-if`,!0):(B(),V(z,{key:1},[K(` 叶子(itemCondition 判定为不可见时不渲染,与线上编辑器一致) `),U(`div`,{class:j([`ptree__row`,{"ptree__row--disabled":n.disabled,"ptree__row--block":a.isBlock(r)}])},[U(`label`,{class:`ptree__label`,title:r.itemDesc||r.itemName||r.itemKey},M(r.itemName||r.itemKey||r.itemType||`字段`),9,dB),U(`div`,fB,[W(s,{property:r,watches:n.watches,disabled:n.disabled,"b-exchange":n.bExchange,onChange:e=>a.onLeaf(r),onSync:a.onSync},null,8,[`property`,`watches`,`disabled`,`b-exchange`,`onChange`,`onSync`])])],2)],2112))],64))),128))],2)}var mB=X(oB,[[`render`,pB],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/PropTree.vue`]]),hB=Sl(ZF);hB.component(`prop-control`,aB),hB.component(`prop-tree`,mB),hB.component(`Dropdown`,Sg),hB.config.errorHandler=(e,t,n)=>{console.error(`[render error]`,n,e),window.__cardDebug&&window.__cardDebug.pushError(`render`,`${n}: ${e.message}`)},hB.mount(`#app`);
|
|
305
|
+
展开/收起由顶栏按钮与面板内 ✕ 控制,初始状态持久化 `),i.apiPanelOpen?(B(),H(v,{key:0,rt:i.rt,onClose:t[31]||=e=>i.apiPanelOpen=!1},null,8,[`rt`])):K(`v-if`,!0)],512)],512),[[Sc,!i.chromeOff]])],512),K(` 远端预览二维码弹层:点击顶栏「远端预览」按钮打开,手机(FinMall App)扫码真机查看 `),W(y,{visible:i.remotePreviewOpen,"page-id":i.currentSchema?i.currentSchema.pageId:``,schema:i.currentSchema,onClose:t[32]||=e=>i.remotePreviewOpen=!1},null,8,[`visible`,`page-id`,`schema`]),K(` 登录凭据弹窗:远程同步检测到缺凭据时弹出,填写账号密码(MD5 后)写入 .local/credentials.json `),W(ic,{name:`modal`},{default:Lr(()=>[i.loginModal?(B(),V(`div`,{key:0,class:`login-mask`,onClick:t[39]||=q((...e)=>a.closeLoginModal&&a.closeLoginModal(...e),[`self`])},[U(`div`,KF,[t[79]||=U(`div`,{class:`login-modal__title`},`FinMall 登录凭据`,-1),t[80]||=U(`div`,{class:`login-modal__desc`},` 本地登录凭据缺失,请填写账号与密码。密码仅做 MD5 后保存,不落明文。 `,-1),U(`label`,qF,[t[77]||=U(`span`,{class:`login-modal__label`},`账号`,-1),I(U(`input`,{class:`login-modal__input`,type:`text`,"onUpdate:modelValue":t[33]||=e=>i.loginName=e,placeholder:`FinMall 登录账号`,disabled:i.loginSubmitting,onKeyup:t[34]||=vl((...e)=>a.submitLogin&&a.submitLogin(...e),[`enter`])},null,40,JF),[[il,i.loginName]])]),U(`label`,YF,[t[78]||=U(`span`,{class:`login-modal__label`},`密码`,-1),I(U(`input`,{class:`login-modal__input`,type:`password`,"onUpdate:modelValue":t[35]||=e=>i.loginPassword=e,placeholder:`FinMall 登录密码`,disabled:i.loginSubmitting,onKeyup:t[36]||=vl((...e)=>a.submitLogin&&a.submitLogin(...e),[`enter`])},null,40,XF),[[il,i.loginPassword]])]),i.loginError?(B(),V(`div`,ZF,M(i.loginError),1)):K(`v-if`,!0),U(`div`,QF,[U(`button`,{class:`login-modal__btn login-modal__btn--ghost`,type:`button`,disabled:i.loginSubmitting,onClick:t[37]||=(...e)=>a.closeLoginModal&&a.closeLoginModal(...e)},` 取消 `,8,$F),U(`button`,{class:`login-modal__btn login-modal__btn--primary`,type:`button`,disabled:i.loginSubmitting,onClick:t[38]||=(...e)=>a.submitLogin&&a.submitLogin(...e)},M(i.loginSubmitting?`保存中…`:`保存并同步`),9,eI)])])])):K(`v-if`,!0)]),_:1}),K(` 组件选择面板:点击结构树每行的「+」后弹出,选择类型即插入对应节点 `),W(ic,{name:`modal`},{default:Lr(()=>[i.addNodePanelOpen?(B(),H(b,{key:0,onPick:a.onPickComponent,onClose:a.cancelAddNode},null,8,[`onPick`,`onClose`])):K(`v-if`,!0)]),_:1}),K(` 二次确认弹窗:版本推送 / 当前同步 / 全量同步 等写/覆盖类操作前弹出,确认后才执行 `),W(x,{visible:i.confirm.show,title:i.confirm.title,message:i.confirm.message,"confirm-text":i.confirm.confirmText,"cancel-text":i.confirm.cancelText,severity:i.confirm.severity,onConfirm:a.onConfirmDialog,onCancel:a.onCancelDialog},null,8,[`visible`,`title`,`message`,`confirm-text`,`cancel-text`,`severity`,`onConfirm`,`onCancel`]),K(` 卡片网格预览弹窗:点击顶栏「网格预览」图标按钮打开,选择卡片即载入工作台 `),W(S,{visible:i.galleryOpen,cards:i.cardList,"selected-id":i.selectedId,onSelect:a.onSelect,onClose:a.closeGallery,onDelete:a.onGalleryDelete},null,8,[`visible`,`cards`,`selected-id`,`onSelect`,`onClose`,`onDelete`]),K(` 卡片表单弹窗(新增空白卡片 / 卡片重命名 共用一个弹窗):成功后关弹窗 + 刷列表 + 加载目标卡;existing-ids 供 ID 重名前置判定 `),W(C,{visible:i.cardDialog.visible,mode:i.cardDialog.mode,"card-id":i.cardDialog.cardId,"card-desc":i.cardDialog.cardDesc,"existing-ids":a.cardIds,onClose:t[40]||=e=>i.cardDialog.visible=!1,onCreated:a.onNewCardCreated,onRenamed:a.onCardRenamed},null,8,[`visible`,`mode`,`card-id`,`card-desc`,`existing-ids`,`onCreated`,`onRenamed`]),K(` App 级弱提示:顶栏异步操作(远端保存 / 同步)完成反馈,浮于 App 外壳顶部居中 `),W(w),K(` 对话图片大图查看器:AI 面板里点预览图后全屏缩放查看,Teleport 到 body `),W(T)],6)}var nI=X(HP,[[`render`,tI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/App.vue`]]),rI={name:`SetText`,props:{...jg,multiline:{type:Boolean,default:!1}},emits:Mg,computed:{text(){return this.value===void 0||this.value===null?``:String(this.value)},rows(){let e=this.options.autosize;return e&&typeof e==`object`&&e.minRows?e.minRows:4}},methods:{onInput(e){this.$emit(`input`,e)}}},iI=[`rows`,`placeholder`,`disabled`,`value`],aI=[`placeholder`,`disabled`,`value`];function oI(e,t,n,r,i,a){return n.multiline?(B(),V(`textarea`,{key:0,class:`st-textarea`,rows:a.rows,placeholder:e.options.placeholder||``,disabled:e.disabled,value:a.text,onInput:t[0]||=e=>a.onInput(e.target.value),onChange:t[1]||=t=>e.$emit(`change`)},null,40,iI)):(B(),V(`input`,{key:1,class:`ni-input`,type:`text`,placeholder:e.options.placeholder||``,disabled:e.disabled,value:a.text,onInput:t[2]||=e=>a.onInput(e.target.value),onChange:t[3]||=t=>e.$emit(`change`)},null,40,aI))}var sI=X(rI,[[`render`,oI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetText.vue`]]),cI={integer:/^-?(0|[1-9][0-9]*)?$/,"+integer":/^(0|[1-9][0-9]*)?$/,"-integer":/^(0|-[1-9]?[0-9]*)?$/,float:/^-?([0-9]*|(0|[1-9][0-9]*)\.[0-9]*)?$/,"+float":/^([0-9]*|(0|[1-9][0-9]*)\.[0-9]*)?$/,"-float":/^(0|-[0-9]*|-(0|[1-9][0-9]*)\.[0-9]*)?$/},lI={name:`SetNumber`,props:jg,emits:Mg,data(){return{inputValue:``,sugOpen:!1}},computed:{suggestions(){return this.options.iParamList||[]},pattern(){return cI[this.options.type]||cI.integer}},watch:{value:{immediate:!0,handler(e){this.inputValue=e==null?``:String(e)}}},methods:{onInput(e){if(!this.pattern.test(e)){this.$refs.field.value=this.inputValue;return}this.inputValue=e,this.$emit(`input`,e)},step(e){let t=parseFloat(this.inputValue),n=String((Number.isNaN(t)?0:t)+e);this.pattern.test(n)&&(this.inputValue=n,this.$emit(`input`,n),this.emitChange())},pick(e){this.sugOpen=!1,this.inputValue=String(e.key),this.$emit(`input`,this.inputValue),this.emitChange()},closeSug(){setTimeout(()=>this.sugOpen=!1,0)},emitChange(){this.$emit(`change`)}}},uI={class:`st-number-wrap`},dI={class:`st-number`},fI=[`placeholder`,`disabled`,`value`],pI={key:0,class:`st-number__symbol st-number__symbol--btn`},mI={key:1,class:`st-number__symbol`},hI={key:0,class:`st-pop st-pop--sug`},gI=[`onMousedown`];function _I(e,t,n,r,i,a){return B(),V(`div`,uI,[U(`div`,dI,[U(`input`,{ref:`field`,class:`st-number__field`,type:`text`,placeholder:e.options.placeholder||`请输入`,disabled:e.disabled,value:i.inputValue,onInput:t[0]||=e=>a.onInput(e.target.value),onChange:t[1]||=e=>a.emitChange(),onKeydown:[t[2]||=vl(q(e=>a.step(1),[`prevent`]),[`up`]),t[3]||=vl(q(e=>a.step(-1),[`prevent`]),[`down`])],onBlur:t[4]||=e=>a.closeSug()},null,40,fI),e.$slots.symbol?(B(),V(`span`,pI,[Qi(e.$slots,`symbol`)])):e.options.symbol&&e.options.symbol!==!0?(B(),V(`span`,mI,M(e.options.symbol),1)):K(`v-if`,!0),a.suggestions.length?(B(),V(`span`,{key:2,class:`st-number__caret`,title:`预设值`,onMousedown:t[5]||=q(e=>i.sugOpen=!i.sugOpen,[`prevent`])},`▾`,32)):K(`v-if`,!0)]),K(` 预设值浮层:移出 .st-number,避免被 overflow:hidden 裁切 `),i.sugOpen&&a.suggestions.length?(B(),V(`div`,hI,[(B(!0),V(z,null,R(a.suggestions,e=>(B(),V(`div`,{key:e.key,class:j([`st-pop__item`,{"st-pop__item--on":String(e.key)===String(i.inputValue)}]),onMousedown:q(t=>a.pick(e),[`prevent`])},M(e.value),43,gI))),128))])):K(`v-if`,!0)])}var vI=X(lI,[[`render`,_I],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetNumber.vue`]]),yI={name:`SetSelect`,props:jg,emits:Mg,computed:{list(){return this.options.iParamList||this.options.iTypeList||[]},placeholder(){return this.options.placeholder||`请选择`},optionList(){return this.list.map(e=>({key:String(e.key),value:e.value}))},current(){return this.value===void 0||this.value===null?``:String(this.value)}},methods:{onChange(e){this.$emit(`input`,e),this.$emit(`change`)}}};function bI(e,t,n,r,i,a){let o=L(`Dropdown`);return B(),H(o,{value:a.current,options:a.optionList,placeholder:a.placeholder,clearable:``,size:`sm`,block:``,disabled:e.disabled,onInput:a.onChange},null,8,[`value`,`options`,`placeholder`,`disabled`,`onInput`])}var xI=X(yI,[[`render`,bI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetSelect.vue`]]),SI={name:`SetSwitch`,props:{...jg,boolean:{type:Boolean,default:!1}},emits:Mg,computed:{activeValue(){return this.options.activeValue===void 0?this.boolean?!0:`1`:this.options.activeValue},inactiveValue(){return this.options.inactiveValue===void 0?!this.boolean&&`0`:this.options.inactiveValue},on(){return this.value===this.activeValue},activeText(){return this.options.activeText||`开`},inactiveText(){return this.options.inactiveText||`关`}},methods:{toggle(){this.disabled||(this.$emit(`input`,this.on?this.inactiveValue:this.activeValue),this.$emit(`change`))}}},CI={class:`st-switch__text`};function wI(e,t,n,r,i,a){return B(),V(`div`,{class:j([`st-switch`,{"st-switch--on":a.on}]),onClick:t[0]||=(...e)=>a.toggle&&a.toggle(...e)},[t[1]||=U(`span`,{class:`st-switch__track`},[U(`span`,{class:`st-switch__knob`})],-1),U(`span`,CI,M(a.on?a.activeText:a.inactiveText),1)],2)}var TI=X(SI,[[`render`,wI],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetSwitch.vue`]]);function EI(e,t){t===void 0&&(t={});var n=t.insertAt;if(!(!e||typeof document>`u`)){var r=document.head||document.getElementsByTagName(`head`)[0],i=document.createElement(`style`);i.type=`text/css`,n===`top`&&r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(document.createTextNode(e))}}var DI=function(e,t){let{componentPrefix:n=``}=t||{};e.component(`${n}${this.name}`,this)},OI={},kI={name:`Checkboard`,props:{size:{type:[Number,String],default:8},white:{type:String,default:`#fff`},grey:{type:String,default:`#e6e6e6`}},computed:{bgStyle(){return{"background-image":`url(${jI(this.white,this.grey,this.size)})`}}}};function AI(e,t,n){if(typeof document>`u`)return null;let r=document.createElement(`canvas`);r.width=r.height=n*2;let i=r.getContext(`2d`);return i?(i.fillStyle=e,i.fillRect(0,0,r.width,r.height),i.fillStyle=t,i.fillRect(0,0,n,n),i.translate(n,n),i.fillRect(0,0,n,n),r.toDataURL()):null}function jI(e,t,n){let r=`${e},${t},${n}`;if(OI[r])return OI[r];let i=AI(e,t,n);return OI[r]=i,i}function MI(e,t,n,r,i,a){return B(),V(`div`,{class:`vc-checkerboard`,style:A(a.bgStyle)},null,4)}EI(`.vc-checkerboard{background-size:contain;bottom:0;left:0;position:absolute;right:0;top:0}`),kI.render=MI,kI.__file=`src/components/checkboard/checkboard.vue`,kI.install=DI;var NI={name:`Alpha`,components:{Checkboard:kI},props:{value:Object,onChange:Function},computed:{colors(){return this.value},gradientColor(){let{rgba:e}=this.colors,t=[e.r,e.g,e.b].join(`,`);return`linear-gradient(to right, rgba(${t}, 0) 0%, rgba(${t}, 1) 100%)`}},methods:{handleChange(e,t){!t&&e.preventDefault();let{container:n}=this.$refs;if(!n)return;let r=n.clientWidth,i=n.getBoundingClientRect().left+window.pageXOffset,a=(e.pageX||(e.touches?e.touches[0].pageX:0))-i,o;o=a<0?0:a>r?1:Math.round(a*100/r)/100,this.colors.a!==o&&this.$emit(`change`,{h:this.colors.hsl.h,s:this.colors.hsl.s,l:this.colors.hsl.l,a:o,source:`rgba`})},handleMouseDown(e){this.handleChange(e,!0),window.addEventListener(`mousemove`,this.handleChange),window.addEventListener(`mouseup`,this.handleMouseUp)},handleMouseUp(){this.unbindEventListeners()},unbindEventListeners(){window.removeEventListener(`mousemove`,this.handleChange),window.removeEventListener(`mouseup`,this.handleMouseUp)}}},PI={class:`vc-alpha`},FI={class:`vc-alpha-checkboard-wrap`},II=[U(`div`,{class:`vc-alpha-picker`},null,-1)];function LI(e,t,n,r,i,a){let o=L(`Checkboard`);return B(),V(`div`,PI,[U(`div`,FI,[W(o)]),U(`div`,{class:`vc-alpha-gradient`,style:A({background:a.gradientColor})},null,4),U(`div`,{ref:`container`,class:`vc-alpha-container`,onMousedown:t[0]||=(...e)=>a.handleMouseDown&&a.handleMouseDown(...e),onTouchmove:t[1]||=(...e)=>a.handleChange&&a.handleChange(...e),onTouchstart:t[2]||=(...e)=>a.handleChange&&a.handleChange(...e)},[U(`div`,{class:`vc-alpha-pointer`,style:A({left:`${a.colors.a*100}%`})},II,4)],544)])}EI(`.vc-alpha,.vc-alpha-checkboard-wrap{bottom:0;left:0;position:absolute;right:0;top:0}.vc-alpha-checkboard-wrap{overflow:hidden}.vc-alpha-gradient{bottom:0;left:0;position:absolute;right:0;top:0}.vc-alpha-container{cursor:pointer;height:100%;margin:0 3px;position:relative;z-index:2}.vc-alpha-pointer{position:absolute;z-index:2}.vc-alpha-picker{background:#fff;border-radius:1px;box-shadow:0 0 2px rgba(0,0,0,.6);cursor:pointer;height:8px;margin-top:1px;transform:translateX(-2px);width:4px}`),NI.render=LI,NI.__file=`src/components/alpha/alpha.vue`,NI.install=DI;function RI(e,t){BI(e)&&(e=`100%`);var n=VI(e);return e=t===360?e:Math.min(t,Math.max(0,parseFloat(e))),n&&(e=parseInt(String(e*t),10)/100),Math.abs(e-t)<1e-6?1:(e=t===360?(e<0?e%t+t:e%t)/parseFloat(String(t)):e%t/parseFloat(String(t)),e)}function zI(e){return Math.min(1,Math.max(0,e))}function BI(e){return typeof e==`string`&&e.indexOf(`.`)!==-1&&parseFloat(e)===1}function VI(e){return typeof e==`string`&&e.indexOf(`%`)!==-1}function HI(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function UI(e){return e<=1?`${Number(e)*100}%`:e}function WI(e){return e.length===1?`0`+e:String(e)}function GI(e,t,n){return{r:RI(e,255)*255,g:RI(t,255)*255,b:RI(n,255)*255}}function KI(e,t,n){e=RI(e,255),t=RI(t,255),n=RI(n,255);var r=Math.max(e,t,n),i=Math.min(e,t,n),a=0,o=0,s=(r+i)/2;if(r===i)o=0,a=0;else{var c=r-i;switch(o=s>.5?c/(2-r-i):c/(r+i),r){case e:a=(t-n)/c+(t<n?6:0);break;case t:a=(n-e)/c+2;break;case n:a=(e-t)/c+4}a/=6}return{h:a,s:o,l:s}}function qI(e,t,n){return n<0&&(n+=1),n>1&&--n,n<1/6?e+(t-e)*(6*n):n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function JI(e,t,n){var r,i,a;if(e=RI(e,360),t=RI(t,100),n=RI(n,100),t===0)i=n,a=n,r=n;else{var o=n<.5?n*(1+t):n+t-n*t,s=2*n-o;r=qI(s,o,e+1/3),i=qI(s,o,e),a=qI(s,o,e-1/3)}return{r:r*255,g:i*255,b:a*255}}function YI(e,t,n){e=RI(e,255),t=RI(t,255),n=RI(n,255);var r=Math.max(e,t,n),i=Math.min(e,t,n),a=0,o=r,s=r-i,c=r===0?0:s/r;if(r===i)a=0;else{switch(r){case e:a=(t-n)/s+(t<n?6:0);break;case t:a=(n-e)/s+2;break;case n:a=(e-t)/s+4}a/=6}return{h:a,s:c,v:o}}function XI(e,t,n){e=RI(e,360)*6,t=RI(t,100),n=RI(n,100);var r=Math.floor(e),i=e-r,a=n*(1-t),o=n*(1-i*t),s=n*(1-(1-i)*t),c=r%6,l=[n,o,a,a,s,n][c],u=[s,n,n,o,a,a][c],d=[a,a,s,n,n,o][c];return{r:l*255,g:u*255,b:d*255}}function ZI(e,t,n,r){var i=[WI(Math.round(e).toString(16)),WI(Math.round(t).toString(16)),WI(Math.round(n).toString(16))];return r&&i[0].startsWith(i[0].charAt(1))&&i[1].startsWith(i[1].charAt(1))&&i[2].startsWith(i[2].charAt(1))?i[0].charAt(0)+i[1].charAt(0)+i[2].charAt(0):i.join(``)}function QI(e,t,n,r,i){var a=[WI(Math.round(e).toString(16)),WI(Math.round(t).toString(16)),WI(Math.round(n).toString(16)),WI($I(r))];return i&&a[0].startsWith(a[0].charAt(1))&&a[1].startsWith(a[1].charAt(1))&&a[2].startsWith(a[2].charAt(1))&&a[3].startsWith(a[3].charAt(1))?a[0].charAt(0)+a[1].charAt(0)+a[2].charAt(0)+a[3].charAt(0):a.join(``)}function $I(e){return Math.round(parseFloat(e)*255).toString(16)}function eL(e){return tL(e)/255}function tL(e){return parseInt(e,16)}function nL(e){return{r:e>>16,g:(e&65280)>>8,b:e&255}}var rL={aliceblue:`#f0f8ff`,antiquewhite:`#faebd7`,aqua:`#00ffff`,aquamarine:`#7fffd4`,azure:`#f0ffff`,beige:`#f5f5dc`,bisque:`#ffe4c4`,black:`#000000`,blanchedalmond:`#ffebcd`,blue:`#0000ff`,blueviolet:`#8a2be2`,brown:`#a52a2a`,burlywood:`#deb887`,cadetblue:`#5f9ea0`,chartreuse:`#7fff00`,chocolate:`#d2691e`,coral:`#ff7f50`,cornflowerblue:`#6495ed`,cornsilk:`#fff8dc`,crimson:`#dc143c`,cyan:`#00ffff`,darkblue:`#00008b`,darkcyan:`#008b8b`,darkgoldenrod:`#b8860b`,darkgray:`#a9a9a9`,darkgreen:`#006400`,darkgrey:`#a9a9a9`,darkkhaki:`#bdb76b`,darkmagenta:`#8b008b`,darkolivegreen:`#556b2f`,darkorange:`#ff8c00`,darkorchid:`#9932cc`,darkred:`#8b0000`,darksalmon:`#e9967a`,darkseagreen:`#8fbc8f`,darkslateblue:`#483d8b`,darkslategray:`#2f4f4f`,darkslategrey:`#2f4f4f`,darkturquoise:`#00ced1`,darkviolet:`#9400d3`,deeppink:`#ff1493`,deepskyblue:`#00bfff`,dimgray:`#696969`,dimgrey:`#696969`,dodgerblue:`#1e90ff`,firebrick:`#b22222`,floralwhite:`#fffaf0`,forestgreen:`#228b22`,fuchsia:`#ff00ff`,gainsboro:`#dcdcdc`,ghostwhite:`#f8f8ff`,goldenrod:`#daa520`,gold:`#ffd700`,gray:`#808080`,green:`#008000`,greenyellow:`#adff2f`,grey:`#808080`,honeydew:`#f0fff0`,hotpink:`#ff69b4`,indianred:`#cd5c5c`,indigo:`#4b0082`,ivory:`#fffff0`,khaki:`#f0e68c`,lavenderblush:`#fff0f5`,lavender:`#e6e6fa`,lawngreen:`#7cfc00`,lemonchiffon:`#fffacd`,lightblue:`#add8e6`,lightcoral:`#f08080`,lightcyan:`#e0ffff`,lightgoldenrodyellow:`#fafad2`,lightgray:`#d3d3d3`,lightgreen:`#90ee90`,lightgrey:`#d3d3d3`,lightpink:`#ffb6c1`,lightsalmon:`#ffa07a`,lightseagreen:`#20b2aa`,lightskyblue:`#87cefa`,lightslategray:`#778899`,lightslategrey:`#778899`,lightsteelblue:`#b0c4de`,lightyellow:`#ffffe0`,lime:`#00ff00`,limegreen:`#32cd32`,linen:`#faf0e6`,magenta:`#ff00ff`,maroon:`#800000`,mediumaquamarine:`#66cdaa`,mediumblue:`#0000cd`,mediumorchid:`#ba55d3`,mediumpurple:`#9370db`,mediumseagreen:`#3cb371`,mediumslateblue:`#7b68ee`,mediumspringgreen:`#00fa9a`,mediumturquoise:`#48d1cc`,mediumvioletred:`#c71585`,midnightblue:`#191970`,mintcream:`#f5fffa`,mistyrose:`#ffe4e1`,moccasin:`#ffe4b5`,navajowhite:`#ffdead`,navy:`#000080`,oldlace:`#fdf5e6`,olive:`#808000`,olivedrab:`#6b8e23`,orange:`#ffa500`,orangered:`#ff4500`,orchid:`#da70d6`,palegoldenrod:`#eee8aa`,palegreen:`#98fb98`,paleturquoise:`#afeeee`,palevioletred:`#db7093`,papayawhip:`#ffefd5`,peachpuff:`#ffdab9`,peru:`#cd853f`,pink:`#ffc0cb`,plum:`#dda0dd`,powderblue:`#b0e0e6`,purple:`#800080`,rebeccapurple:`#663399`,red:`#ff0000`,rosybrown:`#bc8f8f`,royalblue:`#4169e1`,saddlebrown:`#8b4513`,salmon:`#fa8072`,sandybrown:`#f4a460`,seagreen:`#2e8b57`,seashell:`#fff5ee`,sienna:`#a0522d`,silver:`#c0c0c0`,skyblue:`#87ceeb`,slateblue:`#6a5acd`,slategray:`#708090`,slategrey:`#708090`,snow:`#fffafa`,springgreen:`#00ff7f`,steelblue:`#4682b4`,tan:`#d2b48c`,teal:`#008080`,thistle:`#d8bfd8`,tomato:`#ff6347`,turquoise:`#40e0d0`,violet:`#ee82ee`,wheat:`#f5deb3`,white:`#ffffff`,whitesmoke:`#f5f5f5`,yellow:`#ffff00`,yellowgreen:`#9acd32`};function iL(e){var t={r:0,g:0,b:0},n=1,r=null,i=null,a=null,o=!1,s=!1;return typeof e==`string`&&(e=lL(e)),typeof e==`object`&&(uL(e.r)&&uL(e.g)&&uL(e.b)?(t=GI(e.r,e.g,e.b),o=!0,s=String(e.r).substr(-1)===`%`?`prgb`:`rgb`):uL(e.h)&&uL(e.s)&&uL(e.v)?(r=UI(e.s),i=UI(e.v),t=XI(e.h,r,i),o=!0,s=`hsv`):uL(e.h)&&uL(e.s)&&uL(e.l)&&(r=UI(e.s),a=UI(e.l),t=JI(e.h,r,a),o=!0,s=`hsl`),Object.prototype.hasOwnProperty.call(e,`a`)&&(n=e.a)),n=HI(n),{ok:o,format:e.format||s,r:Math.min(255,Math.max(t.r,0)),g:Math.min(255,Math.max(t.g,0)),b:Math.min(255,Math.max(t.b,0)),a:n}}var aL=`(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)`,oL=`[\\s|\\(]+(${aL})[,|\\s]+(${aL})[,|\\s]+(${aL})\\s*\\)?`,sL=`[\\s|\\(]+(${aL})[,|\\s]+(${aL})[,|\\s]+(${aL})[,|\\s]+(${aL})\\s*\\)?`,cL={CSS_UNIT:new RegExp(aL),rgb:RegExp(`rgb`+oL),rgba:RegExp(`rgba`+sL),hsl:RegExp(`hsl`+oL),hsla:RegExp(`hsla`+sL),hsv:RegExp(`hsv`+oL),hsva:RegExp(`hsva`+sL),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/};function lL(e){if(e=e.trim().toLowerCase(),e.length===0)return!1;var t=!1;if(rL[e])e=rL[e],t=!0;else if(e===`transparent`)return{r:0,g:0,b:0,a:0,format:`name`};var n=cL.rgb.exec(e);return n?{r:n[1],g:n[2],b:n[3]}:(n=cL.rgba.exec(e),n?{r:n[1],g:n[2],b:n[3],a:n[4]}:(n=cL.hsl.exec(e),n?{h:n[1],s:n[2],l:n[3]}:(n=cL.hsla.exec(e),n?{h:n[1],s:n[2],l:n[3],a:n[4]}:(n=cL.hsv.exec(e),n?{h:n[1],s:n[2],v:n[3]}:(n=cL.hsva.exec(e),n?{h:n[1],s:n[2],v:n[3],a:n[4]}:(n=cL.hex8.exec(e),n?{r:tL(n[1]),g:tL(n[2]),b:tL(n[3]),a:eL(n[4]),format:t?`name`:`hex8`}:(n=cL.hex6.exec(e),n?{r:tL(n[1]),g:tL(n[2]),b:tL(n[3]),format:t?`name`:`hex`}:(n=cL.hex4.exec(e),n?{r:tL(n[1]+n[1]),g:tL(n[2]+n[2]),b:tL(n[3]+n[3]),a:eL(n[4]+n[4]),format:t?`name`:`hex8`}:(n=cL.hex3.exec(e),n?{r:tL(n[1]+n[1]),g:tL(n[2]+n[2]),b:tL(n[3]+n[3]),format:t?`name`:`hex`}:!1)))))))))}function uL(e){return!!cL.CSS_UNIT.exec(String(e))}var dL=function(){function e(t,n){if(t===void 0&&(t=``),n===void 0&&(n={}),t instanceof e)return t;typeof t==`number`&&(t=nL(t)),this.originalInput=t;var r=iL(t);this.originalInput=t,this.r=r.r,this.g=r.g,this.b=r.b,this.a=r.a,this.roundA=Math.round(100*this.a)/100,this.format=n.format??r.format,this.gradientType=n.gradientType,this.r<1&&(this.r=Math.round(this.r)),this.g<1&&(this.g=Math.round(this.g)),this.b<1&&(this.b=Math.round(this.b)),this.isValid=r.ok}return e.prototype.isDark=function(){return this.getBrightness()<128},e.prototype.isLight=function(){return!this.isDark()},e.prototype.getBrightness=function(){var e=this.toRgb();return(e.r*299+e.g*587+e.b*114)/1e3},e.prototype.getLuminance=function(){var e=this.toRgb(),t,n,r,i=e.r/255,a=e.g/255,o=e.b/255;return t=i<=.03928?i/12.92:((i+.055)/1.055)**2.4,n=a<=.03928?a/12.92:((a+.055)/1.055)**2.4,r=o<=.03928?o/12.92:((o+.055)/1.055)**2.4,.2126*t+.7152*n+.0722*r},e.prototype.getAlpha=function(){return this.a},e.prototype.setAlpha=function(e){return this.a=HI(e),this.roundA=Math.round(100*this.a)/100,this},e.prototype.isMonochrome=function(){return this.toHsl().s===0},e.prototype.toHsv=function(){var e=YI(this.r,this.g,this.b);return{h:e.h*360,s:e.s,v:e.v,a:this.a}},e.prototype.toHsvString=function(){var e=YI(this.r,this.g,this.b),t=Math.round(e.h*360),n=Math.round(e.s*100),r=Math.round(e.v*100);return this.a===1?`hsv(${t}, ${n}%, ${r}%)`:`hsva(${t}, ${n}%, ${r}%, ${this.roundA})`},e.prototype.toHsl=function(){var e=KI(this.r,this.g,this.b);return{h:e.h*360,s:e.s,l:e.l,a:this.a}},e.prototype.toHslString=function(){var e=KI(this.r,this.g,this.b),t=Math.round(e.h*360),n=Math.round(e.s*100),r=Math.round(e.l*100);return this.a===1?`hsl(${t}, ${n}%, ${r}%)`:`hsla(${t}, ${n}%, ${r}%, ${this.roundA})`},e.prototype.toHex=function(e){return e===void 0&&(e=!1),ZI(this.r,this.g,this.b,e)},e.prototype.toHexString=function(e){return e===void 0&&(e=!1),`#`+this.toHex(e)},e.prototype.toHex8=function(e){return e===void 0&&(e=!1),QI(this.r,this.g,this.b,this.a,e)},e.prototype.toHex8String=function(e){return e===void 0&&(e=!1),`#`+this.toHex8(e)},e.prototype.toHexShortString=function(e){return e===void 0&&(e=!1),this.a===1?this.toHexString(e):this.toHex8String(e)},e.prototype.toRgb=function(){return{r:Math.round(this.r),g:Math.round(this.g),b:Math.round(this.b),a:this.a}},e.prototype.toRgbString=function(){var e=Math.round(this.r),t=Math.round(this.g),n=Math.round(this.b);return this.a===1?`rgb(${e}, ${t}, ${n})`:`rgba(${e}, ${t}, ${n}, ${this.roundA})`},e.prototype.toPercentageRgb=function(){var e=function(e){return`${Math.round(RI(e,255)*100)}%`};return{r:e(this.r),g:e(this.g),b:e(this.b),a:this.a}},e.prototype.toPercentageRgbString=function(){var e=function(e){return Math.round(RI(e,255)*100)};return this.a===1?`rgb(${e(this.r)}%, ${e(this.g)}%, ${e(this.b)}%)`:`rgba(${e(this.r)}%, ${e(this.g)}%, ${e(this.b)}%, ${this.roundA})`},e.prototype.toName=function(){if(this.a===0)return`transparent`;if(this.a<1)return!1;for(var e=`#`+ZI(this.r,this.g,this.b,!1),t=0,n=Object.entries(rL);t<n.length;t++){var r=n[t],i=r[0];if(e===r[1])return i}return!1},e.prototype.toString=function(e){var t=!!e;e??=this.format;var n=!1,r=this.a<1&&this.a>=0;return!t&&r&&(e.startsWith(`hex`)||e===`name`)?e===`name`&&this.a===0?this.toName():this.toRgbString():(e===`rgb`&&(n=this.toRgbString()),e===`prgb`&&(n=this.toPercentageRgbString()),(e===`hex`||e===`hex6`)&&(n=this.toHexString()),e===`hex3`&&(n=this.toHexString(!0)),e===`hex4`&&(n=this.toHex8String(!0)),e===`hex8`&&(n=this.toHex8String()),e===`name`&&(n=this.toName()),e===`hsl`&&(n=this.toHslString()),e===`hsv`&&(n=this.toHsvString()),n||this.toHexString())},e.prototype.toNumber=function(){return(Math.round(this.r)<<16)+(Math.round(this.g)<<8)+Math.round(this.b)},e.prototype.clone=function(){return new e(this.toString())},e.prototype.lighten=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.l+=t/100,n.l=zI(n.l),new e(n)},e.prototype.brighten=function(t){t===void 0&&(t=10);var n=this.toRgb();return n.r=Math.max(0,Math.min(255,n.r-Math.round(255*-(t/100)))),n.g=Math.max(0,Math.min(255,n.g-Math.round(255*-(t/100)))),n.b=Math.max(0,Math.min(255,n.b-Math.round(255*-(t/100)))),new e(n)},e.prototype.darken=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.l-=t/100,n.l=zI(n.l),new e(n)},e.prototype.tint=function(e){return e===void 0&&(e=10),this.mix(`white`,e)},e.prototype.shade=function(e){return e===void 0&&(e=10),this.mix(`black`,e)},e.prototype.desaturate=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.s-=t/100,n.s=zI(n.s),new e(n)},e.prototype.saturate=function(t){t===void 0&&(t=10);var n=this.toHsl();return n.s+=t/100,n.s=zI(n.s),new e(n)},e.prototype.greyscale=function(){return this.desaturate(100)},e.prototype.spin=function(t){var n=this.toHsl(),r=(n.h+t)%360;return n.h=r<0?360+r:r,new e(n)},e.prototype.mix=function(t,n){n===void 0&&(n=50);var r=this.toRgb(),i=new e(t).toRgb(),a=n/100;return new e({r:(i.r-r.r)*a+r.r,g:(i.g-r.g)*a+r.g,b:(i.b-r.b)*a+r.b,a:(i.a-r.a)*a+r.a})},e.prototype.analogous=function(t,n){t===void 0&&(t=6),n===void 0&&(n=30);var r=this.toHsl(),i=360/n,a=[this];for(r.h=(r.h-(i*t>>1)+720)%360;--t;)r.h=(r.h+i)%360,a.push(new e(r));return a},e.prototype.complement=function(){var t=this.toHsl();return t.h=(t.h+180)%360,new e(t)},e.prototype.monochromatic=function(t){t===void 0&&(t=6);for(var n=this.toHsv(),r=n.h,i=n.s,a=n.v,o=[],s=1/t;t--;)o.push(new e({h:r,s:i,v:a})),a=(a+s)%1;return o},e.prototype.splitcomplement=function(){var t=this.toHsl(),n=t.h;return[this,new e({h:(n+72)%360,s:t.s,l:t.l}),new e({h:(n+216)%360,s:t.s,l:t.l})]},e.prototype.onBackground=function(t){var n=this.toRgb(),r=new e(t).toRgb(),i=n.a+r.a*(1-n.a);return new e({r:(n.r*n.a+r.r*r.a*(1-n.a))/i,g:(n.g*n.a+r.g*r.a*(1-n.a))/i,b:(n.b*n.a+r.b*r.a*(1-n.a))/i,a:i})},e.prototype.triad=function(){return this.polyad(3)},e.prototype.tetrad=function(){return this.polyad(4)},e.prototype.polyad=function(t){for(var n=this.toHsl(),r=n.h,i=[this],a=360/t,o=1;o<t;o++)i.push(new e({h:(r+o*a)%360,s:n.s,l:n.l}));return i},e.prototype.equals=function(t){return this.toRgbString()===new e(t).toRgbString()},e}();function fL(...e){return new dL(...e)}function pL(e,t){let n=e&&e.a,r;r=e&&e.hsl?fL(e.hsl):e&&e.hex&&e.hex.length>0?fL(e.hex):e&&e.hsv?fL(e.hsv):e&&e.rgba?fL(e.rgba):e&&e.rgb?fL(e.rgb):fL(e),r&&(r._a===void 0||r._a===null)&&r.setAlpha(n||r.getAlpha());let i=r.toHsl(),a=r.toHsv();return i.s===0&&(a.h=i.h=e.h||e.hsl&&e.hsl.h||t||0),a.v<.0164&&(a.h=e.h||e.hsv&&e.hsv.h||0,a.s=e.s||e.hsv&&e.hsv.s||0),i.l<.01&&(i.h=e.h||e.hsl&&e.hsl.h||0,i.s=e.s||e.hsl&&e.hsl.s||0),{hsl:i,hex:r.toHexString().toUpperCase(),hex8:r.toHex8String().toUpperCase(),rgba:r.toRgb(),hsv:a,oldHue:e.h||t||i.h,source:e.source,a:r.getAlpha()}}var mL={model:{prop:`modelValue`,event:`update:modelValue`},props:[`modelValue`],data(){return{val:pL(this.modelValue)}},computed:{colors:{get(){return this.val},set(e){this.val=e,this.$emit(`update:modelValue`,e)}}},watch:{modelValue(e){this.val=pL(e)}},methods:{colorChange(e,t){this.oldHue=this.colors.hsl.h,this.colors=pL(e,t||this.oldHue)},isValidHex(e){return fL(e).isValid},simpleCheckForValidColor(e){let t=[`r`,`g`,`b`,`a`,`h`,`s`,`l`,`v`],n=0,r=0;for(let i=0;i<t.length;i++){let a=t[i];e[a]&&(n++,isNaN(e[a])||r++)}if(n===r)return e},paletteUpperCase(e){return e.map(e=>e.toUpperCase())},isTransparent(e){return fL(e).getAlpha()===0}}},hL={name:`EditableInput`,props:{label:String,labelText:String,desc:String,value:[String,Number],max:Number,min:Number,arrowOffset:{type:Number,default:1}},computed:{val:{get(){return this.value},set(e){if(this.max!==void 0&&+e>this.max)this.$refs.input.value=this.max;else return e}},labelId(){return`input__label__${this.label}__${Math.random().toString().slice(2,5)}`},labelSpanText(){return this.labelText||this.label}},methods:{update(e){this.handleChange(e.target.value)},handleChange(e){let t={};t[this.label]=e,(t.hex===void 0&&t[`#`]===void 0||e.length>5)&&this.$emit(`change`,t)},handleKeyDown(e){let{val:t}=this,n=Number(t);if(n){let r=this.arrowOffset||1;e.keyCode===38&&(t=n+r,this.handleChange(t),e.preventDefault()),e.keyCode===40&&(t=n-r,this.handleChange(t),e.preventDefault())}}}},gL={class:`vc-editable-input`},_L=[`aria-labelledby`],vL=[`id`,`for`],yL={class:`vc-input__desc`};function bL(e,t,n,r,i,a){return B(),V(`div`,gL,[I(U(`input`,{ref:`input`,"onUpdate:modelValue":t[0]||=e=>a.val=e,"aria-labelledby":a.labelId,class:`vc-input__input`,onKeydown:t[1]||=(...e)=>a.handleKeyDown&&a.handleKeyDown(...e),onInput:t[2]||=(...e)=>a.update&&a.update(...e)},null,40,_L),[[il,a.val]]),U(`span`,{id:a.labelId,for:n.label,class:`vc-input__label`},M(a.labelSpanText),9,vL),U(`span`,yL,M(n.desc),1)])}EI(`.vc-editable-input{position:relative}.vc-input__input{border:0;outline:none;padding:0}.vc-input__label{text-transform:capitalize}`),hL.render=bL,hL.__file=`src/components/editable-input/editable-input.vue`,hL.install=DI;function xL(e,t,n){return t<n?e<t?t:e>n?n:e:e<n?n:e>t?t:e}var SL={name:`Saturation`,props:{value:Object},computed:{colors(){return this.value},bgColor(){return`hsl(${this.colors.hsv.h}, 100%, 50%)`},pointerTop(){return`${-(this.colors.hsv.v*100)+1+100}%`},pointerLeft(){return`${this.colors.hsv.s*100}%`}},methods:{handleChange(e,t){!t&&e.preventDefault();let{container:n}=this.$refs;if(!n)return;let r=n.clientWidth,i=n.clientHeight,a=n.getBoundingClientRect().left+window.pageXOffset,o=n.getBoundingClientRect().top+window.pageYOffset,s=e.pageX||(e.touches?e.touches[0].pageX:0),c=e.pageY||(e.touches?e.touches[0].pageY:0),l=xL(s-a,0,r),u=xL(c-o,0,i),d=l/r,f=xL(-(u/i)+1,0,1);this.onChange({h:this.colors.hsv.h,s:d,v:f,a:this.colors.hsv.a,source:`hsva`})},onChange(e){this.$emit(`change`,e)},handleMouseDown(e){window.addEventListener(`mousemove`,this.handleChange),window.addEventListener(`mouseup`,this.handleChange),window.addEventListener(`mouseup`,this.handleMouseUp)},handleMouseUp(e){this.unbindEventListeners()},unbindEventListeners(){window.removeEventListener(`mousemove`,this.handleChange),window.removeEventListener(`mouseup`,this.handleChange),window.removeEventListener(`mouseup`,this.handleMouseUp)}}},CL=U(`div`,{class:`vc-saturation--white`},null,-1),wL=U(`div`,{class:`vc-saturation--black`},null,-1),TL=[U(`div`,{class:`vc-saturation-circle`},null,-1)];function EL(e,t,n,r,i,a){return B(),V(`div`,{ref:`container`,class:`vc-saturation`,style:A({background:a.bgColor}),onMousedown:t[0]||=(...e)=>a.handleMouseDown&&a.handleMouseDown(...e),onTouchmove:t[1]||=(...e)=>a.handleChange&&a.handleChange(...e),onTouchstart:t[2]||=(...e)=>a.handleChange&&a.handleChange(...e)},[CL,wL,U(`div`,{class:`vc-saturation-pointer`,style:A({top:a.pointerTop,left:a.pointerLeft})},TL,4)],36)}EI(`.vc-saturation,.vc-saturation--black,.vc-saturation--white{bottom:0;cursor:pointer;left:0;position:absolute;right:0;top:0}.vc-saturation--white{background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.vc-saturation--black{background:linear-gradient(0deg,#000,transparent)}.vc-saturation-pointer{cursor:pointer;position:absolute}.vc-saturation-circle{border-radius:50%;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);cursor:head;height:4px;transform:translate(-2px,-2px);width:4px}`),SL.render=EL,SL.__file=`src/components/saturation/saturation.vue`,SL.install=DI;var DL={name:`Hue`,props:{value:Object,direction:{type:String,default:`horizontal`}},data(){return{oldHue:0,pullDirection:``}},computed:{colors(){return this.value},directionClass(){return{"vc-hue--horizontal":this.direction===`horizontal`,"vc-hue--vertical":this.direction===`vertical`}},pointerTop(){return this.direction===`vertical`?this.colors.hsl.h===0&&this.pullDirection===`right`?0:`${-(this.colors.hsl.h*100/360)+100}%`:0},pointerLeft(){return this.direction===`vertical`?0:this.colors.hsl.h===0&&this.pullDirection===`right`?`100%`:`${this.colors.hsl.h*100/360}%`}},watch:{value:{handler(e,t){let{h:n}=e.hsl;n!==0&&n-this.oldHue>0&&(this.pullDirection=`right`),n!==0&&n-this.oldHue<0&&(this.pullDirection=`left`),this.oldHue=n},deep:!0,immediate:!0}},methods:{handleChange(e,t){!t&&e.preventDefault();let{container:n}=this.$refs;if(!n)return;let r=n.clientWidth,i=n.clientHeight,a=n.getBoundingClientRect().left+window.pageXOffset,o=n.getBoundingClientRect().top+window.pageYOffset,s=e.pageX||(e.touches?e.touches[0].pageX:0),c=e.pageY||(e.touches?e.touches[0].pageY:0),l=s-a,u=c-o,d,f;this.direction===`vertical`?(u<0?d=360:u>i?d=0:(f=-(u*100/i)+100,d=360*f/100),this.colors.hsl.h!==d&&this.$emit(`change`,{h:d,s:this.colors.hsl.s,l:this.colors.hsl.l,a:this.colors.hsl.a,source:`hsl`})):(l<0?d=0:l>r?d=360:(f=l*100/r,d=360*f/100),this.colors.hsl.h!==d&&this.$emit(`change`,{h:d,s:this.colors.hsl.s,l:this.colors.hsl.l,a:this.colors.hsl.a,source:`hsl`}))},handleMouseDown(e){this.handleChange(e,!0),window.addEventListener(`mousemove`,this.handleChange),window.addEventListener(`mouseup`,this.handleChange),window.addEventListener(`mouseup`,this.handleMouseUp)},handleMouseUp(e){this.unbindEventListeners()},unbindEventListeners(){window.removeEventListener(`mousemove`,this.handleChange),window.removeEventListener(`mouseup`,this.handleChange),window.removeEventListener(`mouseup`,this.handleMouseUp)}}},OL=[`aria-valuenow`],kL=[U(`div`,{class:`vc-hue-picker`},null,-1)];function AL(e,t,n,r,i,a){return B(),V(`div`,{class:j([`vc-hue`,[a.directionClass]])},[U(`div`,{ref:`container`,class:`vc-hue-container`,role:`slider`,"aria-valuenow":a.colors.hsl.h,"aria-valuemin":`0`,"aria-valuemax":`360`,onMousedown:t[0]||=(...e)=>a.handleMouseDown&&a.handleMouseDown(...e),onTouchmove:t[1]||=(...e)=>a.handleChange&&a.handleChange(...e),onTouchstart:t[2]||=(...e)=>a.handleChange&&a.handleChange(...e)},[U(`div`,{class:`vc-hue-pointer`,style:A({top:a.pointerTop,left:a.pointerLeft}),role:`presentation`},kL,4)],40,OL)],2)}EI(`.vc-hue{border-radius:2px;bottom:0;left:0;position:absolute;right:0;top:0}.vc-hue--horizontal{background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.vc-hue--vertical{background:linear-gradient(0deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.vc-hue-container{cursor:pointer;height:100%;margin:0 2px;position:relative}.vc-hue-pointer{position:absolute;z-index:2}.vc-hue-picker{background:#fff;border-radius:1px;box-shadow:0 0 2px rgba(0,0,0,.6);cursor:pointer;height:8px;margin-top:1px;transform:translateX(-2px);width:4px}`),DL.render=AL,DL.__file=`src/components/hue/hue.vue`,DL.install=DI;var jL=[`#D0021B`,`#F5A623`,`#F8E71C`,`#8B572A`,`#7ED321`,`#417505`,`#BD10E0`,`#9013FE`,`#4A90E2`,`#50E3C2`,`#B8E986`,`#000000`,`#4A4A4A`,`#9B9B9B`,`#FFFFFF`,`rgba(0,0,0,0)`],ML={name:`Sketch`,components:{Saturation:SL,Hue:DL,Alpha:NI,EdIn:hL,Checkboard:kI},mixins:[mL],props:{presetColors:{type:Array,default(){return jL}},disableAlpha:{type:Boolean,default:!1},disableFields:{type:Boolean,default:!1}},computed:{hex(){let e;return e=this.colors.a<1?this.colors.hex8:this.colors.hex,e.replace(`#`,``)},activeColor(){let{rgba:e}=this.colors;return`rgba(${[e.r,e.g,e.b,e.a].join(`,`)})`}},methods:{handlePreset(e){this.colorChange(e)},childChange(e){this.colorChange(e)},inputChange(e){e&&(e.hex?this.isValidHex(e.hex)&&this.colorChange({hex:e.hex,source:`hex`}):(e.r||e.g||e.b||e.a)&&this.colorChange({r:e.r||this.colors.rgba.r,g:e.g||this.colors.rgba.g,b:e.b||this.colors.rgba.b,a:e.a||this.colors.rgba.a,source:`rgba`}))}}},NL={class:`vc-sketch-saturation-wrap`},PL={class:`vc-sketch-controls`},FL={class:`vc-sketch-sliders`},IL={class:`vc-sketch-hue-wrap`},LL={key:0,class:`vc-sketch-alpha-wrap`},RL={class:`vc-sketch-color-wrap`},zL=[`aria-label`],BL={key:0,class:`vc-sketch-field`},VL={class:`vc-sketch-field--double`},HL={class:`vc-sketch-field--single`},UL={class:`vc-sketch-field--single`},WL={class:`vc-sketch-field--single`},GL={key:0,class:`vc-sketch-field--single`},KL={class:`vc-sketch-presets`,role:`group`,"aria-label":`A color preset, pick one to set as current color`},qL=[`aria-label`,`onClick`],JL=[`aria-label`,`onClick`];function YL(e,t,n,r,i,a){let o=L(`Saturation`),s=L(`Hue`),c=L(`Alpha`),l=L(`Checkboard`),u=L(`EdIn`);return B(),V(`div`,{role:`application`,"aria-label":`Sketch color picker`,class:j([`vc-sketch`,[n.disableAlpha?`vc-sketch__disable-alpha`:``]])},[U(`div`,NL,[W(o,{value:e.colors,onChange:a.childChange},null,8,[`value`,`onChange`])]),U(`div`,PL,[U(`div`,FL,[U(`div`,IL,[W(s,{value:e.colors,onChange:a.childChange},null,8,[`value`,`onChange`])]),n.disableAlpha?K(`v-if`,!0):(B(),V(`div`,LL,[W(c,{value:e.colors,onChange:a.childChange},null,8,[`value`,`onChange`])]))]),U(`div`,RL,[U(`div`,{"aria-label":`Current color is ${a.activeColor}`,class:`vc-sketch-active-color`,style:A({background:a.activeColor})},null,12,zL),W(l)])]),n.disableFields?K(`v-if`,!0):(B(),V(`div`,BL,[K(` rgba `),U(`div`,VL,[W(u,{label:`hex`,value:a.hex,onChange:a.inputChange},null,8,[`value`,`onChange`])]),U(`div`,HL,[W(u,{label:`r`,value:e.colors.rgba.r,onChange:a.inputChange},null,8,[`value`,`onChange`])]),U(`div`,UL,[W(u,{label:`g`,value:e.colors.rgba.g,onChange:a.inputChange},null,8,[`value`,`onChange`])]),U(`div`,WL,[W(u,{label:`b`,value:e.colors.rgba.b,onChange:a.inputChange},null,8,[`value`,`onChange`])]),n.disableAlpha?K(`v-if`,!0):(B(),V(`div`,GL,[W(u,{label:`a`,value:e.colors.a,"arrow-offset":.01,max:1,onChange:a.inputChange},null,8,[`value`,`arrow-offset`,`onChange`])]))])),U(`div`,KL,[(B(!0),V(z,null,R(n.presetColors,t=>(B(),V(z,null,[e.isTransparent(t)?(B(),V(`div`,{key:t,"aria-label":`Color:${t}`,class:`vc-sketch-presets-color`,onClick:e=>a.handlePreset(t)},[W(l)],8,JL)):(B(),V(`div`,{key:`!${t}`,class:`vc-sketch-presets-color`,"aria-label":`Color:${t}`,style:A({background:t}),onClick:e=>a.handlePreset(t)},null,12,qL))],64))),256))])],2)}EI(`.vc-sketch{background:#fff;border-radius:4px;box-shadow:0 0 0 1px rgba(0,0,0,.15),0 8px 16px rgba(0,0,0,.15);box-sizing:initial;padding:10px 10px 0;position:relative;width:200px}.vc-sketch-saturation-wrap{overflow:hidden;padding-bottom:75%;position:relative;width:100%}.vc-sketch-controls{display:flex}.vc-sketch-sliders{flex:1;padding:4px 0}.vc-sketch-sliders .vc-alpha-gradient,.vc-sketch-sliders .vc-hue{border-radius:2px}.vc-sketch-alpha-wrap,.vc-sketch-hue-wrap{height:10px;position:relative}.vc-sketch-alpha-wrap{margin-top:4px;overflow:hidden}.vc-sketch-color-wrap{border-radius:3px;height:24px;margin-left:4px;margin-top:4px;position:relative;width:24px}.vc-sketch-active-color{border-radius:2px;bottom:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15),inset 0 0 4px rgba(0,0,0,.25);left:0;position:absolute;right:0;top:0;z-index:2}.vc-sketch-color-wrap .vc-checkerboard{background-size:auto}.vc-sketch-field{display:flex;padding-top:4px}.vc-sketch-field .vc-input__input{border:none;box-shadow:inset 0 0 0 1px #ccc;font-size:10px;padding:4px 0 3px 10%;width:90%}.vc-sketch-field .vc-input__label{color:#222;display:block;font-size:11px;padding-bottom:4px;padding-top:3px;text-align:center;text-transform:capitalize}.vc-sketch-field--single{flex:1;padding-left:6px}.vc-sketch-field--double{flex:2}.vc-sketch-presets{border-top:1px solid #eee;margin-left:-10px;margin-right:-10px;padding-left:10px;padding-top:10px}.vc-sketch-presets-color{cursor:pointer;display:inline-block;height:16px;margin:0 10px 10px 0;overflow:hidden;position:relative;vertical-align:top;width:16px}.vc-sketch-presets-color,.vc-sketch-presets-color .vc-checkerboard{border-radius:3px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}.vc-sketch__disable-alpha .vc-sketch-color-wrap{height:10px}`),ML.render=YL,ML.__file=`src/components/sketch/sketch.vue`,ML.install=DI;function XL(e){let t=String(e||``).trim();if(!t)return null;let n=t.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:1};if(n=t.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i),n){let e=e=>parseInt(e+e,16);return{r:e(n[1]),g:e(n[2]),b:e(n[3]),a:1}}if(n=t.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i),n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:parseInt(n[4],16)/255};if(n=t.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)$/i),n){let e=n[4]===void 0?1:parseFloat(n[4]);return{r:Math.round(parseFloat(n[1])),g:Math.round(parseFloat(n[2])),b:Math.round(parseFloat(n[3])),a:e}}return null}function ZL(e){if(!e)return`#000000`;let t=e=>Math.max(0,Math.min(255,Math.round(e))).toString(16).padStart(2,`0`);return`#`+t(e.r)+t(e.g)+t(e.b)}function QL(e){return e?e.a>=1?ZL(e):`rgba(${Math.round(e.r)}, ${Math.round(e.g)}, ${Math.round(e.b)}, ${+e.a.toFixed(2)})`:``}var $L={name:`SetColor`,components:{Sketch:ML},props:jg,emits:Mg,data(){return{_rgb:null,popOpen:!1,popW:240,popStyle:{position:`fixed`,left:`0px`,top:`0px`}}},computed:{text(){return this.value===void 0||this.value===null?``:String(this.value)},parsed(){return XL(this.text)||{r:0,g:0,b:0,a:1}},pickerValue(){return this.text||`#000000`},alpha(){return this.parsed.a},displayColor(){return QL(this.parsed)}},watch:{text(){this._rgb=XL(this.text)}},beforeUnmount(){this.removeDocListener()},methods:{onTextInput(e){this._rgb=XL(e),this.$emit(`input`,e)},onAlphaChange(e){let t=Math.max(0,Math.min(1,parseInt(e,10)/100)),n={...this._rgb||this.parsed,a:t};this._rgb=n,this.$emit(`input`,QL(n)),this.$emit(`change`)},onPicker(e){let t=e&&e.rgba,n,r,i,a;if(Array.isArray(t))[n,r,i,a]=t;else if(t)n=t.r,r=t.g,i=t.b,a=t.a;else{let t=XL(e.hex)||{r:0,g:0,b:0,a:1};n=t.r,r=t.g,i=t.b,a=t.a}a??=1;let o=e.hex||ZL({r:n,g:r,b:i,a:1});this._rgb={r:n,g:r,b:i,a},this.$emit(`input`,a>=1?o:`rgba(${Math.round(n)}, ${Math.round(r)}, ${Math.round(i)}, ${+a.toFixed(2)})`),this.$emit(`change`)},clear(){this.disabled||(this._rgb=null,this.closePop(),this.$emit(`input`,``),this.$emit(`change`))},togglePop(){this.disabled||(this.popOpen?this.closePop():this.openPop())},openPop(){let e=this.$refs.swatch;if(!e)return;let t=e.getBoundingClientRect(),n=this.$refs.top&&this.$refs.top.getBoundingClientRect()||t,r=Math.max(220,Math.min(Math.round(n.width),400)),i=window.innerWidth,a=window.innerHeight,o=n.left,s=t.bottom+6;o+r>i-8&&(o=Math.max(8,i-r-8)),s+320>a-8&&(s=Math.max(8,t.top-320-6)),this.popW=r,this.popStyle={position:`fixed`,left:o+`px`,top:s+`px`,width:r+`px`,zIndex:4e3},this.popOpen=!0,this.$nextTick(()=>{document.addEventListener(`mousedown`,this.onDocClick,!0)})},closePop(){this.popOpen&&(this.popOpen=!1,this.removeDocListener())},removeDocListener(){document.removeEventListener(`mousedown`,this.onDocClick,!0)},onDocClick(e){let t=this.$refs.pop,n=this.$refs.swatch;t&&t.contains(e.target)||n&&n.contains(e.target)||this.closePop()}}},eR={class:`st-color`},tR={class:`st-color__top`,ref:`top`},nR=[`title`,`disabled`],rR=[`disabled`,`value`],iR=[`disabled`],aR={key:0,class:`st-color__alpha-row`},oR=[`disabled`,`value`],sR={class:`st-color__alpha-val`};function cR(e,t,n,r,i,a){let o=L(`Sketch`);return B(),V(`div`,eR,[K(` 色块预览 + 文本输入 + 重置(顶行) `),U(`div`,tR,[U(`button`,{ref:`swatch`,class:`st-color__swatch`,type:`button`,title:a.text||`未设置`,disabled:e.disabled,onClick:t[0]||=(...e)=>a.togglePop&&a.togglePop(...e)},[t[7]||=U(`span`,{class:`st-color__checker`},null,-1),U(`span`,{class:`st-color__fill`,style:A({background:a.displayColor||`transparent`})},null,4)],8,nR),U(`input`,{class:`ni-input st-color__text`,type:`text`,placeholder:`如 #333333 / rgba(0,0,0,.5)`,disabled:e.disabled,value:a.text,onInput:t[1]||=e=>a.onTextInput(e.target.value),onChange:t[2]||=t=>e.$emit(`change`)},null,40,rR),U(`button`,{class:`st-color__clear`,type:`button`,title:`重置(清空颜色)`,disabled:e.disabled,onClick:t[3]||=(...e)=>a.clear&&a.clear(...e)},[...t[8]||=[U(`svg`,{viewBox:`0 0 16 16`,class:`st-ic`,"aria-hidden":`true`},[U(`use`,{href:`#icon-reset`})],-1)]],8,iR)],512),K(` 透明度滑块(仅当颜色值非空时显示),作为快捷调节 `),a.text?(B(),V(`div`,aR,[t[9]||=U(`span`,{class:`st-color__alpha-label`},`透明度`,-1),U(`input`,{class:`st-color__alpha-slider`,type:`range`,min:`0`,max:`100`,disabled:e.disabled,value:Math.round(a.alpha*100),onInput:t[4]||=e=>a.onAlphaChange(e.target.value),onChange:t[5]||=t=>e.$emit(`change`)},null,40,oR),U(`span`,sR,M(Math.round(a.alpha*100))+`%`,1)])):K(`v-if`,!0),K(` 第三方颜色选择器弹层(挂载到 body,避免被滚动容器裁切) `),(B(),H(ai,{to:`body`},[i.popOpen?(B(),V(`div`,{key:0,ref:`pop`,class:`st-color__pop`,style:A(i.popStyle),onMousedown:t[6]||=q(()=>{},[`stop`])},[W(o,{"model-value":a.pickerValue,"disable-alpha":!1,"onUpdate:modelValue":a.onPicker},null,8,[`model-value`,`onUpdate:modelValue`])],36)):K(`v-if`,!0)]))])}var lR=X($L,[[`render`,cR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetColor.vue`]]),uR={name:`SetIconSelect`,components:{SvgSymbols:xd},props:jg,emits:Mg,data(){return{open:!1}},computed:{list(){return this.options.iIconList||[]}},methods:{pick(e){this.disabled||(this.open=!1,this.$emit(`input`,e.key),this.$emit(`change`))}}},dR={class:`st-iconsel-wrap`},fR={class:`st-iconsel`},pR={class:`st-iconsel__preview`},mR={key:1,style:{"font-size":`11px`,color:`var(--text-faint)`}},hR=[`disabled`,`value`],gR={key:0,class:`st-iconsel__grid`},_R=[`title`,`onClick`],vR={key:0,class:`st-list__empty`};function yR(e,t,n,r,i,a){let o=L(`SvgSymbols`);return B(),V(`div`,dR,[U(`div`,fR,[U(`span`,pR,[e.value?(B(),H(o,{key:0,icon:String(e.value),color:`currentColor`},null,8,[`icon`])):(B(),V(`span`,mR,`无`))]),U(`input`,{class:`ni-input`,type:`text`,placeholder:`图标 key`,disabled:e.disabled,value:e.value||``,onInput:t[0]||=t=>e.$emit(`input`,t.target.value),onChange:t[1]||=t=>e.$emit(`change`)},null,40,hR),U(`button`,{class:`st-minibtn`,type:`button`,onClick:t[2]||=e=>i.open=!i.open},M(i.open?`收起`:`选择`),1)]),i.open?(B(),V(`div`,gR,[(B(!0),V(z,null,R(a.list,t=>(B(),V(`span`,{key:t.key,class:j([`st-iconsel__cell`,{"st-iconsel__cell--on":t.key===e.value}]),title:t.name||t.value||t.key,onClick:e=>a.pick(t)},[W(o,{icon:t.key,color:`currentColor`},null,8,[`icon`])],10,_R))),128)),a.list.length?K(`v-if`,!0):(B(),V(`p`,vR,`该组件未提供图标列表`))])):K(`v-if`,!0)])}var bR=X(uR,[[`render`,yR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetIconSelect.vue`]]);Prism.languages.javascript=Prism.languages.extend(`clike`,{"class-name":[Prism.languages.clike[`class-name`],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(`(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])`),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript[`class-name`][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore(`javascript`,`keyword`,{regex:{pattern:RegExp(`((?:^|[^$\\w\\xA0-\\uFFFF."'\\])\\s]|\\b(?:return|yield))\\s*)\\/(?:(?:\\[(?:[^\\]\\\\\\r\\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.|\\[(?:[^[\\]\\\\\\r\\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\\r\\n])+\\/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/)*(?:$|[\\r\\n,.;:})\\]]|\\/\\/))`),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:`language-regex`,inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:`function`},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore(`javascript`,`string`,{hashbang:{pattern:/^#!.*/,greedy:!0,alias:`comment`},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:`string`},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:`punctuation`},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:`property`}}),Prism.languages.insertBefore(`javascript`,`operator`,{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:`property`}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined(`script`,`javascript`),Prism.languages.markup.tag.addAttribute(`on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)`,`javascript`)),Prism.languages.js=Prism.languages.javascript,Yg.default.languages.javascript&&!Yg.default.languages.javascript[`binding-var`]&&Yg.default.languages.insertBefore(`javascript`,`keyword`,{"binding-var":/\$[A-Za-z_$][\w$]*/});var xR={name:`SetExpr`,props:{...jg,placeholder:{type:String,default:``}},emits:Mg,data(){return{code:``}},computed:{lines(){return this.code?this.code.split(`
|
|
306
|
+
`).length:0},chars(){return this.code.length}},watch:{value(e){this.syncFromValue(e)}},mounted(){this.code=this.readValue(this.value),this.$nextTick(()=>this.initJar())},beforeUnmount(){this._t&&clearTimeout(this._t),this._jar&&this._jar.destroy&&this._jar.destroy()},methods:{readValue(e){return e==null?``:typeof e==`string`?e:String(e)},syncFromValue(e){let t=this.readValue(e);if(t===this.code)return;let n=this.$refs.editor;n&&document.activeElement===n||(this.code=t,this._jar&&this._jar.updateCode(t))},initJar(){let e=this.$refs.editor;if(!e)return;let t=e=>{e.innerHTML=Yg.default.highlight(e.textContent,Yg.default.languages.javascript,`javascript`)};this._jar=Jg(e,t,{tab:` `,indentOn:/[({[]$/,addClosing:!0,history:!0}),this._jar.updateCode(this.code),this._jar.onUpdate(e=>this.onCode(e))},onCode(e){this.disabled||(this.code=e,this.$emit(`input`,e),this._t&&clearTimeout(this._t),this._t=setTimeout(()=>this.$emit(`change`),400))}}},SR={key:0,class:`st-expr__ph`},CR={class:`st-expr__foot`},wR={class:`st-expr__hint`};function TR(e,t,n,r,i,a){return B(),V(`div`,{class:j([`st-expr`,{"st-expr--disabled":e.disabled}])},[U(`div`,{ref:`editor`,class:j([`st-expr__editor`,{"is-disabled":e.disabled}])},null,2),n.placeholder&&!i.code?(B(),V(`span`,SR,M(n.placeholder),1)):K(`v-if`,!0),U(`div`,CR,[U(`span`,wR,M(a.lines)+` 行 · `+M(a.chars)+` 字符`,1)])],2)}var ER=X(xR,[[`render`,TR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetExpr.vue`]]),DR={name:`SetIfForm`,components:{SetExpr:ER},props:jg,emits:Mg,computed:{obj(){return this.value&&typeof this.value==`object`?this.value:{}},expression(){return this.obj.expression||``},name(){return this.obj.name||``}},methods:{setExpression(e){let t=!this.name||this.name===this.expression;this.$emit(`input`,{name:t?e:this.name,expression:e})},setName(e){this.$emit(`input`,{name:e,expression:this.expression})}}},OR={class:`st-ifform`},kR=[`disabled`,`value`];function AR(e,t,n,r,i,a){let o=L(`SetExpr`);return B(),V(`div`,OR,[W(o,{value:a.expression,disabled:e.disabled,placeholder:`表达式,如 $singleMode 或 $data.count > 0`,onInput:a.setExpression,onChange:t[0]||=t=>e.$emit(`change`)},null,8,[`value`,`disabled`,`onInput`]),U(`input`,{class:`ni-input`,type:`text`,placeholder:`显示名(留空跟随表达式)`,disabled:e.disabled,value:a.name,onInput:t[1]||=e=>a.setName(e.target.value),onChange:t[2]||=t=>e.$emit(`change`)},null,40,kR)])}var jR=X(DR,[[`render`,AR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetIfForm.vue`]]),MR=[{key:`number`,value:`px`},{key:`percent`,value:`%`},{key:`auto`,value:`@`}],NR={name:`SetNumberStyle`,components:{SetNumber:vI},props:jg,emits:Mg,data(){return{unit:`number`,numValue:``,menuOpen:!1}},computed:{unitList(){return this.options.iTypeList||MR},unitLabel(){let e=this.unitList.filter(e=>e.key===this.unit)[0];return e?e.value:`px`},isAuto(){return this.unit===`auto`},numberOptions(){return{...this.options,type:this.unit===`percent`?`integer`:`float`,placeholder:this.options.placeholder||``,symbol:!0}}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=this.value;/%$/.test(String(e))?(this.unit=`percent`,this.numValue=String(e).replace(/%/g,``)):e===`auto`?(this.unit=`auto`,this.numValue=`auto`):(this.unit=`number`,this.numValue=e===0?`0`:e==null?``:String(e))},onNum(e){this.numValue=e,this.emit()},pickUnit(e){this.menuOpen=!1,this.unit=e,this.numValue=e===`percent`?`100`:e===`auto`?`auto`:``,this.emit(),this.$emit(`change`)},emit(){this.unit===`percent`&&this.numValue?this.$emit(`input`,this.numValue+`%`):this.$emit(`input`,this.numValue)}}},PR={class:`st-numberstyle`},FR={key:1,class:`st-pop st-pop--unit`},IR=[`onMousedown`];function LR(e,t,n,r,i,a){let o=L(`SetNumber`);return B(),V(`div`,PR,[W(o,{value:i.numValue,options:a.numberOptions,disabled:e.disabled||a.isAuto,onInput:a.onNum,onChange:t[1]||=t=>e.$emit(`change`)},{symbol:Lr(()=>[U(`span`,{class:`st-unit`,onMousedown:t[0]||=q(e=>i.menuOpen=!i.menuOpen,[`prevent`])},M(a.unitLabel),33)]),_:1},8,[`value`,`options`,`disabled`,`onInput`]),K(` 单位切换浮层:移到 .st-number 之外,避免被 overflow:hidden 裁切 `),i.menuOpen?(B(),V(`div`,{key:0,class:`st-pop-mask`,onMousedown:t[2]||=q(e=>i.menuOpen=!1,[`prevent`])},null,32)):K(`v-if`,!0),i.menuOpen?(B(),V(`div`,FR,[(B(!0),V(z,null,R(a.unitList,e=>(B(),V(`div`,{key:e.key,class:j([`st-pop__item`,{"st-pop__item--on":e.key===i.unit}]),onMousedown:q(t=>a.pickUnit(e.key),[`prevent`])},M(e.value),43,IR))),128))])):K(`v-if`,!0)])}var RR=X(NR,[[`render`,LR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetNumberStyle.vue`]]),zR={name:`SetPadding`,components:{SetNumber:vI},props:jg,emits:Mg,data(){return{form:{top:``,right:``,bottom:``,left:``}}},computed:{brackets(){return this.options.brackets||[`{`,`}`]},seperator(){return this.options.seperator||`,`}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``);this.brackets.length&&(e=e.replace(RegExp(`[${this.brackets.join(``)}]`,`g`),``));let t=e.split(this.seperator);this.form=this.options.normal?{top:t[0]||``,right:t[1]||``,bottom:t[2]||``,left:t[3]||``}:{top:t[0]||``,left:t[1]||``,bottom:t[2]||``,right:t[3]||``}},opt(e){return{type:`integer`,symbol:e,placeholder:`0`}},set(e,t){this.form[e]=t,this.emitValue()},emitValue(){let e=this.form,t=(this.options.normal?[e.top,e.right,e.bottom,e.left]:[e.top,e.left,e.bottom,e.right]).map(e=>e===``||e===void 0?`0`:e).join(this.seperator),[n,r]=this.brackets.length?this.brackets:[``,``];this.$emit(`input`,`${n||``}${t}${r||``}`)},emitOut(){this.$emit(`change`)}}},BR={class:`st-pad`};function VR(e,t,n,r,i,a){let o=L(`SetNumber`);return B(),V(`div`,BR,[W(o,{value:i.form.top,options:a.opt(`上`),disabled:e.disabled,onInput:t[0]||=e=>a.set(`top`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`]),W(o,{value:i.form.right,options:a.opt(`右`),disabled:e.disabled,onInput:t[1]||=e=>a.set(`right`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`]),W(o,{value:i.form.bottom,options:a.opt(`下`),disabled:e.disabled,onInput:t[2]||=e=>a.set(`bottom`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`]),W(o,{value:i.form.left,options:a.opt(`左`),disabled:e.disabled,onInput:t[3]||=e=>a.set(`left`,e),onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onChange`])])}var HR=X(zR,[[`render`,VR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetPadding.vue`]]),UR=[{key:`TopLeft`,value:`上左`},{key:`TopCenter`,value:`上中`},{key:`TopRight`,value:`上右`},{key:`CenterLeft`,value:`中左`},{key:`Center`,value:`中间`},{key:`CenterRight`,value:`中右`},{key:`BottomLeft`,value:`下左`},{key:`BottomCenter`,value:`下中`},{key:`BottomRight`,value:`下右`}],WR=[{key:`0% 0%`,value:`左上对齐`},{key:`50% 0%`,value:`中上对齐`},{key:`100% 0%`,value:`右上对齐`},{key:`0% 50%`,value:`左中对齐`},{key:`50% 50%`,value:`居中对齐`},{key:`100% 50%`,value:`右中对齐`},{key:`0% 100%`,value:`左下对齐`},{key:`50% 100%`,value:`中下对齐`},{key:`100% 100%`,value:`右下对齐`}],GR={name:`SetGrid9`,props:{...jg,kind:{type:String,default:`PositionStyle`}},emits:Mg,computed:{cells(){return this.kind===`BackgroundPositionStyle`?WR:UR}},methods:{pick(e){this.disabled||(this.$emit(`input`,e.key),this.$emit(`change`))}}},KR={class:`st-grid9`},qR=[`title`,`onClick`];function JR(e,t,n,r,i,a){return B(),V(`div`,KR,[(B(!0),V(z,null,R(a.cells,n=>(B(),V(`div`,{key:n.key,class:j([`st-grid9__cell`,{"st-grid9__cell--on":String(n.key)===String(e.value)}]),title:n.value,onClick:e=>a.pick(n)},[...t[0]||=[U(`span`,{class:`st-grid9__dot`},null,-1)]],10,qR))),128))])}var YR=X(GR,[[`render`,JR],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetGrid9.vue`]]),XR=[{key:`number`,value:`px`},{key:`percent`,value:`%`}],ZR={name:`SetBgPosition`,components:{SetGrid9:YR,SetNumberStyle:RR},props:jg,emits:Mg,data(){return{x:``,y:``}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``).split(/\s+/);this.x=e[0]||``,this.y=e[1]||``},numOptions(e){return{placeholder:e,iTypeList:XR}},pickGrid(e){this.$emit(`input`,e)},setX(e){this.x=e,this.emitValue()},setY(e){this.y=e,this.emitValue()},emitValue(){this.$emit(`input`,`${this.x||`0`} ${this.y||`0`}`)},emitOut(){this.$emit(`change`)}}},QR={class:`st-bgpos`},$R={class:`st-bgpos__xy`};function ez(e,t,n,r,i,a){let o=L(`SetGrid9`),s=L(`SetNumberStyle`);return B(),V(`div`,QR,[W(o,{kind:`BackgroundPositionStyle`,value:e.value,disabled:e.disabled,onInput:a.pickGrid,onChange:t[0]||=t=>e.$emit(`change`)},null,8,[`value`,`disabled`,`onInput`]),U(`div`,$R,[W(s,{value:i.x,options:a.numOptions(`X`),disabled:e.disabled,onInput:a.setX,onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onInput`,`onChange`]),W(s,{value:i.y,options:a.numOptions(`Y`),disabled:e.disabled,onInput:a.setY,onChange:a.emitOut},null,8,[`value`,`options`,`disabled`,`onInput`,`onChange`])])])}var tz=X(ZR,[[`render`,ez],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetBgPosition.vue`]]),nz=[{key:`cover`,desc:`cover:保持纵横比,缩放到完全覆盖背景定位区域的最小尺寸`},{key:`contain`,desc:`contain:保持纵横比,缩放到能放进背景定位区域的最大尺寸`}],rz={name:`SetBgSize`,components:{SetNumberStyle:RR,Dropdown:Sg},computed:{bgOptions(){return[{key:``,value:`自定义`}].concat(this.TYPES.map(e=>({key:e.key,value:e.key})))}},props:jg,emits:Mg,data(){return{TYPES:nz,preset:``,x:``,y:``}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``),t=nz.map(e=>e.key);this.preset=t.includes(e)?e:``;let n=e.split(/\s+/);n.length>=2?(this.x=n[0]||``,this.y=n[1]||``):(this.x=``,this.y=``)},pickPreset(e){this.preset=e,e||(this.x=`auto`,this.y=`auto`),this.emitValue(),this.$emit(`change`)},setX(e){this.x=e,this.emitValue()},setY(e){this.y=e,this.emitValue()},emitValue(){let e=this.preset?this.preset:`${this.x||`auto`} ${this.y||`auto`}`;this.$emit(`input`,e)},emitOut(){this.$emit(`change`)}}},iz={class:`st-bgsize`},az={key:0,class:`st-bgsize__xy`};function oz(e,t,n,r,i,a){let o=L(`Dropdown`),s=L(`SetNumberStyle`);return B(),V(`div`,iz,[W(o,{value:i.preset,options:a.bgOptions,size:`sm`,block:``,disabled:e.disabled,onInput:t[0]||=e=>a.pickPreset(e)},null,8,[`value`,`options`,`disabled`]),i.preset?K(`v-if`,!0):(B(),V(`div`,az,[W(s,{value:i.x,options:{placeholder:`宽`},disabled:e.disabled,onInput:a.setX,onChange:a.emitOut},null,8,[`value`,`disabled`,`onInput`,`onChange`]),W(s,{value:i.y,options:{placeholder:`高`},disabled:e.disabled,onInput:a.setY,onChange:a.emitOut},null,8,[`value`,`disabled`,`onInput`,`onChange`])]))])}var sz=X(rz,[[`render`,oz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetBgSize.vue`]]),cz=[{key:`to bottom`,desc:`从上到下`},{key:`to top`,desc:`从下到上`},{key:`to left`,desc:`从右到左`},{key:`to right`,desc:`从左到右`},{key:`to bottom right`,desc:`从左上到右下`},{key:`to bottom left`,desc:`从右上到左下`},{key:`to top left`,desc:`从右下到左上`},{key:`to top right`,desc:`从左下到右上`}];function lz(e){let t=[],n=0,r=0;for(let i=0;i<e.length;i++){let a=e[i];a===`(`?n++:a===`)`?n--:a===`,`&&n===0&&(t.push(e.slice(r,i).trim()),r=i+1)}return t.push(e.slice(r).trim()),t.filter(e=>e!==``)}var uz={name:`SetGradient`,components:{SetColor:lR,Dropdown:Sg},props:jg,emits:Mg,data(){return{DIRECTIONS:cz,direction:`to bottom`,stops:[]}},computed:{preview(){if(!this.stops.length)return`transparent`;let e=this.stops.map(e=>e.color).filter(Boolean);return e.length<2?e[0]||`transparent`:`linear-gradient(${this.direction}, ${e.join(`, `)})`}},watch:{value:{immediate:!0,handler(){this.parse()}}},methods:{parse(){let e=String(this.value||``).trim().match(/linear-gradient\((.+)\)$/);if(!e){this.direction=this.options.defaultDirection||cz[0].key,this.stops=[];return}let t=lz(e[1]);this.direction=(t[0]||``).toLowerCase()||cz[0].key,this.stops=t.slice(1).map(e=>({color:e}))},setDirection(e){this.direction=e,this.emitValue(),this.$emit(`change`)},setStop(e,t){this.stops[e].color=t,this.emitValue()},addStop(){this.disabled||(this.stops.push({color:`#ffffff`}),this.emitValue(),this.$emit(`change`))},removeStop(e){this.disabled||(this.stops.splice(e,1),this.emitValue(),this.$emit(`change`))},emitValue(){let e=this.stops.map(e=>e.color).filter(e=>e!==``&&e!==void 0);this.$emit(`input`,e.length?`linear-gradient(${this.direction}, ${e.join(`, `)})`:``)},emitOut(){this.$emit(`change`)}}},dz={class:`st-gradient`},fz=[`onClick`],pz=[`disabled`];function mz(e,t,n,r,i,a){let o=L(`Dropdown`),s=L(`SetColor`);return B(),V(`div`,dz,[U(`div`,{class:`st-gradient__preview`,style:A({background:a.preview})},null,4),W(o,{value:i.direction,options:i.DIRECTIONS.map(e=>({key:e.key,value:e.desc})),size:`sm`,block:``,disabled:e.disabled,onInput:t[0]||=e=>a.setDirection(e)},null,8,[`value`,`options`,`disabled`]),(B(!0),V(z,null,R(i.stops,(t,n)=>(B(),V(`div`,{key:`stop`+n,class:`st-gradient__stop`},[W(s,{value:t.color,disabled:e.disabled,onInput:e=>a.setStop(n,e),onChange:a.emitOut},null,8,[`value`,`disabled`,`onInput`,`onChange`]),U(`button`,{class:`st-gradient__del`,type:`button`,title:`删除该渐变色`,onClick:e=>a.removeStop(n)},`✕`,8,fz)]))),128)),U(`button`,{class:`st-minibtn`,type:`button`,disabled:e.disabled,onClick:t[1]||=(...e)=>a.addStop&&a.addStop(...e)},`+ 新增渐变色`,8,pz)])}var hz=X(uz,[[`render`,mz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetGradient.vue`]]),gz=new Set([`width`,`height`,`lineHeight`,`marginRight`,`cursor`,`textAlign`]),_z={name:`SetCustomSelect`,props:jg,emits:[...Mg,`sync`],computed:{list(){return this.options.list||[]}},methods:{normalizeStyle(e){if(!e||typeof e!=`object`)return{};let t={};for(let n in e)gz.has(n)||(t[n]=e[n]);return t},apply(e){if(this.disabled)return;let t=e.sync||{};Object.keys(t).length&&this.$emit(`sync`,t)}}},vz={class:`st-customsel`},yz=[`title`,`onClick`],bz={key:0},xz={key:0,class:`st-list__empty`};function Sz(e,t,n,r,i,a){return B(),V(`div`,vz,[(B(!0),V(z,null,R(a.list,(e,t)=>(B(),V(`div`,{key:t,class:`st-customsel__item`,style:A(a.normalizeStyle(e.style)),title:`应用:`+Object.keys(e.sync||{}).join(`、`),onClick:t=>a.apply(e)},[(B(!0),V(z,null,R(e.list||[],(e,t)=>(B(),V(`span`,{key:t,style:A(a.normalizeStyle(e.style))},M(e.innerText),5))),128)),(e.list||[]).length?K(`v-if`,!0):(B(),V(`span`,bz,M(e.innerText||`样式`+(t+1)),1))],12,yz))),128)),a.list.length?K(`v-if`,!0):(B(),V(`p`,xz,`未配置常用样式`))])}var Cz=X(_z,[[`render`,Sz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetCustomSelect.vue`]]),wz={name:`SetList`,props:jg,emits:Mg,computed:{list(){let e=this.itemInfo;return e&&e.itemList||[]},addText(){return this.options&&this.options.btnText||`添加项`}},methods:{displayName(e){let t=e.itemName||e.itemKey||``;return{fontStyle:`字体风格`,textDecoration:`文字装饰`}[e.itemKey]||t},add(){if(this.disabled)return;let e=this.itemInfo,t=this.list[0],n;n=t?new du(t.properties.map(e=>({itemId:e.itemId,itemKey:e.itemKey,itemName:e.itemName,itemType:e.itemType,itemOption:e.itemOption,itemParam:e.itemParam,itemDefaultValue:e.itemDefaultValue,itemDesc:e.itemDesc,itemTypeRange:e.itemTypeRange,itemValueFrom:`0`,itemValue:``})),{}):new du((this.options&&this.options.iFieldList||[]).map(e=>({itemId:e.key,itemKey:e.key,itemName:e.value||e.key,itemType:`Input`,itemValueFrom:`0`,itemValue:``})),{}),e.itemList.push(n),this.$emit(`change`)},remove(e){this.disabled||(this.itemInfo.removeAt(e),this.$emit(`change`))},move(e,t){this.disabled||(this.itemInfo.moveItem(e,e+t),this.$emit(`change`))}}},Tz={class:`st-list`},Ez={class:`st-list__head`},Dz={class:`st-list__idx`},Oz=[`disabled`,`onClick`],kz=[`disabled`,`onClick`],Az=[`disabled`,`onClick`],jz={class:`st-list__body`},Mz=[`title`],Nz={class:`st-list__control`},Pz={key:0,class:`st-list__empty`},Fz={key:0,class:`st-list__empty`},Iz=[`disabled`];function Lz(e,t,n,r,i,a){let o=L(`prop-control`);return B(),V(`div`,Tz,[(B(!0),V(z,null,R(a.list,(n,r)=>(B(),V(`div`,{key:n.id,class:`st-list__item`},[U(`div`,Ez,[U(`span`,Dz,`#`+M(r+1),1),t[4]||=U(`span`,{class:`st-list__head-spacer`},null,-1),U(`button`,{class:`st-list__op`,type:`button`,title:`上移`,disabled:e.disabled||r===0,onClick:e=>a.move(r,-1)},`↑`,8,Oz),U(`button`,{class:`st-list__op`,type:`button`,title:`下移`,disabled:e.disabled||r===a.list.length-1,onClick:e=>a.move(r,1)},`↓`,8,kz),U(`button`,{class:`st-list__op st-list__op--del`,type:`button`,title:`删除`,disabled:e.disabled,onClick:e=>a.remove(r)},[...t[3]||=[U(`svg`,{viewBox:`0 0 16 16`,class:`st-ic`,"aria-hidden":`true`},[U(`use`,{href:`#icon-delete`})],-1)]],8,Az)]),U(`div`,jz,[(B(!0),V(z,null,R(n.properties,n=>I((B(),V(`div`,{key:n.itemId,class:`st-list__row`},[U(`label`,{class:`st-list__label`,title:n.itemDesc||a.displayName(n)},M(a.displayName(n)),9,Mz),U(`div`,Nz,[W(o,{property:n,disabled:e.disabled,onChange:t[0]||=t=>e.$emit(`change`),onSync:t[1]||=t=>e.$emit(`sync`,t)},null,8,[`property`,`disabled`])])])),[[Sc,n.itemVisible]])),128)),n.properties.length?K(`v-if`,!0):(B(),V(`p`,Pz,`该项无字段`))])]))),128)),a.list.length?K(`v-if`,!0):(B(),V(`p`,Fz,`暂无项`)),U(`button`,{class:`st-minibtn st-list__add`,type:`button`,disabled:e.disabled,onClick:t[2]||=(...e)=>a.add&&a.add(...e)},M(a.addText),9,Iz)])}var Rz=X(wz,[[`render`,Lz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetList.vue`]]),zz={name:`SetImage`,props:jg,emits:Mg,methods:{clear(){this.disabled||(this.$emit(`input`,``),this.$emit(`change`))}}},Bz={class:`st-image`},Vz={class:`st-image__row`},Hz=[`disabled`,`value`],Uz=[`disabled`];function Wz(e,t,n,r,i,a){return B(),V(`div`,Bz,[U(`div`,Vz,[U(`input`,{class:`ni-input`,type:`text`,disabled:e.disabled,value:e.value||``,placeholder:`图片路径,如 @filestore/...png 或 https://...`,onInput:t[0]||=t=>e.$emit(`input`,t.target.value),onChange:t[1]||=t=>e.$emit(`change`)},null,40,Hz),e.value?(B(),V(`button`,{key:0,class:`st-image__clear`,type:`button`,title:`清空`,disabled:e.disabled,onClick:t[2]||=(...e)=>a.clear&&a.clear(...e)},[...t[3]||=[U(`svg`,{viewBox:`0 0 16 16`,class:`st-ic`,"aria-hidden":`true`},[U(`use`,{href:`#icon-reset`})],-1)]],8,Uz)):K(`v-if`,!0)])])}var Gz=X(zz,[[`render`,Wz],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetImage.vue`]]),Kz={name:`SetCode`,props:jg,emits:Mg,data(){return{code:``,bridge:null}},computed:{codeKey(){return this.options.codeKey||`code`},lines(){return this.code?this.code.split(`
|
|
307
|
+
`).length:0},chars(){return this.code.length}},mounted(){this.code=this.readCode(),this.$nextTick(()=>this.initJar())},beforeUnmount(){this._t&&clearTimeout(this._t),this.teardownBridge(!0),this._jar&&this._jar.destroy&&this._jar.destroy()},methods:{readCode(){let e=this.value;return e==null?``:typeof e==`string`?e:String(typeof e==`object`?e[this.codeKey]||``:e)},initJar(){let e=this.$refs.editor;if(!e)return;let t=e=>{e.innerHTML=Yg.default.highlight(e.textContent,Yg.default.languages.javascript,`javascript`)};this._jar=Jg(e,t,{tab:` `,indentOn:/[({[]$/,addClosing:!0,history:!0}),this._jar.updateCode(this.code),this._jar.onUpdate(e=>this.onCode(e))},onCode(e){if(this.disabled||this.bridge)return;this.code=e;let t=this.value&&typeof this.value==`object`?Object.assign({},this.value):{};t[this.codeKey]=e,this.$emit(`input`,t),this._t&&clearTimeout(this._t),this._t=setTimeout(()=>this.$emit(`change`),400)},toggleBridge(){this.bridge?this.teardownBridge(!0):this.setupBridge()},async setupBridge(){if(this.disabled||this.bridge)return;let e=this.itemInfo&&this.itemInfo.itemKey?String(this.itemInfo.itemKey):``;try{let t=await Gl(this.code,e);this.bridge={id:t.id,file:t.file}}catch(e){console.error(`[VSCode 桥接建立失败]`,e);return}this.setEditorEditable(!1),this._hb=setInterval(()=>{this.bridge&&ql(this.bridge.id).catch(()=>{})},5e3),this._bridgeUnsub=Hl(e=>{if(!(!this.bridge||!e||e.id!==this.bridge.id)){if(e.reason)return this.teardownBridge(!1);this.pullBridgeCode()}})},async pullBridgeCode(){if(!this.bridge)return;let e;try{e=await Kl(this.bridge.id)}catch{return}let t=String(e.code==null?``:e.code);t!==this.code&&this.applyExternalCode(t)},applyExternalCode(e){this.code=e,this._jar&&this._jar.updateCode(e,!1);let t=this.value&&typeof this.value==`object`?Object.assign({},this.value):{};t[this.codeKey]=e,this.$emit(`input`,t),this._t&&clearTimeout(this._t),this._t=setTimeout(()=>this.$emit(`change`),400)},teardownBridge(e){let t=this.bridge;this.bridge=null,this._hb&&=(clearInterval(this._hb),null),this._bridgeUnsub&&=(this._bridgeUnsub(),null),this.setEditorEditable(!0),t&&e&&Jl(t.id).catch(()=>{})},setEditorEditable(e){let t=this.$refs.editor;t&&t.setAttribute(`contenteditable`,e?`true`:`false`)}}},qz={class:`st-code`},Jz={class:`st-code__foot`},Yz={class:`st-code__hint`},Xz={class:`st-code__foot-actions`},Zz=[`title`],Qz=[`title`,`disabled`],$z={key:0,class:`st-code__vscode-label`};function eB(e,t,n,r,i,a){return B(),V(`div`,qz,[U(`div`,{ref:`editor`,class:j([`st-code__editor`,{"is-disabled":e.disabled,"is-bridged":!!i.bridge}])},null,2),K(` 右上角语言标签:弱化的只读标识,不参与交互 `),t[2]||=U(`span`,{class:`st-code__lang`,"aria-hidden":`true`},`JS`,-1),U(`div`,Jz,[U(`span`,Yz,M(a.lines)+` 行 · `+M(a.chars)+` 字符`,1),K(` VSCode 代码桥:生成临时 js 用外部编辑器编辑,保存实时回写;断开即删临时文件 `),U(`span`,Xz,[i.bridge?(B(),V(`span`,{key:0,class:`st-code__bridge-tag`,title:i.bridge.file},`VSCode 同步中`,8,Zz)):K(`v-if`,!0),U(`button`,{type:`button`,class:j([`st-code__vscode`,{"is-on":!!i.bridge}]),title:i.bridge?`断开 VSCode 桥接并删除临时文件`:`在 VSCode 中编辑:保存实时同步回编辑区,断开后清除临时文件`,disabled:e.disabled,onClick:t[0]||=(...e)=>a.toggleBridge&&a.toggleBridge(...e)},[K(` 图标左侧小字:未桥接时是动作说明;桥接后由状态徽标接替,避免两段文字挤一行 `),i.bridge?K(`v-if`,!0):(B(),V(`span`,$z,`在编辑器中打开`)),t[1]||=U(`svg`,{viewBox:`0 0 24 24`,width:`14`,height:`14`,"aria-hidden":`true`},[U(`path`,{fill:`currentColor`,d:`M23.15 2.587 18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z`})],-1)],10,Qz)])])])}var tB=X(Kz,[[`render`,eB],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/setters/SetCode.vue`]]),nB={0:`常量`,1:`变量`,2:`图片`},rB={const:`0`,var:`1`,image:`2`};function iB(e){switch(e){case`InputNumber`:return{comp:vI};case`Color`:return{comp:lR};case`Select`:return{comp:xI};case`TabSelect`:return{comp:Kg,kind:`TabSelect`};case`Input`:return{comp:sI};case`Textarea`:return{comp:sI,multiline:!0};case`Switcher`:return{comp:TI};case`BooleanForm`:return{comp:TI,boolean:!0};case`PaddingStyle`:return{comp:HR};case`NumberStyle`:return{comp:RR};case`PositionStyle`:return{comp:YR,kind:`PositionStyle`};case`BackgroundPositionStyle`:return{comp:tz};case`BackgroundSizeStyle`:return{comp:sz};case`GradientStyle`:return{comp:hz};case`FontStyle`:return{comp:Kg,kind:`FontStyle`};case`TextDecorationStyle`:return{comp:Kg,kind:`TextDecorationStyle`};case`JustifyContentStyle`:return{comp:Kg,kind:`JustifyContentStyle`};case`AlignItemsStyle`:return{comp:Kg,kind:`AlignItemsStyle`};case`IconSelect`:return{comp:bR};case`CustomSelect`:return{comp:Cz};case`List`:return{comp:Rz};case`IfForm`:return{comp:jR};case`Code`:return{comp:tB};default:return{comp:sI}}}var aB={name:`PropControl`,components:{SetText:sI,SetNumber:vI,SetSelect:xI,SetSegment:Kg,SetSwitch:TI,SetColor:lR,SetIconSelect:bR,SetIfForm:jR,SetNumberStyle:RR,SetPadding:HR,SetGrid9:YR,SetBgPosition:tz,SetBgSize:sz,SetGradient:hz,SetCustomSelect:Cz,SetList:Rz,SetImage:Gz,SetCode:tB,SetExpr:ER},props:{property:{type:Object,required:!0},watches:{type:Object,default:()=>({})},disabled:{type:Boolean,default:!1},bExchange:{type:Boolean,default:!0}},emits:[`change`,`sync`],computed:{itemType(){return this.property&&this.property.itemType||``},sources(){let e=this.property&&this.property.itemTypeRange||`const`,t=String(e).split(`,`).map(e=>e.trim()).filter(Boolean).map(e=>({key:rB[e],label:nB[rB[e]]})).filter(e=>e.key),n=String(this.property.itemValueFrom);return/^[012]$/.test(n)&&!t.some(e=>e.key===n)&&(t=t.concat([{key:n,label:nB[n]||`来源`+n}])),t},setterComp(){return iB(this.itemType)}},methods:{onInput(e){this.property.itemValue=e,this.$emit(`change`)},onChange(){this.$emit(`change`)},onSync(e){this.$emit(`sync`,e)},setSource(e){if(this.disabled)return;let t=this.property,n=String(e);t.itemValueFrom!==n&&(t._valuesByFrom||={0:void 0,1:void 0,2:void 0},t._valuesByFrom[t.itemValueFrom]=t.itemValue,t.itemValueFrom=n,t._valuesByFrom[n]===void 0?n===`0`?(t.itemValue=t.itemDefaultValue??this.defaultFor(),t._valuesByFrom[n]=t.itemValue):(t.itemValue=``,t._valuesByFrom[n]=``):t.itemValue=t._valuesByFrom[n],this.$emit(`change`))},defaultFor(){switch(this.itemType){case`Color`:return`#000000`;case`InputNumber`:return 0;case`Switcher`:return`0`;case`BooleanForm`:return!1;case`TabSelect`:case`Select`:{let e=this.property.itemOption||{},t=e.iParamList||e.iTypeList||[];return t.length?t[0].key:``}default:return``}}}},oB={key:0,class:`pc-srcs`},sB=[`disabled`,`onClick`],cB={class:`pc-body`};function lB(e,t,n,r,i,a){let o=L(`SetImage`),s=L(`SetExpr`);return B(),V(`div`,{class:j([`pc`,{"pc--readonly":n.disabled}])},[K(` 值来源切换(仅当 meta 声明了多于一种来源 且 允许切换时显示) `),a.sources.length>1&&n.bExchange?(B(),V(`div`,oB,[(B(!0),V(z,null,R(a.sources,e=>(B(),V(`button`,{key:e.key,type:`button`,class:j([`pc-src`,{"is-active":n.property.itemValueFrom===e.key}]),disabled:n.disabled,onClick:t=>a.setSource(e.key)},M(e.label),11,sB))),128))])):K(`v-if`,!0),U(`div`,cB,[K(` 图片素材来源 `),n.property.itemValueFrom===`2`?(B(),H(o,{key:0,value:n.property.itemValue,options:n.property.itemOption,"item-info":n.property,disabled:n.disabled,onInput:a.onInput,onChange:a.onChange},null,8,[`value`,`options`,`item-info`,`disabled`,`onInput`,`onChange`])):n.property.itemValueFrom===`1`?(B(),V(z,{key:1},[K(` 变量 / 表达式来源:带语法高亮、可拖拽调高度 `),W(s,{value:n.property.itemValue,disabled:n.disabled,"item-info":n.property,onInput:a.onInput,onChange:a.onChange},null,8,[`value`,`disabled`,`item-info`,`onInput`,`onChange`])],2112)):(B(),V(z,{key:2},[K(` 常量来源:按 itemType 分派 `),(B(),H(Yi(a.setterComp.comp),{value:n.property.itemValue,options:n.property.itemOption,watches:n.watches,"item-info":n.property,disabled:n.disabled,kind:a.setterComp.kind,multiline:a.setterComp.multiline,boolean:a.setterComp.boolean,onInput:a.onInput,onChange:a.onChange,onSync:a.onSync},null,40,[`value`,`options`,`watches`,`item-info`,`disabled`,`kind`,`multiline`,`boolean`,`onInput`,`onChange`,`onSync`]))],2112))])],2)}var uB=X(aB,[[`render`,lB],[`__scopeId`,`data-v-910daa70`],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/PropControl.vue`]]),dB={name:`PropTree`,props:{properties:{type:Array,default:()=>[]},mode:{type:String,default:`property`},depth:{type:Number,default:1},chain:{type:Array,default:()=>[]},watches:{type:Object,default:()=>({})},disabled:{type:Boolean,default:!1},bExchange:{type:Boolean,default:!0},plain:{type:Boolean,default:!1}},emits:[`leaf-change`,`leaf-sync`],data(){return{openMap:{}}},methods:{isGroup(e){if(!e)return!1;if(e.itemType===`group`)return!0;let t=e.itemChildren&&e.itemChildren.properties;return!!(t&&t.length)},childCount(e){let t=e.itemChildren&&e.itemChildren.properties;return t?t.length:0},isBlock(e){return e&&e.itemType===`Code`},groupVisible(e){if(e.itemVisible===!1)return!1;let t=e.itemChildren&&e.itemChildren.properties;return!t||!t.length||t.some(e=>e.itemVisible===!1?!1:!this.isGroup(e)||this.groupVisible(e))},isOpen(e){return this.openMap[e.itemId]!==!1},toggle(e){this.openMap[e.itemId]=this.openMap[e.itemId]===!1,this.openMap=Object.assign({},this.openMap)},onLeaf(e){this.$emit(`leaf-change`,this.chain.concat(e))},onSync(e){this.$emit(`leaf-sync`,e)}}},fB={key:0,class:`ptree__group`},pB=[`onClick`],mB={class:`ptree__group-name`},hB={class:`ptree__group-body`},gB=[`title`],_B={class:`ptree__control`};function vB(e,t,n,r,i,a){let o=L(`prop-tree`,!0),s=L(`prop-control`);return B(),V(`div`,{class:j([`ptree`,{"ptree--plain":n.plain}])},[(B(!0),V(z,null,R(n.properties,r=>(B(),V(z,{key:r.itemId},[K(` 分组(自身可见 且 存在可见后代才渲染,避免空分组) `),a.isGroup(r)&&a.groupVisible(r)?(B(),V(`div`,fB,[U(`div`,{class:`ptree__group-head`,type:`button`,onClick:e=>a.toggle(r)},[U(`span`,{class:j([`ptree__caret`,{"is-open":a.isOpen(r)}])},`▸`,2),U(`span`,mB,M(r.itemName||r.itemKey),1)],8,pB),I(U(`div`,hB,[r.itemChildren&&r.itemChildren.properties.length?(B(),H(o,{key:0,properties:r.itemChildren.properties,mode:n.mode,depth:n.depth+1,chain:n.chain.concat(r),watches:n.watches,disabled:n.disabled,"b-exchange":n.bExchange,plain:n.plain,onLeafChange:t[0]||=t=>e.$emit(`leaf-change`,t),onLeafSync:t[1]||=t=>e.$emit(`leaf-sync`,t)},null,8,[`properties`,`mode`,`depth`,`chain`,`watches`,`disabled`,`b-exchange`,`plain`])):K(`v-if`,!0)],512),[[Sc,a.isOpen(r)]])])):r.itemVisible===!1?K(`v-if`,!0):(B(),V(z,{key:1},[K(` 叶子(itemCondition 判定为不可见时不渲染,与线上编辑器一致) `),U(`div`,{class:j([`ptree__row`,{"ptree__row--disabled":n.disabled,"ptree__row--block":a.isBlock(r)}])},[U(`label`,{class:`ptree__label`,title:r.itemDesc||r.itemName||r.itemKey},M(r.itemName||r.itemKey||r.itemType||`字段`),9,gB),U(`div`,_B,[W(s,{property:r,watches:n.watches,disabled:n.disabled,"b-exchange":n.bExchange,onChange:e=>a.onLeaf(r),onSync:a.onSync},null,8,[`property`,`watches`,`disabled`,`b-exchange`,`onChange`,`onSync`])])],2)],2112))],64))),128))],2)}var yB=X(dB,[[`render`,vB],[`__file`,`/Users/owlaford/Workspace/dsl-card/card-editor/components/PropTree.vue`]]),bB=Sl(nI);bB.component(`prop-control`,uB),bB.component(`prop-tree`,yB),bB.component(`Dropdown`,Sg),bB.config.errorHandler=(e,t,n)=>{console.error(`[render error]`,n,e),window.__cardDebug&&window.__cardDebug.pushError(`render`,`${n}: ${e.message}`)},bB.mount(`#app`);
|