mirror of
https://github.com/027xiguapi/code-box.git
synced 2026-09-24 16:18:36 +00:00
重构dom选择器
This commit is contained in:
@@ -1,248 +0,0 @@
|
||||
import React, { useEffect, useRef } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
|
||||
import { useMessage } from "@plasmohq/messaging/hook"
|
||||
import { useStorage } from "@plasmohq/storage/dist/hook"
|
||||
|
||||
import ValidateContent from "~component/contents/validateContent"
|
||||
import { addCss, saveHtml, saveMarkdown } from "~tools"
|
||||
import { useEditMarkdown } from "~utils/editMarkdownHook"
|
||||
import { useParseMarkdown } from "~utils/parseMarkdownHook"
|
||||
import { Print } from "~utils/print"
|
||||
import Turndown from "~utils/turndown"
|
||||
|
||||
import Tooltip from "../ui/tooltip"
|
||||
|
||||
const turndownService = Turndown()
|
||||
|
||||
export default function CustomDomSelector() {
|
||||
const [aiType, setAiType] = useStorage("app-aiType")
|
||||
const isReady = useRef(false)
|
||||
const isSelect = useRef(false)
|
||||
const downloadType = useRef("")
|
||||
const [editContent, setEditContent] = useEditMarkdown()
|
||||
const [parseContent, setParseContent] = useParseMarkdown()
|
||||
|
||||
const selectorRef = useRef<HTMLElement | null>(null)
|
||||
const tooltipRef = useRef<HTMLElement | null>(null)
|
||||
const modalRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
const articleTitle = document
|
||||
.querySelector<HTMLElement>("head title")
|
||||
?.innerText.trim()
|
||||
|
||||
useEffect(() => {
|
||||
if (aiType) {
|
||||
addEventListeners()
|
||||
addCss(`.codebox-current { outline: 2px solid #42b88350 !important; }`)
|
||||
}
|
||||
return () => {
|
||||
removeEventListeners()
|
||||
removeTooltip()
|
||||
removeHighlight()
|
||||
}
|
||||
}, [aiType])
|
||||
|
||||
const createTooltip = () => {
|
||||
const tooltip = document.createElement("div")
|
||||
tooltip.classList.add("codebox-tooltip")
|
||||
tooltip.style.position = "absolute"
|
||||
tooltip.style.zIndex = "2147483641"
|
||||
tooltip.style.backgroundColor = "#fff"
|
||||
tooltip.style.border = "1px solid #eee"
|
||||
tooltip.style.borderRadius = "5px"
|
||||
tooltip.style.padding = "8px"
|
||||
tooltip.style.boxShadow = "0 2px 8px rgba(0, 0, 0, 0.15)"
|
||||
|
||||
document.body.appendChild(tooltip)
|
||||
const root = createRoot(tooltip)
|
||||
root.render(
|
||||
<Tooltip
|
||||
onConfirm={handleConfirm}
|
||||
onCancel={handleCancel}
|
||||
onNavigate={navigateElement}
|
||||
/>
|
||||
)
|
||||
tooltipRef.current = tooltip
|
||||
}
|
||||
|
||||
const removeTooltip = () => {
|
||||
if (tooltipRef.current) {
|
||||
document.body.removeChild(tooltipRef.current)
|
||||
tooltipRef.current = null
|
||||
}
|
||||
}
|
||||
|
||||
const addEventListeners = () => {
|
||||
document.addEventListener("mousemove", handleMouseMove)
|
||||
document.addEventListener("click", handleClick)
|
||||
}
|
||||
|
||||
const removeEventListeners = () => {
|
||||
document.removeEventListener("mousemove", handleMouseMove)
|
||||
document.removeEventListener("click", handleClick)
|
||||
}
|
||||
|
||||
const handleMouseMove = (event: MouseEvent) => {
|
||||
if (isReady.current && !isSelect.current) {
|
||||
const target = event.target as HTMLElement
|
||||
highlightElement(target)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClick = (event: MouseEvent) => {
|
||||
if (isReady.current) {
|
||||
const target = event.target as HTMLElement
|
||||
const tooltip = target.closest(".codebox-tooltip")
|
||||
const modal = target.closest(".codebox-modal")
|
||||
const submit = target.closest(".valid-submit")
|
||||
|
||||
if (!tooltip && !modal && !submit) {
|
||||
removeTooltip()
|
||||
createTooltip()
|
||||
isSelect.current = true
|
||||
highlightElement(target)
|
||||
updateTooltipPosition(target)
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const highlightElement = (element: HTMLElement) => {
|
||||
removeHighlight()
|
||||
element.classList.add("codebox-current")
|
||||
selectorRef.current = element
|
||||
}
|
||||
|
||||
const removeHighlight = () => {
|
||||
const currentList = document.querySelectorAll(".codebox-current")
|
||||
currentList.forEach((el) => el.classList.remove("codebox-current"))
|
||||
selectorRef.current = null
|
||||
}
|
||||
|
||||
const updateTooltipPosition = (element: HTMLElement) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const distanceTop = rect.top + window.scrollY
|
||||
const distanceLeft = rect.left + window.scrollX
|
||||
const top =
|
||||
distanceTop < 50 ? distanceTop + rect.height + 5 : distanceTop - 40
|
||||
tooltipRef.current.style.top = `${top}px`
|
||||
tooltipRef.current.style.left = `${distanceLeft + 5}px`
|
||||
window.scrollTo({ top: top - 150, behavior: "smooth" })
|
||||
}
|
||||
|
||||
useMessage(async (req: any, res: any) => {
|
||||
const name = req.name
|
||||
setCustom(name.split("-")[1])
|
||||
})
|
||||
|
||||
const setCustom = (type: string) => {
|
||||
downloadType.current = type
|
||||
isReady.current = true
|
||||
isSelect.current = false
|
||||
}
|
||||
|
||||
const handleOkModal = () => {
|
||||
if (!selectorRef.current || !downloadType.current) return
|
||||
|
||||
const current = document.querySelector(".codebox-current")
|
||||
current.classList.remove("codebox-current")
|
||||
|
||||
switch (downloadType.current) {
|
||||
case "downloadHtml":
|
||||
saveHtml(selectorRef.current, articleTitle)
|
||||
break
|
||||
case "downloadMarkdown":
|
||||
const markdown = turndownService.turndown(selectorRef.current)
|
||||
saveMarkdown(markdown, articleTitle)
|
||||
break
|
||||
case "editMarkdown":
|
||||
setEditContent(selectorRef.current)
|
||||
break
|
||||
case "parseMarkdown":
|
||||
setParseContent(selectorRef.current, aiType)
|
||||
break
|
||||
case "downloadPdf":
|
||||
const elementToPrint = selectorRef.current
|
||||
if (elementToPrint) {
|
||||
Print.print(elementToPrint, { title: articleTitle })
|
||||
.then(() => console.log("Printing complete"))
|
||||
.catch((error) => console.error("Printing failed:", error))
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
resetState()
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(modalRef.current)
|
||||
modalRef.current = null
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
const modal = document.createElement("div")
|
||||
modal.classList.add("codebox-modal")
|
||||
modal.style.position = "fixed"
|
||||
modal.style.zIndex = "2147483648"
|
||||
modal.style.backgroundColor = "rgba(0, 0, 0, 0.7)"
|
||||
modal.style.width = "100vw"
|
||||
modal.style.height = "100vh"
|
||||
modal.style.top = "0"
|
||||
modal.style.left = "0"
|
||||
document.body.appendChild(modal)
|
||||
const root = createRoot(modal)
|
||||
root.render(
|
||||
<ValidateContent
|
||||
type={downloadType.current}
|
||||
handleOk={handleOkModal}
|
||||
handleCancel={handleCancelModal}
|
||||
/>
|
||||
)
|
||||
modalRef.current = modal
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
resetState()
|
||||
}
|
||||
|
||||
const resetState = () => {
|
||||
removeHighlight()
|
||||
removeTooltip()
|
||||
isReady.current = false
|
||||
isSelect.current = false
|
||||
}
|
||||
|
||||
const navigateElement = (direction: "parent" | "child" | "prev" | "next") => {
|
||||
if (!selectorRef.current) return
|
||||
|
||||
let newElement: HTMLElement | null = null
|
||||
switch (direction) {
|
||||
case "parent":
|
||||
newElement = selectorRef.current.parentElement
|
||||
break
|
||||
case "child":
|
||||
newElement = selectorRef.current.firstElementChild as HTMLElement
|
||||
break
|
||||
case "prev":
|
||||
newElement = selectorRef.current.previousElementSibling as HTMLElement
|
||||
break
|
||||
case "next":
|
||||
newElement = selectorRef.current.nextElementSibling as HTMLElement
|
||||
break
|
||||
}
|
||||
|
||||
if (newElement) {
|
||||
highlightElement(newElement)
|
||||
// updateSelectorPosition(newElement)
|
||||
updateTooltipPosition(newElement)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelModal = () => {
|
||||
document.body.removeChild(modalRef.current)
|
||||
modalRef.current = null
|
||||
}
|
||||
|
||||
return <div style={{ display: "none" }}></div>
|
||||
}
|
||||
@@ -8,7 +8,6 @@ interface QRCodeModalProps {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
// 新增样式
|
||||
const styles = {
|
||||
overlay: {
|
||||
position: "fixed" as const,
|
||||
@@ -70,10 +69,6 @@ const styles = {
|
||||
letterSpacing: "2px",
|
||||
color: "#333"
|
||||
},
|
||||
countdown: {
|
||||
color: "#666",
|
||||
fontSize: "0.9rem"
|
||||
},
|
||||
inputGroup: {
|
||||
display: "flex",
|
||||
gap: "0.5rem"
|
||||
@@ -130,7 +125,6 @@ export default function QRCodeModal({ onClose, onConfirm }: QRCodeModalProps) {
|
||||
return (
|
||||
<div style={styles.overlay}>
|
||||
<div style={styles.content}>
|
||||
{/* 原有关闭按钮和二维码内容... */}
|
||||
<button style={styles.closeButton} onClick={onClose} aria-label="Close">
|
||||
×
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
|
||||
import { useMessage } from "@plasmohq/messaging/hook"
|
||||
import { useStorage } from "@plasmohq/storage/dist/hook"
|
||||
|
||||
import ValidModal from "~component/ui/validModal"
|
||||
import { addCss, saveHtml, saveMarkdown } from "~tools"
|
||||
import { useEditMarkdown } from "~utils/editMarkdownHook"
|
||||
import { useParseMarkdown } from "~utils/parseMarkdownHook"
|
||||
import { Print } from "~utils/print"
|
||||
import Turndown from "~utils/turndown"
|
||||
|
||||
import Tooltip from "../ui/tooltip"
|
||||
|
||||
const turndownService = Turndown()
|
||||
|
||||
export default function CustomDomSelector() {
|
||||
const [aiType, setAiType] = useStorage("app-aiType")
|
||||
const [position, setPosition] = useState({ top: 0, left: 0 })
|
||||
const [isReady, setIsReady] = useState(false)
|
||||
const [isSelect, setIsSelect] = useState(false)
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
const downloadType = useRef("")
|
||||
const [editContent, setEditContent] = useEditMarkdown()
|
||||
const [parseContent, setParseContent] = useParseMarkdown()
|
||||
|
||||
const articleTitle = document
|
||||
.querySelector<HTMLElement>("head title")
|
||||
?.innerText.trim()
|
||||
|
||||
useEffect(() => {
|
||||
if (aiType) {
|
||||
addCss(`.codebox-current { outline: 2px solid #42b88350 !important; }`)
|
||||
if (isReady) {
|
||||
addEventListeners()
|
||||
} else {
|
||||
removeEventListeners()
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
removeEventListeners()
|
||||
}
|
||||
}, [aiType, isReady, isSelect])
|
||||
|
||||
const addEventListeners = () => {
|
||||
document.addEventListener("mousemove", handleMouseMove)
|
||||
document.addEventListener("click", handleClick)
|
||||
}
|
||||
|
||||
const removeEventListeners = () => {
|
||||
document.removeEventListener("mousemove", handleMouseMove)
|
||||
document.removeEventListener("click", handleClick)
|
||||
}
|
||||
|
||||
const handleMouseMove = (event: MouseEvent) => {
|
||||
if (isReady && !isSelect) {
|
||||
const target = event.target as HTMLElement
|
||||
highlightElement(target)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClick = (event: MouseEvent) => {
|
||||
if (isReady) {
|
||||
const target = event.target as HTMLElement
|
||||
const tooltip = target.closest(".codebox-tooltip")
|
||||
const modal = target.closest(".codebox-modal")
|
||||
const csui = target.closest("#codebox-csui")
|
||||
|
||||
if (!tooltip && !modal && !csui) {
|
||||
setIsSelect(true)
|
||||
highlightElement(target)
|
||||
updateTooltipPosition(target)
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const highlightElement = (element: HTMLElement) => {
|
||||
removeHighlight()
|
||||
element.classList.add("codebox-current")
|
||||
}
|
||||
|
||||
const removeHighlight = () => {
|
||||
const currentList = document.querySelectorAll(".codebox-current")
|
||||
currentList.forEach((el) => el.classList.remove("codebox-current"))
|
||||
}
|
||||
|
||||
const updateTooltipPosition = (element: HTMLElement) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const distanceTop = rect.top + window.scrollY
|
||||
const distanceLeft = rect.left + window.scrollX
|
||||
const top =
|
||||
distanceTop < 50 ? distanceTop + rect.height + 5 : distanceTop - 40
|
||||
const left = distanceLeft + 5
|
||||
|
||||
setPosition({ top: top, left: left })
|
||||
window.scrollTo({ top: top - 150, behavior: "smooth" })
|
||||
}
|
||||
|
||||
useMessage(async (req: any, res: any) => {
|
||||
const name = req.name
|
||||
setCustom(name.split("-")[1])
|
||||
})
|
||||
|
||||
const setCustom = (type: string) => {
|
||||
downloadType.current = type
|
||||
setIsReady(true)
|
||||
setIsSelect(false)
|
||||
}
|
||||
|
||||
const handleOkModal = () => {
|
||||
const selector = document.querySelector<HTMLElement>(".codebox-current")
|
||||
if (!selector || !downloadType.current) return
|
||||
|
||||
selector.classList.remove("codebox-current")
|
||||
|
||||
switch (downloadType.current) {
|
||||
case "downloadHtml":
|
||||
saveHtml(selector, articleTitle)
|
||||
break
|
||||
case "downloadMarkdown":
|
||||
const markdown = turndownService.turndown(selector)
|
||||
saveMarkdown(markdown, articleTitle)
|
||||
break
|
||||
case "editMarkdown":
|
||||
setEditContent(selector)
|
||||
break
|
||||
case "parseMarkdown":
|
||||
setParseContent(selector, aiType)
|
||||
break
|
||||
case "downloadPdf":
|
||||
Print.print(selector, { title: articleTitle })
|
||||
.then(() => console.log("Printing complete"))
|
||||
.catch((error) => console.error("Printing failed:", error))
|
||||
break
|
||||
}
|
||||
|
||||
resetState()
|
||||
setTimeout(() => {
|
||||
setIsModalOpen(false)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
setIsModalOpen(true)
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
resetState()
|
||||
}
|
||||
|
||||
const resetState = () => {
|
||||
removeHighlight()
|
||||
setIsSelect(false)
|
||||
setIsReady(false)
|
||||
}
|
||||
|
||||
const navigateElement = (direction: "parent" | "child" | "prev" | "next") => {
|
||||
const selector = document.querySelector(".codebox-current")
|
||||
if (!selector) return
|
||||
let newElement: HTMLElement | null = null
|
||||
switch (direction) {
|
||||
case "parent":
|
||||
newElement = selector.parentElement
|
||||
break
|
||||
case "child":
|
||||
newElement = selector.firstElementChild as HTMLElement
|
||||
break
|
||||
case "prev":
|
||||
newElement = selector.previousElementSibling as HTMLElement
|
||||
break
|
||||
case "next":
|
||||
newElement = selector.nextElementSibling as HTMLElement
|
||||
break
|
||||
}
|
||||
|
||||
if (newElement) {
|
||||
highlightElement(newElement)
|
||||
updateTooltipPosition(newElement)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancelModal = () => {
|
||||
setIsModalOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isSelect && (
|
||||
<Tooltip
|
||||
left={position.left}
|
||||
top={position.top}
|
||||
onConfirm={handleConfirm}
|
||||
onCancel={handleCancel}
|
||||
onNavigate={navigateElement}
|
||||
/>
|
||||
)}
|
||||
{isModalOpen && (
|
||||
<ValidModal onClose={handleCancelModal} onConfirm={handleOkModal} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -10,7 +10,16 @@ import React from "react"
|
||||
|
||||
const tooltipStyles = {
|
||||
tooltip: {
|
||||
backgroundColor: "#fff"
|
||||
position: "absolute" as const,
|
||||
zIndex: "2147483641",
|
||||
backgroundColor: "#fff",
|
||||
border: "1px solid #eee",
|
||||
borderRadius: "5px",
|
||||
padding: "8px",
|
||||
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
||||
width: "450px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between"
|
||||
},
|
||||
button: {
|
||||
backgroundColor: "#fff",
|
||||
@@ -18,7 +27,8 @@ const tooltipStyles = {
|
||||
color: "#000",
|
||||
borderRadius: "4px",
|
||||
padding: "2px 7px",
|
||||
fontSize: "14px"
|
||||
fontSize: "14px",
|
||||
cursor: "pointer"
|
||||
},
|
||||
blueButton: {
|
||||
backgroundColor: "#1677FF",
|
||||
@@ -51,8 +61,12 @@ export default function Tooltip(props: any) {
|
||||
props.onCancel()
|
||||
}
|
||||
|
||||
const setTooltipStyle = () => {
|
||||
return { ...tooltipStyles.tooltip, left: props.left, top: props.top }
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={tooltipStyles.tooltip as React.CSSProperties}>
|
||||
<div style={setTooltipStyle()} className="codebox-tooltip">
|
||||
<button style={tooltipStyles.blueButton} onClick={handleConfirm}>
|
||||
<CheckOutlined /> 确定
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
import dayjs from "dayjs"
|
||||
import qrcodeUrl from "raw:~/public/wx/qrcode_wx.jpg"
|
||||
import React, { useRef, useState } from "react"
|
||||
|
||||
import { sendToBackground } from "@plasmohq/messaging"
|
||||
import { useStorage } from "@plasmohq/storage/dist/hook"
|
||||
|
||||
import { verifyTOTP } from "~utils/2FA"
|
||||
|
||||
const styles = {
|
||||
overlay: {
|
||||
position: "fixed" as const,
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
zIndex: 1000
|
||||
},
|
||||
container: {
|
||||
width: "350px",
|
||||
padding: "2rem",
|
||||
position: "absolute" as const,
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
backgroundColor: "white",
|
||||
borderRadius: "5px",
|
||||
textAlign: "center" as const,
|
||||
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.1)"
|
||||
},
|
||||
closeButton: {
|
||||
position: "absolute" as const,
|
||||
top: "10px",
|
||||
right: "10px",
|
||||
background: "none",
|
||||
border: "none",
|
||||
fontSize: "1.5rem",
|
||||
cursor: "pointer",
|
||||
padding: "0.5rem"
|
||||
},
|
||||
activatedText: {
|
||||
fontSize: "16px",
|
||||
color: "red"
|
||||
},
|
||||
noticeText: {
|
||||
fontSize: "14px",
|
||||
color: "red"
|
||||
},
|
||||
helpLink: {
|
||||
cursor: "pointer"
|
||||
},
|
||||
qrcodeImage: {
|
||||
margin: "auto"
|
||||
},
|
||||
inputContainer: {
|
||||
marginTop: "10px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
},
|
||||
label: {
|
||||
display: "block",
|
||||
marginRight: "7px"
|
||||
},
|
||||
captchaSection: {
|
||||
marginTop: "1.5rem",
|
||||
borderTop: "1px solid #eee",
|
||||
paddingTop: "1.5rem"
|
||||
},
|
||||
captchaRow: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "1rem"
|
||||
},
|
||||
captchaText: {
|
||||
fontSize: "1.2rem",
|
||||
letterSpacing: "2px",
|
||||
color: "#333"
|
||||
},
|
||||
inputGroup: {
|
||||
display: "flex",
|
||||
gap: "0.5rem"
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
padding: "0.8rem",
|
||||
border: "1px solid #ddd",
|
||||
borderRadius: "4px",
|
||||
fontSize: "1rem",
|
||||
outline: "none",
|
||||
"&:focus": {
|
||||
borderColor: "#007bff"
|
||||
}
|
||||
},
|
||||
verifyButton: {
|
||||
padding: "0.8rem 1.5rem",
|
||||
backgroundColor: "#007bff",
|
||||
color: "white",
|
||||
border: "none",
|
||||
borderRadius: "4px",
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
backgroundColor: "#0056b3"
|
||||
}
|
||||
},
|
||||
errorText: {
|
||||
color: "#ff4444",
|
||||
fontSize: "0.9rem",
|
||||
marginTop: "0.5rem"
|
||||
}
|
||||
}
|
||||
|
||||
export default function ValidModal(props) {
|
||||
const [validTime, setValidTime] = useStorage("app-validTime", "1730390400")
|
||||
const [inputCode, setInputCode] = useState<string>("")
|
||||
const [isValid, setIsValid] = useState(true)
|
||||
|
||||
function handleSubmit() {
|
||||
if (Number(validTime) > dayjs().unix()) {
|
||||
props.handleOk()
|
||||
} else if (
|
||||
verifyTOTP(process.env.PLASMO_PUBLIC_CODEBOX_SECRET1, inputCode)
|
||||
) {
|
||||
let time = dayjs().add(20, "day").unix()
|
||||
setValidTime(String(time))
|
||||
setIsValid(true)
|
||||
props.handleOk()
|
||||
} else if (
|
||||
verifyTOTP(process.env.PLASMO_PUBLIC_CODEBOX_SECRET2, inputCode)
|
||||
) {
|
||||
let time = dayjs().add(65, "day").unix()
|
||||
setValidTime(String(time))
|
||||
setIsValid(true)
|
||||
props.handleOk()
|
||||
} else if (process.env.PLASMO_PUBLIC_CODEBOX_SECRET3 == inputCode) {
|
||||
let time = dayjs().add(7, "day").unix()
|
||||
setValidTime(String(time))
|
||||
setIsValid(true)
|
||||
props.handleOk()
|
||||
} else if (
|
||||
verifyTOTP(process.env.PLASMO_PUBLIC_CODEBOX_SECRET4, inputCode)
|
||||
) {
|
||||
setIsValid(true)
|
||||
props.handleOk()
|
||||
} else {
|
||||
setIsValid(false)
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
props.onClose()
|
||||
}
|
||||
|
||||
function help() {
|
||||
sendToBackground({
|
||||
name: "tab",
|
||||
body: {
|
||||
url: "feed.html"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const typeMap = {
|
||||
downloadHtml: "下载HTML",
|
||||
downloadMarkdown: "下载markdown",
|
||||
editMarkdown: "编辑markdown",
|
||||
parseMarkdown: "解析markdown",
|
||||
downloadPdf: "下载PDF"
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={styles.overlay} className="codebox-modal">
|
||||
<div style={styles.container}>
|
||||
<button
|
||||
style={styles.closeButton}
|
||||
onClick={handleCancel}
|
||||
aria-label="Close">
|
||||
×
|
||||
</button>
|
||||
{Number(validTime) > dayjs().unix() ? (
|
||||
<p style={styles.activatedText}>
|
||||
已激活!确认{typeMap[props.type]}?
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
<div style={styles.noticeText}>
|
||||
此功能需要关注公众号
|
||||
<p>
|
||||
【codebox代码助手】获取验证码(
|
||||
<a onClick={help} target="_blank" style={styles.helpLink}>
|
||||
帮助
|
||||
</a>
|
||||
)
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
style={styles.qrcodeImage}
|
||||
src={qrcodeUrl}
|
||||
alt="微信公众号"
|
||||
/>
|
||||
</div>
|
||||
<div style={styles.captchaSection}>
|
||||
<div style={styles.inputGroup}>
|
||||
<input
|
||||
type="text"
|
||||
value={inputCode}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value.replace(/[^\d\s]/g, "")
|
||||
setInputCode(val)
|
||||
setIsValid(null) // 清除验证状态
|
||||
}}
|
||||
placeholder="请输入验证码"
|
||||
style={{
|
||||
...styles.input,
|
||||
borderColor: isValid === false ? "#ff4444" : "#ddd"
|
||||
}}
|
||||
maxLength={11} // 6数字+5空格
|
||||
/>
|
||||
<button style={styles.verifyButton} onClick={handleSubmit}>
|
||||
验证
|
||||
</button>
|
||||
</div>
|
||||
{isValid === false && (
|
||||
<div style={styles.errorText}>验证码错误,请重新输入</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+2
-18
@@ -1,5 +1,3 @@
|
||||
import { StyleProvider } from "@ant-design/cssinjs"
|
||||
import antdResetCssText from "data-text:antd/dist/reset.css"
|
||||
import type {
|
||||
PlasmoCSConfig,
|
||||
PlasmoGetShadowHostId,
|
||||
@@ -11,8 +9,7 @@ import { sendToBackground } from "@plasmohq/messaging"
|
||||
import { useMessage } from "@plasmohq/messaging/hook"
|
||||
import { useStorage } from "@plasmohq/storage/hook"
|
||||
|
||||
import CustomDomSelector from "~component/customDomSelector"
|
||||
import { ThemeProvider } from "~theme"
|
||||
import CustomDomSelector from "~component/ui/customDomSelector"
|
||||
import { setIcon } from "~tools"
|
||||
import { getSummary } from "~utils/coze"
|
||||
import DrawImages from "~utils/drawImages"
|
||||
@@ -21,13 +18,6 @@ const HOST_ID = "codebox-csui"
|
||||
|
||||
export const getShadowHostId: PlasmoGetShadowHostId = () => HOST_ID
|
||||
|
||||
export const getStyle: PlasmoGetStyle = () => {
|
||||
const style = document.createElement("style")
|
||||
|
||||
style.textContent = antdResetCssText
|
||||
return style
|
||||
}
|
||||
|
||||
const articleTitle = document
|
||||
.querySelector<HTMLElement>("head title")
|
||||
?.innerText.trim()
|
||||
@@ -101,11 +91,5 @@ export default function CustomOverlay() {
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<StyleProvider container={document.getElementById(HOST_ID).shadowRoot}>
|
||||
<CustomDomSelector />
|
||||
</StyleProvider>
|
||||
</ThemeProvider>
|
||||
)
|
||||
return <CustomDomSelector />
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-box",
|
||||
"displayName": "__MSG_extensionName__",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"description": "__MSG_extensionDescription__",
|
||||
"author": "027xiguapi. <458813868@qq.com>",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user