lcw
This commit is contained in:
@ -10,11 +10,11 @@ const getChildrenRoutes = (routes) => {
|
||||
routes.forEach((route) => {
|
||||
if (route.children && route.children.length > 0) {
|
||||
if (deptBizType == '23' && roleList) {
|
||||
// 在这个条件分支中也需要过滤掉/internalAuditor路由
|
||||
result.push(...route.children);
|
||||
} else {
|
||||
// console.log(route.path);
|
||||
if (route.path == '/JudgmentHome') {
|
||||
route.children.splice(6, 1);
|
||||
route.children.splice(route.children.findIndex(item => item.path == '/internalAuditor'), 1)
|
||||
result.push(...route.children);
|
||||
} else {
|
||||
result.push(...route.children);
|
||||
@ -29,15 +29,18 @@ const getChildrenRoutes = (routes) => {
|
||||
*处理脱离层级的路由
|
||||
*/
|
||||
export const filterRoutes = (routes) => {
|
||||
|
||||
//获取到所有的子集路由
|
||||
const childrenRoutes = getChildrenRoutes(routes);
|
||||
//根据子集路由进行查重操作
|
||||
return routes.filter((route) => {
|
||||
const data = routes.filter((route) => {
|
||||
//根据route在childrenRoutes中进行查重,把所有重复路由表 剔除
|
||||
return !childrenRoutes.find((childrenRoute) => {
|
||||
return childrenRoute.path === route.path;
|
||||
});
|
||||
});
|
||||
}).filter(item => item.path != '/internalAuditor')
|
||||
console.log(childrenRoutes);
|
||||
|
||||
return data
|
||||
};
|
||||
|
||||
function isNull(data) {
|
||||
@ -86,3 +89,5 @@ export function generateMenus(routes, basePath = "") {
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
171
src/utils/sse.js
Normal file
171
src/utils/sse.js
Normal file
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* SSE (Server-Sent Events) 工具函数
|
||||
* 用于处理服务器发送的事件流
|
||||
*/
|
||||
|
||||
// SSE连接状态管理
|
||||
const sseState = {
|
||||
isStreaming: false,
|
||||
controller: null
|
||||
};
|
||||
|
||||
/**
|
||||
* 关闭SSE连接
|
||||
* 清理连接资源并重置状态
|
||||
*/
|
||||
const closeSSEConnection = () => {
|
||||
if (sseState.controller) {
|
||||
sseState.controller.abort();
|
||||
sseState.controller = null;
|
||||
}
|
||||
sseState.isStreaming = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 使用POST方法建立SSE流式连接
|
||||
* @param {string} prompt - 发送给AI的提示词
|
||||
* @param {Object} options - 可选配置项
|
||||
* @param {string} options.url - SSE请求的URL,默认为'/mosty-api/mosty-gsxt/ai/stream/qa'
|
||||
* @param {Function} options.onChunk - 每收到一个数据块时的回调函数
|
||||
* @param {Function} options.onComplete - 连接完成时的回调函数
|
||||
* @param {Function} options.onError - 连接错误时的回调函数
|
||||
* @returns {Promise} 返回Promise,连接成功或失败时resolve/reject
|
||||
*
|
||||
* 功能说明:
|
||||
* 1. 关闭之前的连接(如果有)
|
||||
* 2. 使用fetch API发送POST请求
|
||||
* 3. 通过ReadableStream的reader逐块读取响应数据
|
||||
* 4. 使用TextDecoder解码二进制数据
|
||||
* 5. 按行解析JSON数据并处理
|
||||
* 6. 支持[DONE]标记作为结束信号
|
||||
*/
|
||||
const connectSSEWithPost = (prompt, options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 关闭之前的连接
|
||||
closeSSEConnection();
|
||||
//http://localhost:3000/api/stream
|
||||
// 默认配置
|
||||
const {
|
||||
url = '/mosty-api/mosty-gsxt/ai/stream/qa',
|
||||
onChunk,
|
||||
onComplete,
|
||||
onError
|
||||
} = options;
|
||||
|
||||
// 创建AbortController用于取消请求
|
||||
sseState.controller = new AbortController();
|
||||
const { signal } = sseState.controller;
|
||||
|
||||
// 发送POST请求
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
prompt: prompt
|
||||
}),
|
||||
signal
|
||||
}).then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
// 获取响应体的读取器
|
||||
const reader = response.body.getReader();
|
||||
// 创建文本解码器,用于解码二进制数据
|
||||
const decoder = new TextDecoder();
|
||||
sseState.isStreaming = true;
|
||||
|
||||
/**
|
||||
* 读取流式数据的内部函数
|
||||
* 循环读取数据块,直到流结束
|
||||
*/
|
||||
const readStream = async () => {
|
||||
try {
|
||||
while (true) {
|
||||
// 读取下一个数据块
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
closeSSEConnection();
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
// 解码数据块并按行分割
|
||||
const chunk = decoder.decode(value, { stream: true });
|
||||
const lines = chunk.split('\n');
|
||||
// 逐行处理数据
|
||||
for (const line of lines) {
|
||||
// 跳过空行
|
||||
if (line.trim() === '') continue;
|
||||
// 检查结束标记
|
||||
if (line.trim() === '[DONE]') {
|
||||
closeSSEConnection();
|
||||
if (onComplete) {
|
||||
onComplete();
|
||||
}
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let cleanLine = line;
|
||||
if (line.startsWith('data:')) {
|
||||
cleanLine = line.substring(5).trim(); // "data:" 长度为 5
|
||||
}
|
||||
// 尝试解析JSON数据
|
||||
const jsonData = JSON.parse(cleanLine);
|
||||
let data;
|
||||
if (typeof jsonData === 'string') {
|
||||
data = JSON.parse(jsonData);
|
||||
} else {
|
||||
data = jsonData;
|
||||
}
|
||||
// 提取content值
|
||||
const content = data.choices && data.choices[0] && data.choices[0].delta && data.choices[0].delta.content;
|
||||
if (content && onChunk) {
|
||||
onChunk(content);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('解析SSE数据失败:', e);
|
||||
console.log('原始数据:', line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('流式读取错误:', error);
|
||||
closeSSEConnection();
|
||||
if (onError) {
|
||||
onError(error);
|
||||
}
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
|
||||
readStream();
|
||||
}).catch(error => {
|
||||
console.error('SSE请求错误:', error);
|
||||
closeSSEConnection();
|
||||
if (onError) {
|
||||
onError(error);
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查当前是否正在流式传输
|
||||
* @returns {boolean} 是否正在流式传输
|
||||
*/
|
||||
const isSSEStreaming = () => {
|
||||
return sseState.isStreaming;
|
||||
};
|
||||
|
||||
export {
|
||||
connectSSEWithPost,
|
||||
closeSSEConnection,
|
||||
isSSEStreaming
|
||||
};
|
||||
@ -103,6 +103,9 @@ export function timeValidate(date, type) {
|
||||
if (type == 'td') {
|
||||
return `${yyyy}年${MM}月${dd}日`
|
||||
}
|
||||
if (type == 'ny') {
|
||||
return `${yyyy}年${MM}月`
|
||||
}
|
||||
if (type == 'yd') {
|
||||
return `${yyyy}`
|
||||
}
|
||||
@ -133,18 +136,29 @@ export function timeSlotChange(val) {
|
||||
switch (val) {
|
||||
case '天':
|
||||
case '日':
|
||||
startTime = timeValidate(new Date(), 'ymd')
|
||||
endTime = timeValidate(new Date(), 'ymd')
|
||||
// 设置当天的开始时间(00:00:00)
|
||||
const startDate = new Date();
|
||||
startDate.setHours(0, 0, 0, 0);
|
||||
startTime = timeValidate(startDate, 'ymd');
|
||||
|
||||
// 设置当天的结束时间(23:59:59)
|
||||
const endDate = new Date();
|
||||
endDate.setHours(23, 59, 59, 999);
|
||||
endTime = timeValidate(endDate, 'ymd');
|
||||
console.log(startTime, endTime);
|
||||
|
||||
break;
|
||||
case "本周":
|
||||
case "周":
|
||||
startTime = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek)
|
||||
endTime = new Date(nowYear, nowMonth, nowDay + 6 - nowDayOfWeek)
|
||||
|
||||
break;
|
||||
case "本月":
|
||||
case "月":
|
||||
startTime = new Date(nowYear, nowMonth, 1)
|
||||
endTime = new Date(nowYear, nowMonth + 1, 0)
|
||||
console.log(startTime, endTime);
|
||||
break;
|
||||
case "本季度":
|
||||
case "季度":
|
||||
@ -378,11 +392,16 @@ export const bqYs = (val) => {
|
||||
/** 全息档案跳转
|
||||
* @param {string} szhm 身证号
|
||||
*/
|
||||
export function holographicProfileJump(szhm) {
|
||||
if (!szhm) return
|
||||
window.open(`https://tyyy.lz.dsj.xz/profile/people/person-manage?sfzhm=${szhm}&from=portal`)
|
||||
export function holographicProfileJump(lx, val) {
|
||||
if (!val) return
|
||||
if (lx == 1 || !lx) {
|
||||
const sfzh = val.sfzh || val.rysfzh || val.yjRysfzh
|
||||
window.open(`https://tyyy.lz.dsj.xz/profile/people/person-manage?sfzhm=${sfzh}&from=portal`)
|
||||
} else {
|
||||
const cph = val.cph || val.yjClcph
|
||||
window.open(`https://tyyy.lz.dsj.xz/profile/car/car-manage?cphm=${cph}&from=portal`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表单验证错误信息
|
||||
* @param fields 表单验证错误信息
|
||||
|
||||
Reference in New Issue
Block a user