手动颜色
* 2. 外层元素 data-p1000-theme-color
* 3. 外层元素的常见 CSS 主色变量
* 4. 外层元素背景色、渐变色
* 5. 全部找不到时保留粉色后备方案
*/
var THEME_VARIABLES = [
"--p1000-theme-color",
"--p1000-accent",
"--p1000-dark",
"--p1000-deep",
"--p1000-green",
"--emerald-main",
"--emerald-dark",
"--accent-color",
"--primary-color",
"--theme-color"
];
function clamp(value, min, max) {
return Math.min(max, Math.max(min, value));
}
function parseHex(value) {
var hex = value.replace("#", "").trim();
if (hex.length === 3 || hex.length === 4) {
hex = hex.split("").map(function (char) {
return char + char;
}).join("");
}
if (hex.length !== 6 && hex.length !== 8) {
return null;
}
var number = parseInt(hex.slice(0, 6), 16);
if (Number.isNaN(number)) {
return null;
}
return {
r: (number >> 16) & 255,
g: (number >> 8) & 255,
b: number & 255,
a: hex.length === 8
? parseInt(hex.slice(6, 8), 16) / 255
: 1
};
}
function parseRgb(value) {
var match = value.match(
/rgba?\(\s*([\d.]+)(%)?\s*[, ]\s*([\d.]+)(%)?\s*[, ]\s*([\d.]+)(%)?(?:\s*[,/]\s*([\d.]+)(%)?)?\s*\)/i
);
if (!match) {
return null;
}
return {
r: clamp(
parseFloat(match[1]) * (match[2] ? 2.55 : 1),
0,
255
),
g: clamp(
parseFloat(match[3]) * (match[4] ? 2.55 : 1),
0,
255
),
b: clamp(
parseFloat(match[5]) * (match[6] ? 2.55 : 1),
0,
255
),
a: match[7]
? clamp(
parseFloat(match[7]) *
(match[8] ? 0.01 : 1),
0,
1
)
: 1
};
}
function hslToRgb(h, s, l, a) {
h = ((h % 360) + 360) % 360;
s = clamp(s, 0, 1);
l = clamp(l, 0, 1);
var c = (1 - Math.abs(2 * l - 1)) * s;
var x = c * (1 - Math.abs((h / 60) % 2 - 1));
var m = l - c / 2;
var rp = 0;
var gp = 0;
var bp = 0;
if (h < 60) {
rp = c;
gp = x;
} else if (h < 120) {
rp = x;
gp = c;
} else if (h < 180) {
gp = c;
bp = x;
} else if (h < 240) {
gp = x;
bp = c;
} else if (h < 300) {
rp = x;
bp = c;
} else {
rp = c;
bp = x;
}
return {
r: Math.round((rp + m) * 255),
g: Math.round((gp + m) * 255),
b: Math.round((bp + m) * 255),
a: typeof a === "number" ? a : 1
};
}
function parseHsl(value) {
var match = value.match(
/hsla?\(\s*([-\d.]+)(?:deg)?\s*[, ]\s*([\d.]+)%\s*[, ]\s*([\d.]+)%(?:\s*[,/]\s*([\d.]+)(%)?)?\s*\)/i
);
if (!match) {
return null;
}
var alpha = 1;
if (match[4]) {
alpha = parseFloat(match[4]);
if (match[5]) {
alpha = alpha / 100;
}
}
return hslToRgb(
parseFloat(match[1]),
parseFloat(match[2]) / 100,
parseFloat(match[3]) / 100,
clamp(alpha, 0, 1)
);
}
function parseColor(value) {
if (!value || typeof value !== "string") {
return null;
}
var color = value.trim();
if (!color || color === "transparent") {
return null;
}
if (color.charAt(0) === "#") {
return parseHex(color);
}
if (/^rgba?\(/i.test(color)) {
return parseRgb(color);
}
if (/^hsla?\(/i.test(color)) {
return parseHsl(color);
}
/*
* 处理 green、rebeccapurple 等颜色名称。
*/
var probe = document.createElement("span");
probe.style.color = "";
probe.style.color = color;
if (!probe.style.color) {
return null;
}
probe.style.position = "absolute";
probe.style.visibility = "hidden";
document.body.appendChild(probe);
var computed = window.getComputedStyle(probe).color;
probe.remove();
return parseRgb(computed);
}
function rgbToHsl(rgb) {
var r = rgb.r / 255;
var g = rgb.g / 255;
var b = rgb.b / 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var delta = max - min;
var h = 0;
var s = 0;
var l = (max + min) / 2;
if (delta !== 0) {
s = delta / (1 - Math.abs(2 * l - 1));
if (max === r) {
h = 60 * (((g - b) / delta) % 6);
} else if (max === g) {
h = 60 * (((b - r) / delta) + 2);
} else {
h = 60 * (((r - g) / delta) + 4);
}
}
if (h < 0) {
h += 360;
}
return {
h: h,
s: s,
l: l
};
}
function extractColors(text) {
if (!text || text === "none") {
return [];
}
var matches = text.match(
/#[0-9a-f]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/gi
);
if (!matches) {
return [];
}
return matches.map(parseColor).filter(Boolean);
}
function scoreColor(rgb, sourceBoost, depth) {
if (!rgb || rgb.a < 0.08) {
return -Infinity;
}
var hsl = rgbToHsl(rgb);
if (hsl.l > 0.965 || hsl.l < 0.035) {
return -Infinity;
}
/*
* 优先选择有色相、不是纯白/纯灰的中深色。
*/
return (
hsl.s * 118 -
Math.abs(hsl.l - 0.42) * 34 +
sourceBoost -
depth * 1.4
);
}
function findThemeColor(card) {
var candidates = [];
function addCandidate(value, boost, depth) {
var rgb = parseColor(value);
if (!rgb) {
return;
}
candidates.push({
rgb: rgb,
score: scoreColor(rgb, boost, depth)
});
}
var manual = card.getAttribute(
"data-p1000-theme-color"
);
if (manual) {
addCandidate(manual, 120, 0);
}
var node = card.parentElement;
var depth = 0;
while (node && node !== document.documentElement && depth < 14) {
var dataColor =
node.getAttribute("data-p1000-theme-color") ||
node.getAttribute("data-theme-color");
if (dataColor) {
addCandidate(dataColor, 98, depth);
}
var style = window.getComputedStyle(node);
THEME_VARIABLES.forEach(function (variableName, index) {
var value = style
.getPropertyValue(variableName)
.trim();
if (value) {
addCandidate(
value,
84 - index * 1.5,
depth
);
}
});
extractColors(style.backgroundImage).forEach(
function (rgb) {
candidates.push({
rgb: rgb,
score: scoreColor(rgb, 34, depth)
});
}
);
addCandidate(
style.backgroundColor,
28,
depth
);
addCandidate(
style.borderTopColor,
13,
depth
);
node = node.parentElement;
depth += 1;
}
candidates = candidates.filter(function (candidate) {
return Number.isFinite(candidate.score);
});
candidates.sort(function (a, b) {
return b.score - a.score;
});
return candidates.length ? candidates[0].rgb : null;
}
function hslString(h, s, l, alpha) {
var hue = Math.round(((h % 360) + 360) % 360);
var sat = Math.round(clamp(s, 0, 1) * 100);
var light = Math.round(clamp(l, 0, 1) * 100);
if (typeof alpha === "number") {
return "hsla(" +
hue + ", " +
sat + "%, " +
light + "%, " +
clamp(alpha, 0, 1) +
")";
}
return "hsl(" +
hue + ", " +
sat + "%, " +
light + "%)";
}
function applyTheme(card) {
if (!card || card.dataset.p1000ThemeReady === "true") {
return;
}
var rgb = findThemeColor(card);
if (!rgb) {
card.dataset.p1000ThemeReady = "fallback";
return;
}
var hsl = rgbToHsl(rgb);
var hue = hsl.h;
var saturation = clamp(
Math.max(hsl.s, 0.38),
0.38,
0.72
);
card.style.setProperty(
"--sc8-accent",
hslString(hue, saturation, 0.47)
);
card.style.setProperty(
"--sc8-accent-strong",
hslString(hue, saturation, 0.36)
);
card.style.setProperty(
"--sc8-accent-dark",
hslString(hue, saturation * 0.78, 0.24)
);
card.style.setProperty(
"--sc8-soft",
hslString(hue, saturation * 0.34, 0.955)
);
card.style.setProperty(
"--sc8-soft-2",
hslString(hue, saturation * 0.43, 0.885)
);
card.style.setProperty(
"--sc8-surface",
hslString(hue, saturation * 0.18, 0.992)
);
card.style.setProperty(
"--sc8-surface-2",
hslString(hue, saturation * 0.27, 0.965)
);
card.style.setProperty(
"--sc8-border",
hslString(hue, saturation * 0.72, 0.5, 0.32)
);
card.style.setProperty(
"--sc8-border-strong",
hslString(hue, saturation * 0.82, 0.41, 0.56)
);
card.style.setProperty(
"--sc8-text",
hslString(hue, saturation * 0.32, 0.27)
);
card.style.setProperty(
"--sc8-muted",
hslString(hue, saturation * 0.26, 0.44)
);
card.style.setProperty(
"--sc8-glow",
hslString(hue, saturation, 0.42, 0.17)
);
card.dataset.p1000ThemeReady = "true";
}
function scanCards(root) {
var scope = root || document;
if (
scope.nodeType === 1 &&
scope.matches &&
scope.matches(".p1000-sc8-card")
) {
applyTheme(scope);
}
if (!scope.querySelectorAll) {
return;
}
scope.querySelectorAll(".p1000-sc8-card").forEach(
applyTheme
);
}
/* =================================================
* V9:个人卡片 → 页面 AI 聊天气泡
*
* 当前 AI 聊天框已经公开:
* - window.toggleChat()
* - window.handlePrinceChange(false)
* - #princeSelector 隐藏选择值
*
* 因此这里不复制 AI 逻辑,只把卡片作者 ID
* 交给现有聊天框,避免两套人物状态互相冲突。
* ================================================= */
function flashChatButtonError(button) {
if (!button) {
return;
}
button.classList.remove("is-opening");
button.classList.add("is-chat-unavailable");
button.setAttribute("aria-busy", "false");
window.setTimeout(function () {
button.classList.remove("is-chat-unavailable");
}, 1200);
}
function finishChatButton(button) {
if (!button) {
return;
}
button.classList.remove("is-opening");
button.classList.remove("is-chat-unavailable");
button.setAttribute("aria-busy", "false");
}
function openAuthorPrinceChat(button) {
if (!button) {
return;
}
var authorId = String(
button.getAttribute("data-prince-user-id") || ""
).replace(/\D+/g, "");
if (!authorId || authorId === "0") {
flashChatButtonError(button);
return;
}
button.classList.add("is-opening");
button.setAttribute("aria-busy", "true");
var attempt = 0;
var maxAttempts = 36;
function connectToChat() {
attempt += 1;
var selector = document.getElementById(
"princeSelector"
);
var chatBox = document.getElementById(
"chat-box-wrapper"
);
var chatReady =
selector &&
chatBox &&
typeof window.handlePrinceChange === "function";
/*
* 聊天框通常位于 wp_footer,极早点击时可能
* 比卡片脚本晚几毫秒初始化,因此短暂等待重试。
*/
if (!chatReady) {
if (attempt < maxAttempts) {
window.setTimeout(connectToChat, 90);
} else {
flashChatButtonError(button);
}
return;
}
/* 先把随机状态改为本卡片 author 的用户 ID。 */
selector.value = authorId;
/*
* 只在聊天框关闭时调用 toggleChat,避免已经
* 展开的聊天框被再次点击后反而收起。
*/
var isClosed =
window.getComputedStyle(chatBox).display === "none";
if (
isClosed &&
typeof window.toggleChat === "function"
) {
window.toggleChat();
}
window.requestAnimationFrame(function () {
/*
* 这会同步更新顶部王子选择器,并新增一条
* “我已经准备好倾听了,我是凌天”式问候语。
*/
window.handlePrinceChange(false);
if (
typeof window.ccPositionWidgetChatBox ===
"function"
) {
window.ccPositionWidgetChatBox();
}
var input = document.getElementById("input");
if (input && typeof input.focus === "function") {
window.setTimeout(function () {
input.focus({ preventScroll: true });
}, 120);
}
finishChatButton(button);
});
}
connectToChat();
}
function bindPrinceChatButtons() {
if (document.documentElement.dataset.p1000Sc8ChatBound === "1") {
return;
}
document.documentElement.dataset.p1000Sc8ChatBound = "1";
document.addEventListener("click", function (event) {
var target = event.target;
if (!(target instanceof Element)) {
return;
}
var button = target.closest(
".p1000-sc8-chat-button"
);
if (!button) {
return;
}
event.preventDefault();
event.stopPropagation();
openAuthorPrinceChat(button);
});
}
function start() {
scanCards(document);
bindPrinceChatButtons();
/*
* 兼容无限滚动、AJAX载入贴文。
*/
if ("MutationObserver" in window && document.body) {
var observer = new MutationObserver(
function (mutations) {
mutations.forEach(function (mutation) {
mutation.addedNodes.forEach(
function (node) {
if (node.nodeType === 1) {
scanCards(node);
}
}
);
});
}
);
observer.observe(document.body, {
childList: true,
subtree: true
});
}
}
if (document.readyState === "loading") {
document.addEventListener(
"DOMContentLoaded",
start,
{ once: true }
);
} else {
start();
}
})();
房间号
0010
他经营珍珠养殖场,他说"遇到你就像发现了这世界上最珍贵、最透亮的珍珠。他只想把你放在他坚硬的珍珠蚌壳里好好保护你!”