修复h5记事本不显示问题

This commit is contained in:
2026-08-18 09:25:51 +08:00
parent aed71d237d
commit 0e797c39f4
11 changed files with 911 additions and 452 deletions
+38 -7
View File
@@ -36,24 +36,47 @@ function showGeetest4H5(captchaId) {
reject(new Error('极验 SDK 未加载'))
return
}
let settled = false
const settle = (fn) => {
if (settled) return
settled = true
fn()
}
window.initGeetest4(
{
captchaId,
product: 'bind',
language: 'zh-CN'
language: 'zh-CN',
https: true
},
(instance) => {
instance.onSuccess(() => {
resolve(normalizeValidate(instance.getValidate(), captchaId))
if (typeof instance.destroy === 'function') {
instance.destroy()
const teardown = () => {
try {
if (typeof instance.hideCaptcha === 'function') instance.hideCaptcha()
if (typeof instance.destroy === 'function') instance.destroy()
} catch {
// ignore
}
}
instance.onSuccess(() => {
const result = normalizeValidate(instance.getValidate(), captchaId)
teardown()
settle(() => resolve(result))
})
instance.onFail(() => {
reject(new Error('人机验证未通过'))
teardown()
settle(() => reject(new Error('人机验证未通过')))
})
instance.onError(() => {
reject(new Error('人机验证加载失败'))
teardown()
settle(() => reject(new Error('人机验证加载失败')))
})
instance.onClose?.(() => {
setTimeout(() => {
if (settled) return
teardown()
settle(() => reject(new Error('已取消人机验证')))
}, 400)
})
instance.showCaptcha()
}
@@ -64,6 +87,14 @@ function showGeetest4H5(captchaId) {
// #ifdef APP-PLUS
function showGeetest4App(captchaId) {
// 清理可能残留的原生 Webview
if (typeof plus !== 'undefined' && plus.webview) {
try {
const old = plus.webview.getWebviewById('geetest-captcha-overlay')
if (old) old.close('none')
} catch (e) {}
}
return new Promise((resolve, reject) => {
uni.navigateTo({
url: `/pages/login/geetest-webview?captchaId=${encodeURIComponent(captchaId)}`,
+82 -4
View File
@@ -1,17 +1,89 @@
/** H5 富文本表格 DOM 操作 */
/**
* 富文本表格操作与行内样式/属性注入工具
* 注入 border="1"、cellpadding="8"、cellspacing="0" 以及 style 属性
* 保证在 H5、App-plus 原生 editor、小程序以及 rich-text 中均能拥有清晰的表格边框与样式
*/
const TABLE_STYLE = 'border-collapse: collapse; width: 100%; border: 1px solid #dcdfe6; margin: 12px 0; table-layout: auto;'
const TR_STYLE = 'border-bottom: 1px solid #ebeef5;'
const TH_STYLE = 'border: 1px solid #dcdfe6; background-color: #f5f7fa; color: #303133; font-weight: 600; padding: 8px 12px; font-size: 14px; text-align: left; min-width: 44px; word-break: break-word;'
const TD_STYLE = 'border: 1px solid #dcdfe6; background-color: #ffffff; color: #303133; padding: 8px 12px; font-size: 14px; vertical-align: top; word-break: break-word; min-width: 44px;'
/**
* 给 HTML 字符串中的所有 table/tr/th/td 注入高优先级的行内样式与原生 HTML 边框属性
* (双重保障,即使 Quill 或原生组件重置了部分 CSS,border="1" 仍能强制渲染出边框)
*/
export function injectTableInlineStyles(html) {
if (!html || typeof html !== 'string') return ''
let res = html
// 注入 table 属性与样式
res = res.replace(/<table(\s+[^>]*)?>/gi, (match, attrs = '') => {
let cleanAttrs = attrs
cleanAttrs = cleanAttrs.replace(/\s+(border|cellspacing|cellpadding)\s*=\s*["'][^"']*["']/gi, '')
if (/style\s*=\s*["']/i.test(cleanAttrs)) {
cleanAttrs = cleanAttrs.replace(/style\s*=\s*["']([^"']*)["']/i, (m, s) => `style="${s}; ${TABLE_STYLE}"`)
} else {
cleanAttrs = ` style="${TABLE_STYLE}"` + cleanAttrs
}
return `<table border="1" cellpadding="8" cellspacing="0"${cleanAttrs}>`
})
// 注入 tr 样式
res = res.replace(/<tr(\s+[^>]*)?>/gi, (match, attrs = '') => {
if (/style\s*=\s*["']/i.test(attrs)) {
return `<tr${attrs.replace(/style\s*=\s*["']([^"']*)["']/i, (m, s) => `style="${s}; ${TR_STYLE}"`)}>`
}
return `<tr style="${TR_STYLE}"${attrs}>`
})
// 注入 th 属性与样式
res = res.replace(/<th(\s+[^>]*)?>/gi, (match, attrs = '') => {
let cleanAttrs = attrs.replace(/\s+border\s*=\s*["'][^"']*["']/gi, '')
if (/style\s*=\s*["']/i.test(cleanAttrs)) {
cleanAttrs = cleanAttrs.replace(/style\s*=\s*["']([^"']*)["']/i, (m, s) => `style="${s}; ${TH_STYLE}"`)
} else {
cleanAttrs = ` style="${TH_STYLE}"` + cleanAttrs
}
return `<th border="1"${cleanAttrs}>`
})
// 注入 td 属性与样式
res = res.replace(/<td(\s+[^>]*)?>/gi, (match, attrs = '') => {
let cleanAttrs = attrs.replace(/\s+border\s*=\s*["'][^"']*["']/gi, '')
if (/style\s*=\s*["']/i.test(cleanAttrs)) {
cleanAttrs = cleanAttrs.replace(/style\s*=\s*["']([^"']*)["']/i, (m, s) => `style="${s}; ${TD_STYLE}"`)
} else {
cleanAttrs = ` style="${TD_STYLE}"` + cleanAttrs
}
return `<td border="1"${cleanAttrs}>`
})
return res
}
export function createEmptyCell(tagName = 'td') {
const cell = document.createElement(tagName)
cell.innerHTML = '<p><br></p>'
cell.setAttribute('border', '1')
if (tagName === 'th') {
cell.style.cssText = TH_STYLE
} else {
cell.style.cssText = TD_STYLE
}
return cell
}
export function buildTableHtml(rows = 3, cols = 3) {
let html = '<table><tbody>'
let html = `<table border="1" cellpadding="8" cellspacing="0" style="${TABLE_STYLE}"><tbody>`
for (let r = 0; r < rows; r += 1) {
html += '<tr>'
html += `<tr style="${TR_STYLE}">`
for (let c = 0; c < cols; c += 1) {
html += '<td><p><br></p></td>'
if (r === 0) {
html += `<th border="1" style="${TH_STYLE}"><p><br></p></th>`
} else {
html += `<td border="1" style="${TD_STYLE}"><p><br></p></td>`
}
}
html += '</tr>'
}
@@ -32,10 +104,13 @@ export function getCurrentCell(editorEl) {
export function addRowBefore(cell) {
const row = cell.closest('tr')
const newRow = row.cloneNode(true)
newRow.style.cssText = TR_STYLE
newRow.querySelectorAll('td, th').forEach((item) => {
item.innerHTML = '<p><br></p>'
item.removeAttribute('colspan')
item.removeAttribute('rowspan')
item.setAttribute('border', '1')
item.style.cssText = item.tagName.toLowerCase() === 'th' ? TH_STYLE : TD_STYLE
})
row.before(newRow)
return newRow.cells[cell.cellIndex] || newRow.cells[0]
@@ -44,10 +119,13 @@ export function addRowBefore(cell) {
export function addRowAfter(cell) {
const row = cell.closest('tr')
const newRow = row.cloneNode(true)
newRow.style.cssText = TR_STYLE
newRow.querySelectorAll('td, th').forEach((item) => {
item.innerHTML = '<p><br></p>'
item.removeAttribute('colspan')
item.removeAttribute('rowspan')
item.setAttribute('border', '1')
item.style.cssText = item.tagName.toLowerCase() === 'th' ? TH_STYLE : TD_STYLE
})
row.after(newRow)
return newRow.cells[cell.cellIndex] || newRow.cells[0]