diff --git a/component/preview-image/preview.js b/component/preview-image/preview.js new file mode 100644 index 0000000..60aed55 --- /dev/null +++ b/component/preview-image/preview.js @@ -0,0 +1,99 @@ +class PreviewImage extends HTMLElement { + static get observedAttributes() { return ["src", "alt"]; } + constructor(){ + super(); + this._src = this.getAttribute("src") || ""; + this._alt = this.getAttribute("alt") || ""; + this.attachShadow({ mode: "open" }); + const root = document.createElement("div"); + root.className = "root"; + const img = document.createElement("img"); + root.appendChild(img); + this.shadowRoot.append(style, root); + this._img = img; + this._render(); + this._img.addEventListener("click", (e)=>{ e.stopPropagation(); this.init(this._src); }); + // 保存一个全局实例(与 bi.js 风格一致,便于外部静态调用) + window.previewImageComponent = this; + } + attributeChangedCallback(name, oldVal, newVal){ + if(name === "src") this._src = newVal || ""; + if(name === "alt") this._alt = newVal || ""; + this._render(); + } + _render(){ + if(this._img){ this._img.src = this._src; this._img.alt = this._alt; } + } + init(src){ PreviewImage.open(src || this._src); } + static open(src){ + if(!src) return; + const mask = document.createElement("div"); + const box = document.createElement("div"); + const img = document.createElement("img"); + + mask.style.width = "100%"; + mask.style.height = "100%"; + mask.style.maxWidth = "none"; + mask.style.maxHeight = "none"; + mask.style.border = "none"; + mask.style.position = "fixed"; + mask.style.top = "0"; + mask.style.left = "0"; + mask.style.backgroundColor = "rgba(255, 255, 255, 0.8)"; + mask.style.zIndex = "10002"; + mask.style.display = "flex"; + mask.style.alignItems = "center"; + mask.style.justifyContent = "center"; + + // box.className = "detail-image flexcenter"; + box.style.width = "80vw"; + box.style.height = "80vh"; + box.style.borderRadius = "8px"; + box.style.backgroundColor = "rgba(17, 17, 17, 0.9)"; + box.style.overflow = "hidden"; + box.style.display = "flex"; + box.style.alignItems = "center"; + box.style.justifyContent = "center"; + box.style.position = "relative"; + + // img.className = "detail-img"; + img.style.maxWidth = "100%"; + img.style.maxHeight = "100%"; + img.src = src; + box.appendChild(img); + mask.appendChild(box); + let scale = 1, tx = 0, ty = 0, dragging = false, sx = 0, sy = 0; + const apply = () => { img.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`; img.style.cursor = dragging ? "grabbing" : "grab"; }; + const onWheel = (ev) => { ev.preventDefault(); const step = 0.1; scale += (ev.deltaY > 0 ? -step : step); if (scale < 0.1) scale = 0.1; if (scale > 5) scale = 5; apply(); }; + const onDown = (ev) => { ev.preventDefault(); dragging = true; sx = ev.clientX; sy = ev.clientY; apply(); }; + const onMove = (ev) => { if (!dragging) return; const dx = ev.clientX - sx, dy = ev.clientY - sy; sx = ev.clientX; sy = ev.clientY; tx += dx; ty += dy; apply(); }; + const onUp = () => { dragging = false; apply(); }; + img.addEventListener("wheel", onWheel, { passive: false }); img.addEventListener("mousedown", onDown); document.addEventListener("mousemove", onMove); document.addEventListener("mouseup", onUp); img.addEventListener("click", (ev) => ev.stopPropagation()); + const onKey = (ev) => { if (ev.key === "Escape") close(); }; + const close = () => { + document.body.style.overflow = "auto"; + img.removeEventListener("wheel", onWheel); + img.removeEventListener("mousedown", onDown); + document.removeEventListener("mousemove", onMove); + document.removeEventListener("mouseup", onUp); + document.removeEventListener("keydown", onKey); + mask.remove(); + }; + mask.addEventListener("click", (ev)=>{ if (ev.target === mask) close(); }); + box.addEventListener("click", (ev)=>ev.stopPropagation()); + const dl = document.createElement("button"); dl.textContent = "下载图片"; Object.assign(dl.style, { position: "absolute", right: "24px", bottom: "24px", zIndex: "10001", padding: "8px 14px", borderRadius: "6px", border: "none", cursor: "pointer", backgroundColor: "#50e3c2", color: "#000" }); + dl.addEventListener("click", (ev) => { ev.stopPropagation(); const name = (src.split("/").pop() || "image").split("?")[0]; fetch(src).then((r) => r.blob()).then((blob) => { const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = name || "image"; document.body.appendChild(a); a.click(); a.remove(); setTimeout(()=>URL.revokeObjectURL(url),0); }).catch(() => { const a = document.createElement("a"); a.href = src; a.target = "_blank"; document.body.appendChild(a); a.click(); a.remove(); }); }); + box.appendChild(dl); + document.body.appendChild(mask); + document.addEventListener("keydown", onKey); + document.body.style.overflow = "hidden"; + apply(); + } +} +if (!customElements.get("preview-image")) customElements.define("preview-image", PreviewImage); +// 3. 暴露统一对象(可使用 previewImage.initComponent(url)) +PreviewImage.initComponent = function(url){ + if (window.previewImageComponent) { window.previewImageComponent.init(url); return true; } + PreviewImage.open(url); return true; +}; +window.previewImage = PreviewImage; diff --git a/css/details.css b/css/details.css index 492bf31..e53f527 100644 --- a/css/details.css +++ b/css/details.css @@ -156,7 +156,7 @@ font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; font-size: 15px; color: #555555; - line-height: 24px; + line-height: 26px; margin-bottom: 66px; } #details .matter .matter-left .html a { @@ -177,6 +177,13 @@ #details .matter .matter-left .html video { margin: 0 auto; } +#details .matter .matter-left .html h2 { + font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; + font-weight: 650; + color: #000000; + font-size: 18px; + line-height: 30px; +} #details .matter .matter-left .last-time { color: #aaaaaa; font-size: 13px; @@ -1124,6 +1131,7 @@ height: 80vh; border-radius: 8px; background-color: #111; + overflow: hidden; } .detail-image-mask .detail-image .detail-img { max-width: 100%; diff --git a/css/details.less b/css/details.less index 7283cc8..608bfc0 100644 --- a/css/details.less +++ b/css/details.less @@ -180,7 +180,7 @@ font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; font-size: 15px; color: #555555; - line-height: 24px; + line-height: 26px; margin-bottom: 66px; a { @@ -204,6 +204,14 @@ video { margin: 0 auto; } + + h2 { + font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; + font-weight: 650; + color: #000000; + font-size: 18px; + line-height: 30px; + } } .last-time { @@ -1316,6 +1324,7 @@ height: 80vh; border-radius: 8px; background-color: #111; + overflow: hidden; } .detail-image-mask .detail-image .detail-img { diff --git a/css/signIn.css b/css/signIn.css new file mode 100644 index 0000000..cd950f4 --- /dev/null +++ b/css/signIn.css @@ -0,0 +1,112 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; + font-weight: 400; + font-style: normal; + word-break: break-word; +} +a { + text-decoration: none; + color: unset; +} +body { + background-color: #eef2f5; +} +.flexflex { + display: flex; +} +.flexcenter { + display: flex; + justify-content: center; + align-items: center; +} +.flexjcenter { + display: flex; + justify-content: center; +} +.flexacenter { + display: flex; + align-items: center; +} +.flex1 { + flex: 1; +} +.signInBox-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 10005; +} +.signInBox-mask .signInBox { + width: 1060px; + height: 658px; + background-color: #fff; + border-radius: 20px; + position: relative; + filter: drop-shadow(0 -5px 0 #f7c308); +} +.signInBox-mask .signInBox .signInBox-head { + position: relative; + height: 64px; + border-bottom: 1px dotted #d7d7d7; +} +.signInBox-mask .signInBox .signInBox-head .header-bi { + width: 83px; + height: 99px; + position: absolute; + top: -61px; + left: 50%; + transform: translateX(-50%); +} +.signInBox-mask .signInBox .signInBox-head .header-halo { + width: 160px; + height: 154px; + position: absolute; + top: -89px; + left: 50%; + transform: translateX(-50%); +} +.signInBox-mask .signInBox .signInBox-head .header-cross { + width: 18px; + height: 18px; + position: absolute; + top: 10px; + right: 10px; + cursor: pointer; +} +.signInBox-mask .signInBox .signInBox-content .left-box { + width: 538px; + padding: 20px 30px; + border-right: 1px dotted #d7d7d7; +} +.signInBox-mask .signInBox .signInBox-content .left-box .content-header { + font-size: 15px; + color: #555555; + line-height: 40px; +} +.signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-img { + width: 25px; + height: 30px; + margin-right: 7px; +} +.signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-value { + font-family: Arial-Black, "Arial Black", sans-serif; + font-weight: 900; + font-style: normal; + font-size: 28px; + color: #000000; + margin-right: 7px; +} +.signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-text { + font-size: 15px; + color: #555555; + line-height: normal; + margin-top: 8px; +} +.signInBox-mask .signInBox .signInBox-content .left-box .content-header .bi-rule { + margin-left: auto; +} diff --git a/css/signIn.less b/css/signIn.less new file mode 100644 index 0000000..e7adf9e --- /dev/null +++ b/css/signIn.less @@ -0,0 +1,135 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "PingFangSC-Regular", "PingFang SC", sans-serif; + font-weight: 400; + font-style: normal; + word-break: break-word; +} + +a { + text-decoration: none; + color: unset; +} + +body { + background-color: rgba(238, 242, 245, 1); +} + +.flexflex { + display: flex; +} + +.flexcenter { + display: flex; + justify-content: center; + align-items: center; +} + +.flexjcenter { + display: flex; + justify-content: center; +} + +.flexacenter { + display: flex; + align-items: center; +} + +.flex1 { + flex: 1; +} + +.signInBox-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + // background-color: rgba(0, 0, 0, 0.5); + z-index: 10005; + + .signInBox { + width: 1060px; + height: 658px; + background-color: #fff; + border-radius: 20px; + position: relative; + filter: drop-shadow(0 -5px 0 rgba(247, 195, 8, 1)); + + .signInBox-head { + position: relative; + height: 64px; + + border-bottom: 1px dotted #d7d7d7; + + .header-bi { + width: 83px; + height: 99px; + position: absolute; + top: -61px; + left: 50%; + transform: translateX(-50%); + } + + .header-halo { + width: 160px; + height: 154px; + position: absolute; + top: -89px; + left: 50%; + transform: translateX(-50%); + } + + .header-cross { + width: 18px; + height: 18px; + position: absolute; + top: 10px; + right: 10px; + cursor: pointer; + } + } + + .signInBox-content { + .left-box { + width: 538px; + padding: 20px 30px; + border-right: 1px dotted #d7d7d7; + + .content-header { + font-size: 15px; + color: rgb(85, 85, 85); + line-height: 40px; + + .bi-img { + width: 25px; + height: 30px; + margin-right: 7px; + } + + .bi-value { + font-family: Arial-Black, "Arial Black", sans-serif; + font-weight: 900; + font-style: normal; + font-size: 28px; + color: rgb(0, 0, 0); + margin-right: 7px; + } + + .bi-text { + font-size: 15px; + color: #555555; + line-height: normal; + margin-top: 8px; + } + + .bi-rule { + margin-left: auto; + } + } + } + } + } +} diff --git a/details.html b/details.html index 131498c..9b39132 100644 --- a/details.html +++ b/details.html @@ -17,7 +17,7 @@