AI回复内容,岗位卡片的点击事件绑定问题解决
This commit is contained in:
@@ -1,157 +1,194 @@
|
||||
import MarkdownIt from '@/lib/markdown-it.min.js';
|
||||
import hljs from "@/lib/highlight/highlight-uni.min.js";
|
||||
import parseHtml from '@/lib/html-parser.js';
|
||||
// import DOMPurify from '@/lib/dompurify@3.2.4es.js';
|
||||
|
||||
export let codeDataList = []
|
||||
export let jobMoreMap = new Map()
|
||||
|
||||
const md = new MarkdownIt({
|
||||
html: true, // 允许 HTML 标签
|
||||
linkify: true, // 自动解析 URL
|
||||
typographer: true, // 美化标点符号
|
||||
tables: true,
|
||||
breaks: true, // 让 \n 自动换行
|
||||
langPrefix: 'language-', // 代码高亮前缀
|
||||
// 如果结果以 <pre ... 开头,内部包装器则会跳过。
|
||||
highlight: function(str, lang) {
|
||||
if (lang === 'job-json') {
|
||||
const result = safeExtractJson(str);
|
||||
if (result) { // json解析成功
|
||||
const jobId = result.appJobUrl.split('jobId=')[1]
|
||||
let domContext = `<a class="custom-card" data-job-id="${jobId}"><div class="card-title"><span class="title-text">${result.jobTitle}</span><div class="card-salary">${result.salary}</div></div><div class="card-company">${result.location}·${result.companyName}</div><div class="card-info"><div class="info-item"><div class="card-tag">${result.education}</div><div class="card-tag">${result.experience}</div></div><div class="info-item">查看详情<div class="position-nav"></div></div></div></a>`
|
||||
if (result.data) {
|
||||
jobMoreMap.set(jobId, result.data)
|
||||
domContext += `<a class="custom-more" data-job-id="${jobId}">查看更多岗位<div class="more-icon"></div></a>`
|
||||
}
|
||||
return domContext
|
||||
}
|
||||
}
|
||||
// 代码块
|
||||
let preCode = ""
|
||||
try {
|
||||
preCode = hljs.highlightAuto(str).value
|
||||
} catch (err) {
|
||||
preCode = md.utils.escapeHtml(str);
|
||||
}
|
||||
// 以换行进行分割 , 按行拆分代码
|
||||
const lines = preCode.split(/\n/).slice(0, -1);
|
||||
const html = lines
|
||||
.map((line, index) =>
|
||||
line ?
|
||||
`<li><span class="line-num" data-line="${index + 1}"></span>${line}</li>` :
|
||||
'<li></li>'
|
||||
)
|
||||
.join('');
|
||||
|
||||
// 代码复制功能
|
||||
const cacheIndex = codeDataList.length;
|
||||
codeDataList.push(str);
|
||||
return `
|
||||
<div class="code-container">
|
||||
<div class="code-header">
|
||||
<span class="lang-label">${lang || 'plaintext'}</span>
|
||||
<a class="copy-btn" data-copy-index="${cacheIndex}">复制代码</a>
|
||||
</div>
|
||||
<pre class="hljs"><code><ol>${html}</ol></code></pre>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
})
|
||||
|
||||
function extractFirstJson(text) {
|
||||
let stack = [];
|
||||
let startIndex = -1;
|
||||
let endIndex = -1;
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const char = text[i];
|
||||
|
||||
if (char === '{') {
|
||||
if (stack.length === 0) startIndex = i; // 记录第一个 '{' 的位置
|
||||
stack.push(char);
|
||||
} else if (char === '}') {
|
||||
stack.pop();
|
||||
if (stack.length === 0) {
|
||||
endIndex = i; // 找到配对的 '}'
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startIndex !== -1 && endIndex !== -1) {
|
||||
const jsonString = text.slice(startIndex, endIndex + 1);
|
||||
try {
|
||||
const jsonObject = JSON.parse(jsonString);
|
||||
return jsonObject;
|
||||
} catch (e) {
|
||||
return null; // 如果不是有效的 JSON
|
||||
}
|
||||
}
|
||||
|
||||
return null; // 如果没有找到有效的 JSON 对象
|
||||
}
|
||||
|
||||
|
||||
function safeExtractJson(text) {
|
||||
try {
|
||||
const jsonObject = extractFirstJson(text);
|
||||
return jsonObject
|
||||
} catch (e) {
|
||||
console.error('JSON 解析失败:', e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function clearJobMoreMap() { // 切换对话清空
|
||||
jobMoreMap.clear()
|
||||
}
|
||||
|
||||
export function parseMarkdown(content) {
|
||||
if (!content) {
|
||||
return [] //处理特殊情况,比如网络异常导致的响应的 content 的值为空
|
||||
}
|
||||
|
||||
// 过滤掉<think>标签及其内容,这些是AI内部思考过程,不应该显示给用户
|
||||
// 1. 处理原始标签(支持多行)
|
||||
content = content.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 2. 处理HTML编码的标签
|
||||
content = content.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 3. 处理部分编码的标签
|
||||
content = content.replace(/<\s*think\s*>/gi, '')
|
||||
content = content.replace(/<\s*\/\s*think\s*>/gi, '')
|
||||
|
||||
codeDataList = []
|
||||
const unsafeHtml = md.render(content || '')
|
||||
|
||||
// 在markdown渲染后再次过滤,确保没有遗漏
|
||||
let filteredHtml = unsafeHtml
|
||||
// 1. 处理原始标签(支持多行)
|
||||
filteredHtml = filteredHtml.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 2. 处理HTML编码的标签
|
||||
filteredHtml = filteredHtml.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 3. 处理部分编码的标签
|
||||
filteredHtml = filteredHtml.replace(/<\s*think\s*>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<\s*\/\s*think\s*>/gi, '')
|
||||
// 4. 单独处理剩余的think标签对
|
||||
filteredHtml = filteredHtml.replace(/<think>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<\/think>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<think>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<\/think>/gi, '')
|
||||
|
||||
// 根据平台返回不同的内容格式
|
||||
// 微信小程序:返回rich-text组件支持的nodes格式
|
||||
// H5:直接返回HTML字符串,避免HTML解析错误
|
||||
if (process.env.UNI_PLATFORM === 'mp-weixin') {
|
||||
try {
|
||||
return parseHtml(filteredHtml)
|
||||
} catch (error) {
|
||||
console.error('HTML解析失败:', error)
|
||||
// 解析失败时返回空数组,避免页面崩溃
|
||||
return []
|
||||
}
|
||||
} else {
|
||||
// H5端直接返回HTML字符串
|
||||
return filteredHtml
|
||||
}
|
||||
}
|
||||
import MarkdownIt from '@/lib/markdown-it.min.js';
|
||||
import hljs from "@/lib/highlight/highlight-uni.min.js";
|
||||
import parseHtml from '@/lib/html-parser.js';
|
||||
// import DOMPurify from '@/lib/dompurify@3.2.4es.js';
|
||||
|
||||
export let codeDataList = []
|
||||
export let jobMoreMap = new Map()
|
||||
export let jobCardsList = []
|
||||
|
||||
const md = new MarkdownIt({
|
||||
html: true, // 允许 HTML 标签
|
||||
linkify: true, // 自动解析 URL
|
||||
typographer: true, // 美化标点符号
|
||||
tables: true,
|
||||
breaks: true, // 让 \n 自动换行
|
||||
langPrefix: 'language-', // 代码高亮前缀
|
||||
// 如果结果以 <pre ... 开头,内部包装器则会跳过。
|
||||
highlight: function(str, lang) {
|
||||
if (lang === 'job-json') {
|
||||
const result = safeExtractJson(str);
|
||||
if (result) { // json解析成功
|
||||
let jobId = result.appJobUrl;
|
||||
// If appJobUrl contains 'jobId=', extract the value after it, otherwise use it directly
|
||||
if (jobId && jobId.includes('jobId=')) {
|
||||
jobId = jobId.split('jobId=')[1];
|
||||
// 如果还有额外的参数,只取jobId部分
|
||||
if (jobId.includes('&')) {
|
||||
jobId = jobId.split('&')[0];
|
||||
}
|
||||
}
|
||||
console.log('Job JSON result:', result, 'Extracted jobId:', jobId);
|
||||
|
||||
// 确保jobId有效
|
||||
if (!jobId || jobId === 'undefined' || jobId === 'null') {
|
||||
console.error('Invalid jobId extracted:', jobId, 'from appJobUrl:', result.appJobUrl);
|
||||
// 尝试从其他字段获取jobId
|
||||
if (result.jobId) {
|
||||
jobId = result.jobId;
|
||||
console.log('Using jobId from result.jobId:', jobId);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加到岗位卡片列表,供小程序端单独渲染
|
||||
jobCardsList.push({
|
||||
jobId,
|
||||
jobTitle: result.jobTitle,
|
||||
salary: result.salary,
|
||||
location: result.location,
|
||||
companyName: result.companyName,
|
||||
education: result.education,
|
||||
experience: result.experience
|
||||
});
|
||||
|
||||
// 生成岗位卡片HTML,注意:微信小程序rich-text组件只支持部分HTML属性
|
||||
// 使用普通的href属性,微信小程序rich-text会将其转换为可点击链接
|
||||
// 添加data-job-id属性,方便获取jobId
|
||||
// 为所有平台添加onclick事件,微信小程序可能会忽略,但H5端会生效
|
||||
let domContext = `<a class="custom-card" href="/packageA/pages/post/post?jobId=${jobId}" data-job-id="${jobId}" data-jobid="${jobId}" onclick="if(typeof uni !== 'undefined'){uni.navigateTo({url: '/packageA/pages/post/post?jobId=${jobId}'});return false;}"><div class="card-title"><span class="title-text">${result.jobTitle}</span><div class="card-salary">${result.salary}</div></div><div class="card-company">${result.location}·${result.companyName}</div><div class="card-info"><div class="info-item"><div class="card-tag">${result.education}</div><div class="card-tag">${result.experience}</div></div><div class="info-item">查看详情<div class="position-nav"></div></div></div></a>`
|
||||
if (result.data) {
|
||||
jobMoreMap.set(jobId, result.data)
|
||||
domContext += `<a class="custom-more" href="/packageA/pages/moreJobs/moreJobs?jobId=${jobId}" data-job-id="${jobId}" data-jobid="${jobId}" onclick="if(typeof uni !== 'undefined'){uni.navigateTo({url: '/packageA/pages/moreJobs/moreJobs?jobId=${jobId}'});return false;}">查看更多岗位<div class="more-icon"></div></a>`
|
||||
}
|
||||
return domContext
|
||||
}
|
||||
}
|
||||
// 代码块
|
||||
let preCode = ""
|
||||
try {
|
||||
preCode = hljs.highlightAuto(str).value
|
||||
} catch (err) {
|
||||
preCode = md.utils.escapeHtml(str);
|
||||
}
|
||||
// 以换行进行分割 , 按行拆分代码
|
||||
const lines = preCode.split(/\n/).slice(0, -1);
|
||||
const html = lines
|
||||
.map((line, index) =>
|
||||
line ?
|
||||
`<li><span class="line-num" data-line="${index + 1}"></span>${line}</li>` :
|
||||
'<li></li>'
|
||||
)
|
||||
.join('');
|
||||
|
||||
// 代码复制功能
|
||||
const cacheIndex = codeDataList.length;
|
||||
codeDataList.push(str);
|
||||
return `
|
||||
<div class="code-container">
|
||||
<div class="code-header">
|
||||
<span class="lang-label">${lang || 'plaintext'}</span>
|
||||
<a class="copy-btn" data-copy-index="${cacheIndex}">复制代码</a>
|
||||
</div>
|
||||
<pre class="hljs"><code><ol>${html}</ol></code></pre>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
})
|
||||
|
||||
function extractFirstJson(text) {
|
||||
let stack = [];
|
||||
let startIndex = -1;
|
||||
let endIndex = -1;
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
const char = text[i];
|
||||
|
||||
if (char === '{') {
|
||||
if (stack.length === 0) startIndex = i; // 记录第一个 '{' 的位置
|
||||
stack.push(char);
|
||||
} else if (char === '}') {
|
||||
stack.pop();
|
||||
if (stack.length === 0) {
|
||||
endIndex = i; // 找到配对的 '}'
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startIndex !== -1 && endIndex !== -1) {
|
||||
const jsonString = text.slice(startIndex, endIndex + 1);
|
||||
try {
|
||||
const jsonObject = JSON.parse(jsonString);
|
||||
return jsonObject;
|
||||
} catch (e) {
|
||||
return null; // 如果不是有效的 JSON
|
||||
}
|
||||
}
|
||||
|
||||
return null; // 如果没有找到有效的 JSON 对象
|
||||
}
|
||||
|
||||
|
||||
function safeExtractJson(text) {
|
||||
try {
|
||||
const jsonObject = extractFirstJson(text);
|
||||
return jsonObject
|
||||
} catch (e) {
|
||||
console.error('JSON 解析失败:', e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function clearJobMoreMap() { // 切换对话清空
|
||||
jobMoreMap.clear()
|
||||
}
|
||||
|
||||
export function parseMarkdown(content) {
|
||||
if (!content) {
|
||||
return [] //处理特殊情况,比如网络异常导致的响应的 content 的值为空
|
||||
}
|
||||
|
||||
// 过滤掉<think>标签及其内容,这些是AI内部思考过程,不应该显示给用户
|
||||
// 1. 处理原始标签(支持多行)
|
||||
content = content.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 2. 处理HTML编码的标签
|
||||
content = content.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 3. 处理部分编码的标签
|
||||
content = content.replace(/<\s*think\s*>/gi, '')
|
||||
content = content.replace(/<\s*\/\s*think\s*>/gi, '')
|
||||
|
||||
codeDataList = []
|
||||
jobCardsList = [] // 清空岗位卡片列表,避免重复
|
||||
const unsafeHtml = md.render(content || '')
|
||||
|
||||
// 在markdown渲染后再次过滤,确保没有遗漏
|
||||
let filteredHtml = unsafeHtml
|
||||
// 1. 处理原始标签(支持多行)
|
||||
filteredHtml = filteredHtml.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 2. 处理HTML编码的标签
|
||||
filteredHtml = filteredHtml.replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, '')
|
||||
// 3. 处理部分编码的标签
|
||||
filteredHtml = filteredHtml.replace(/<\s*think\s*>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<\s*\/\s*think\s*>/gi, '')
|
||||
// 4. 单独处理剩余的think标签对
|
||||
filteredHtml = filteredHtml.replace(/<think>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<\/think>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<think>/gi, '')
|
||||
filteredHtml = filteredHtml.replace(/<\/think>/gi, '')
|
||||
|
||||
// 根据平台返回不同的内容格式
|
||||
// 微信小程序:返回rich-text组件支持的nodes格式
|
||||
// H5:直接返回HTML字符串,避免HTML解析错误
|
||||
if (process.env.UNI_PLATFORM === 'mp-weixin') {
|
||||
try {
|
||||
return parseHtml(filteredHtml)
|
||||
} catch (error) {
|
||||
console.error('HTML解析失败:', error)
|
||||
// 解析失败时返回空数组,避免页面崩溃
|
||||
return []
|
||||
}
|
||||
} else {
|
||||
// H5端直接返回HTML字符串
|
||||
return filteredHtml
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user