sdsds
This commit is contained in:
parent
2274c0df86
commit
48f566a560
157
api/drugOcr.js
Normal file
157
api/drugOcr.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
export const getOcr = (url) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
wx.request({
|
||||||
|
url: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
|
||||||
|
method: 'POST',
|
||||||
|
dataType: 'json', // 微信官方文档中介绍会对数据进行一次JSON.parse
|
||||||
|
header: {
|
||||||
|
'Authorization': 'Bearer sk-52414b887aee47e4883caf16cbf801bd',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
"model": "qwen-vl-ocr-latest",
|
||||||
|
"messages": [{
|
||||||
|
"role": "user",
|
||||||
|
"content": [{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {
|
||||||
|
"url": url
|
||||||
|
},
|
||||||
|
"min_pixels": 3136,
|
||||||
|
"max_pixels": 6422528
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "要求准确无误的提取上述关键信息、不要遗漏和捏造虚假信息,模糊或者强光遮挡的单个文字可以用英文问号?代替。返回数据格式以MD方式输出"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
success(res) {
|
||||||
|
let data = parseOcrResult(res.data.choices[0].message.content)
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
|
|
||||||
|
resolve(data);
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.log(err)
|
||||||
|
// 断网、服务器挂了都会fail回调,直接reject即可
|
||||||
|
reject(err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseMarkdownTable(md) {
|
||||||
|
// 拆分行,去掉空行
|
||||||
|
const lines = md.split('\n').filter(line => line.trim().length > 0);
|
||||||
|
|
||||||
|
// 找到表头和数据行
|
||||||
|
const headerLine = lines[0];
|
||||||
|
// 保留空单元格
|
||||||
|
const header = headerLine.split('|').map(h => h.trim());
|
||||||
|
|
||||||
|
// 数据行从第三行开始(第二行为分隔符)
|
||||||
|
const dataLines = lines.slice(2);
|
||||||
|
|
||||||
|
// 解析每一行
|
||||||
|
const result = dataLines.map(line => {
|
||||||
|
// 保留空单元格
|
||||||
|
const cells = line.split('|').map(cell => cell.trim());
|
||||||
|
const obj = {};
|
||||||
|
header.forEach((key, idx) => {
|
||||||
|
// 这里 key 可能是空字符串,需跳过
|
||||||
|
if (key) obj[key] = cells[idx] || '';
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析类似 ```json ... ``` 格式的字符串,提取检测项目数组
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {Array<Object>}
|
||||||
|
*/
|
||||||
|
function parseJsonBlock(str) {
|
||||||
|
// 去除包裹的代码块标记
|
||||||
|
const jsonStr = str.replace(/^[\s`]*```json[\s`]*|```$/g, '').replace(/↵/g, '\n').trim();
|
||||||
|
|
||||||
|
// 用正则提取所有 "key": "value"
|
||||||
|
const regex = /"([^"]+)":\s*"([^"]*)"/g;
|
||||||
|
const pairs = [];
|
||||||
|
let match;
|
||||||
|
while ((match = regex.exec(jsonStr)) !== null) {
|
||||||
|
pairs.push([match[1], match[2]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按“序号”分组
|
||||||
|
const items = [];
|
||||||
|
let current = {};
|
||||||
|
const itemFields = ['序号', '项目名称', '缩写', '结果', '单位', '参考区间', '测定方法'];
|
||||||
|
pairs.forEach(([key, value]) => {
|
||||||
|
if (key === '序号' && Object.keys(current).length > 0) {
|
||||||
|
items.push({ ...current });
|
||||||
|
current = {};
|
||||||
|
}
|
||||||
|
if (itemFields.includes(key)) {
|
||||||
|
current[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (Object.keys(current).length > 0) {
|
||||||
|
items.push({ ...current });
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动判断OCR返回内容格式并调用对应解析方法
|
||||||
|
* @param {string} content
|
||||||
|
* @returns {Array<Object>}
|
||||||
|
*/
|
||||||
|
function parseOcrResult(content) {
|
||||||
|
// 判断是否为JSON代码块
|
||||||
|
if (/^```json/.test(content.trim())) {
|
||||||
|
return parseJsonBlock(content);
|
||||||
|
}
|
||||||
|
// 判断是否为Markdown表格(以|开头,且有---分隔行)
|
||||||
|
if (/\|.*\|/.test(content) && /\|[\s\-:|]+\|/.test(content)) {
|
||||||
|
return parseMarkdownTable(content);
|
||||||
|
}
|
||||||
|
// 判断是否为实验室结果格式(数字+中文+数字+单位+参考区间)
|
||||||
|
if (/^\d+[\u4e00-\u9fa5A-Za-z]+[\d.]+[a-zA-Zμ\/]+[\d.\-]+/m.test(content.replace(/↵/g, '\n'))) {
|
||||||
|
return parseLabResults(content);
|
||||||
|
}
|
||||||
|
// 其它情况返回空数组或原始内容
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析实验室结果字符串为结构化对象数组
|
||||||
|
* @param {string} str - 原始字符串
|
||||||
|
* @returns {Array} 结构化结果数组
|
||||||
|
*/
|
||||||
|
function parseLabResults(str) {
|
||||||
|
if (!str) return [];
|
||||||
|
// 替换特殊换行符为标准换行
|
||||||
|
str = str.replace(/↵/g, '\n');
|
||||||
|
const lines = str.split(/\n+/).filter(Boolean);
|
||||||
|
const result = [];
|
||||||
|
const regex = /^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/;
|
||||||
|
lines.forEach(line => {
|
||||||
|
// 尝试用正则提取
|
||||||
|
const match = line.match(/^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/);
|
||||||
|
if (match) {
|
||||||
|
result.push({
|
||||||
|
index: Number(match[1]),
|
||||||
|
name: match[2],
|
||||||
|
value: Number(match[3]),
|
||||||
|
unit: match[4] || '',
|
||||||
|
reference: match[5] || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
114
api/ocr.js
114
api/ocr.js
@ -28,7 +28,78 @@ export const getOcr = (url) => {
|
|||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
success(res) {
|
success(res) {
|
||||||
const data = parseOcrResult(res.data.choices[0].message.content)
|
let data = parseOcrResult(res.data.choices[0].message.content)
|
||||||
|
// 新增:统一字段名
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
data = data.map(item => {
|
||||||
|
const newItem = { ...item };
|
||||||
|
if ('项目' in newItem) {
|
||||||
|
newItem.name = newItem['项目'];
|
||||||
|
delete newItem['项目'];
|
||||||
|
} else if ('项目名称' in newItem) {
|
||||||
|
newItem.name = newItem['项目名称'];
|
||||||
|
delete newItem['项目名称'];
|
||||||
|
} else if ('检验项目' in newItem) {
|
||||||
|
newItem.name = newItem['检验项目'];
|
||||||
|
delete newItem['检验项目'];
|
||||||
|
} else if ('检查项目' in newItem) {
|
||||||
|
newItem.name = newItem['检查项目'];
|
||||||
|
delete newItem['检查项目'];
|
||||||
|
} else if ('检查项目名称' in newItem) {
|
||||||
|
newItem.name = newItem['检查项目名称'];
|
||||||
|
delete newItem['检查项目名称'];
|
||||||
|
} else if ('项目全称' in newItem) {
|
||||||
|
newItem.name = newItem['项目全称'];
|
||||||
|
delete newItem['项目全称'];
|
||||||
|
} else if ('中文名称' in newItem) {
|
||||||
|
newItem.name = newItem['中文名称'];
|
||||||
|
delete newItem['中文名称'];
|
||||||
|
} else if ('分析项目' in newItem) {
|
||||||
|
newItem.name = newItem['分析项目'];
|
||||||
|
delete newItem['分析项目'];
|
||||||
|
} else if ('实验名称' in newItem) {
|
||||||
|
newItem.name = newItem['实验名称'];
|
||||||
|
delete newItem['实验名称'];
|
||||||
|
} else if ('N项目名称' in newItem) {
|
||||||
|
newItem.name = newItem['N项目名称'];
|
||||||
|
delete newItem['N项目名称'];
|
||||||
|
}else if ('序号检查项目' in newItem) {
|
||||||
|
newItem.name = newItem['序号检查项目'];
|
||||||
|
delete newItem['序号检查项目'];
|
||||||
|
}
|
||||||
|
if ('结果' in newItem) {
|
||||||
|
newItem.value = newItem['结果'];
|
||||||
|
delete newItem['结果'];
|
||||||
|
} else if ('值' in newItem) {
|
||||||
|
newItem.value = newItem['值'];
|
||||||
|
delete newItem['值'];
|
||||||
|
} else if ('检验结果' in newItem) {
|
||||||
|
newItem.value = newItem['检验结果'];
|
||||||
|
delete newItem['检验结果'];
|
||||||
|
} else if ('检查结果' in newItem) {
|
||||||
|
newItem.value = newItem['检查结果'];
|
||||||
|
delete newItem['检查结果'];
|
||||||
|
} else if ('结果值' in newItem) {
|
||||||
|
newItem.value = newItem['结果值'];
|
||||||
|
delete newItem['结果值'];
|
||||||
|
} else if ('结果浓度' in newItem) {
|
||||||
|
newItem.value = newItem['结果浓度'];
|
||||||
|
delete newItem['结果浓度'];
|
||||||
|
} else if ('测定结果' in newItem) {
|
||||||
|
newItem.value = newItem['测定结果'];
|
||||||
|
delete newItem['测定结果'];
|
||||||
|
} else if ('检验值' in newItem) {
|
||||||
|
newItem.value = newItem['检验值'];
|
||||||
|
delete newItem['检验值'];
|
||||||
|
}
|
||||||
|
// 去掉name中的括号及其内容
|
||||||
|
if (typeof newItem.name === 'string') {
|
||||||
|
newItem.name = newItem.name.replace(/(.*?)|\(.*?\)/g, '').trim();
|
||||||
|
}
|
||||||
|
console.log(newItem)
|
||||||
|
return newItem;
|
||||||
|
});
|
||||||
|
}
|
||||||
resolve(data);
|
resolve(data);
|
||||||
},
|
},
|
||||||
fail(err) {
|
fail(err) {
|
||||||
@ -46,17 +117,20 @@ function parseMarkdownTable(md) {
|
|||||||
|
|
||||||
// 找到表头和数据行
|
// 找到表头和数据行
|
||||||
const headerLine = lines[0];
|
const headerLine = lines[0];
|
||||||
const header = headerLine.split('|').map(h => h.trim()).filter(Boolean);
|
// 保留空单元格
|
||||||
|
const header = headerLine.split('|').map(h => h.trim());
|
||||||
|
|
||||||
// 数据行从第三行开始(第二行为分隔符)
|
// 数据行从第三行开始(第二行为分隔符)
|
||||||
const dataLines = lines.slice(2);
|
const dataLines = lines.slice(2);
|
||||||
|
|
||||||
// 解析每一行
|
// 解析每一行
|
||||||
const result = dataLines.map(line => {
|
const result = dataLines.map(line => {
|
||||||
const cells = line.split('|').map(cell => cell.trim()).filter(Boolean);
|
// 保留空单元格
|
||||||
|
const cells = line.split('|').map(cell => cell.trim());
|
||||||
const obj = {};
|
const obj = {};
|
||||||
header.forEach((key, idx) => {
|
header.forEach((key, idx) => {
|
||||||
obj[key] = cells[idx];
|
// 这里 key 可能是空字符串,需跳过
|
||||||
|
if (key) obj[key] = cells[idx] || '';
|
||||||
});
|
});
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
@ -114,6 +188,38 @@ function parseOcrResult(content) {
|
|||||||
if (/\|.*\|/.test(content) && /\|[\s\-:|]+\|/.test(content)) {
|
if (/\|.*\|/.test(content) && /\|[\s\-:|]+\|/.test(content)) {
|
||||||
return parseMarkdownTable(content);
|
return parseMarkdownTable(content);
|
||||||
}
|
}
|
||||||
|
// 判断是否为实验室结果格式(数字+中文+数字+单位+参考区间)
|
||||||
|
if (/^\d+[\u4e00-\u9fa5A-Za-z]+[\d.]+[a-zA-Zμ\/]+[\d.\-]+/m.test(content.replace(/↵/g, '\n'))) {
|
||||||
|
return parseLabResults(content);
|
||||||
|
}
|
||||||
// 其它情况返回空数组或原始内容
|
// 其它情况返回空数组或原始内容
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析实验室结果字符串为结构化对象数组
|
||||||
|
* @param {string} str - 原始字符串
|
||||||
|
* @returns {Array} 结构化结果数组
|
||||||
|
*/
|
||||||
|
function parseLabResults(str) {
|
||||||
|
if (!str) return [];
|
||||||
|
// 替换特殊换行符为标准换行
|
||||||
|
str = str.replace(/↵/g, '\n');
|
||||||
|
const lines = str.split(/\n+/).filter(Boolean);
|
||||||
|
const result = [];
|
||||||
|
const regex = /^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/;
|
||||||
|
lines.forEach(line => {
|
||||||
|
// 尝试用正则提取
|
||||||
|
const match = line.match(/^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/);
|
||||||
|
if (match) {
|
||||||
|
result.push({
|
||||||
|
index: Number(match[1]),
|
||||||
|
name: match[2],
|
||||||
|
value: Number(match[3]),
|
||||||
|
unit: match[4] || '',
|
||||||
|
reference: match[5] || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import request from '~/api/request';
|
import request from '~/api/request';
|
||||||
|
import { getOcr } from '~/api/drugOcr';
|
||||||
|
|
||||||
let modeType = '';
|
let modeType = '';
|
||||||
let mode2 = '';
|
let mode2 = '';
|
||||||
@ -364,7 +365,9 @@ Page({
|
|||||||
this.setData({
|
this.setData({
|
||||||
imageFile: data
|
imageFile: data
|
||||||
})
|
})
|
||||||
|
getOcr(data).then(res => {
|
||||||
|
|
||||||
|
})
|
||||||
console.log('上传成功:', data); // 输出上传成功后的数据
|
console.log('上传成功:', data); // 输出上传成功后的数据
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -40,8 +40,8 @@ Page({
|
|||||||
},
|
},
|
||||||
mode: '',
|
mode: '',
|
||||||
dateVisible: false,
|
dateVisible: false,
|
||||||
date: new Date('2021-12-23').getTime(), // 支持时间戳传入
|
|
||||||
dateText: '',
|
dateText: '',
|
||||||
|
startTimePicker: String(new Date().getFullYear()),
|
||||||
filter(type, options) {
|
filter(type, options) {
|
||||||
if (type === 'year') {
|
if (type === 'year') {
|
||||||
return options.sort((a, b) => b.value - a.value);
|
return options.sort((a, b) => b.value - a.value);
|
||||||
@ -346,7 +346,6 @@ Page({
|
|||||||
handleImagePreview(e) {
|
handleImagePreview(e) {
|
||||||
const { mode, index } = e.currentTarget.dataset;
|
const { mode, index } = e.currentTarget.dataset;
|
||||||
this.imageKey = mode
|
this.imageKey = mode
|
||||||
console.log(this.data.form[mode])
|
|
||||||
this.setData({
|
this.setData({
|
||||||
imageList: this.data.form[mode],
|
imageList: this.data.form[mode],
|
||||||
imageIndex: index,
|
imageIndex: index,
|
||||||
@ -368,7 +367,6 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onDelete(e) {
|
onDelete(e) {
|
||||||
console.log(e)
|
|
||||||
let arr = this.data.form[this.imageKey]
|
let arr = this.data.form[this.imageKey]
|
||||||
arr.splice(e.detail.index, 1)
|
arr.splice(e.detail.index, 1)
|
||||||
// let imageList = this.data.imageList
|
// let imageList = this.data.imageList
|
||||||
@ -391,7 +389,6 @@ Page({
|
|||||||
['form.follow_name']: options.name,
|
['form.follow_name']: options.name,
|
||||||
['form.follow_date']: options.time
|
['form.follow_date']: options.time
|
||||||
})
|
})
|
||||||
console.log(options)
|
|
||||||
if (options.questionnaire_id != 0) {
|
if (options.questionnaire_id != 0) {
|
||||||
this.getDetail()
|
this.getDetail()
|
||||||
}
|
}
|
||||||
@ -414,63 +411,233 @@ Page({
|
|||||||
|
|
||||||
// 遍历识别结果,填充字段
|
// 遍历识别结果,填充字段
|
||||||
setFormData(ocrs, mode) {
|
setFormData(ocrs, mode) {
|
||||||
console.log(ocrs, mode)
|
|
||||||
ocrs.forEach(ocr => {
|
ocrs.forEach(ocr => {
|
||||||
console.log(ocr['项目名称'], ocr['结果'])
|
|
||||||
// 血常规
|
// 血常规
|
||||||
if (mode == 'blood_routine_image') {
|
if (mode == 'blood_routine_image') {
|
||||||
if (ocr['项目名称'] == '血红蛋白') {
|
if (ocr.name == '血红蛋白') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.hemoglobin`]: ocr['结果']
|
[`form.hemoglobin`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '血小板') {
|
||||||
|
this.setData({
|
||||||
|
[`form.platelets`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '白细胞') {
|
||||||
|
this.setData({
|
||||||
|
[`form.white_blood_cells`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 凝血功能
|
// 凝血功能
|
||||||
if (mode == 'coagulation_function_image') {
|
if (mode == 'coagulation_function_image') {
|
||||||
|
if (ocr.name == 'C-反应蛋白' || ocr.name == 'c-反应蛋白' || ocr.name == 'CRP') {
|
||||||
if (ocr['项目名称'] == '凝血酶原时间') {
|
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.pt`]: ocr['结果']
|
[`form.crp`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr['项目名称'] == '凝血酶原活动度') {
|
if (ocr.name == 'DDR' || ocr.name == 'ddr') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.pta`]: ocr['结果']
|
[`form.ddr`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr['项目名称'] == '国际标准化比值') {
|
if (ocr.name == '凝血酶原时间' || ocr.name == 'Pt') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.inr`]: ocr['结果']
|
[`form.pt`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr['项目名称'] == '活化部分凝血活酶时间') {
|
if (ocr.name == '凝血酶原活动度' || ocr.name == 'Pt-a' || ocr.name == 'PtA') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.aptt`]: ocr['结果']
|
[`form.pta`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr['项目名称'] == '凝血酶时间') {
|
if (ocr.name == '国际标准化比值' || ocr.name == 'INR') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.tt`]: ocr['结果']
|
[`form.inr`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr['项目名称'] == '纤维蛋白原') {
|
if (ocr.name == '活化部分凝血活酶时间' || ocr.name == 'APTT') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.fib`]: ocr['结果']
|
[`form.aptt`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '凝血酶时间' || ocr.name == 'TT') {
|
||||||
|
this.setData({
|
||||||
|
[`form.tt`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '纤维蛋白原' || ocr.name == 'FIB') {
|
||||||
|
this.setData({
|
||||||
|
[`form.fib`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == 'NPDP' || ocr.name == 'npdp') {
|
||||||
|
this.setData({
|
||||||
|
[`form.npdp`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == 'MMP-7' || ocr.name == 'MMP7' || ocr.name == '基质金属蛋白酶-7') {
|
||||||
|
this.setData({
|
||||||
|
[`form.mmp_7`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 肝功能
|
// 肝功能
|
||||||
if (mode == 'liver_function_image') {
|
if (mode == 'liver_function_image') {
|
||||||
|
if (ocr.name == '总胆红素') {
|
||||||
|
this.setData({
|
||||||
|
[`form.total_bilirubin`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '直接胆红素') {
|
||||||
|
this.setData({
|
||||||
|
[`form.direct_bilirubin`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '总胆汁酸') {
|
||||||
|
this.setData({
|
||||||
|
[`form.total_bile_acid`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '白蛋白') {
|
||||||
|
this.setData({
|
||||||
|
[`form.albumin`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '谷草' || ocr.name == '谷草转氨酶') {
|
||||||
|
this.setData({
|
||||||
|
[`form.grain_grass`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '谷丙' || ocr.name == '谷丙转氨酶') {
|
||||||
|
this.setData({
|
||||||
|
[`form.gu_bing`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == 'γ-谷氨酰转肽酶' || ocr.name == '谷氨酰转肽酶') {
|
||||||
|
this.setData({
|
||||||
|
[`form.ggt`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ocr.name == '碱性磷酸酶') {
|
||||||
|
this.setData({
|
||||||
|
[`form.alp`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 营养指数
|
// 营养指数
|
||||||
if (mode == 'nutritional_indicator_image') {
|
if (mode == 'nutritional_indicator_image') {
|
||||||
|
if (ocr.name == '25-羟基维生素D3' || ocr.name == '25-OH-Vitamin D3' || ocr.name == '25(OH)D3') {
|
||||||
|
this.setData({
|
||||||
|
[`form.oh_d3`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '25-羟基维生素D2' || ocr.name == '25-OH-Vitamin D2' || ocr.name == '25(OH)D2') {
|
||||||
|
this.setData({
|
||||||
|
[`form.oh_d2`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '25-羟基维生素D' || ocr.name == '25-OH-Vitamin D' || ocr.name == '25(OH)D') {
|
||||||
|
this.setData({
|
||||||
|
[`form.oh_d`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '维生素A' || ocr.name == '维生素a' || ocr.name == 'vitamin a' || ocr.name == 'vit A') {
|
||||||
|
this.setData({
|
||||||
|
[`form.vitamin_a`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '维生素K' || ocr.name == '维生素k' || ocr.name == 'vitamin k' || ocr.name == 'vit K') {
|
||||||
|
this.setData({
|
||||||
|
[`form.vitamin_k`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (ocr.name == '维生素E' || ocr.name == '维生素e' || ocr.name == 'vitamin e' || ocr.name == 'vit E') {
|
||||||
|
this.setData({
|
||||||
|
[`form.vitamin_e`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// B超
|
// B超
|
||||||
if (mode == 'b_mode_image') {
|
if (mode == 'b_mode_image') {
|
||||||
|
if(ocr.name == '肝肋下'){
|
||||||
|
this.setData({
|
||||||
|
[`form.under_the_liver_rib`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '肝剑突下'){
|
||||||
|
this.setData({
|
||||||
|
[`form.under_the_xiphoid_liver`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '脾肋下'){
|
||||||
|
this.setData({
|
||||||
|
[`form.spleen_rib_area`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '门静脉主干内径'){
|
||||||
|
this.setData({
|
||||||
|
[`form.main_portal_vein`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '肝回声'){
|
||||||
|
this.setData({
|
||||||
|
[`form.liver_echo`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '胆囊大小'){
|
||||||
|
this.setData({
|
||||||
|
[`form.gallbladder_size`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '胆总管'){
|
||||||
|
this.setData({
|
||||||
|
[`form.common_bile_duct`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '纤维块大小'){
|
||||||
|
this.setData({
|
||||||
|
[`form.fiber_block_size`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '门静脉流速' || ocr.name == 'PVV' || ocr.name == 'PVV流速' || ocr.name == 'pvv'){
|
||||||
|
this.setData({
|
||||||
|
[`form.pvv`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '肝弹性值'){
|
||||||
|
this.setData({
|
||||||
|
[`form.liver_elasticity_value`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '有无肝囊肿'){
|
||||||
|
this.setData({
|
||||||
|
[`form.is_have_cyst`]: ocr.value == '无' ? '2' : '1'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '有无腹水'){
|
||||||
|
this.setData({
|
||||||
|
[`form.is_have_ascites`]: ocr.value == '无' ? '2' : '1'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '弹性成像最小值'){
|
||||||
|
this.setData({
|
||||||
|
[`form.elastography_minimum`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '弹性成像最大值'){
|
||||||
|
this.setData({
|
||||||
|
[`form.elastography_maximum`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if(ocr.name == '弹性成像中位数'){
|
||||||
|
this.setData({
|
||||||
|
[`form.elastography_median`]: ocr.value
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@ -536,7 +536,7 @@
|
|||||||
<view class="dark">
|
<view class="dark">
|
||||||
<view class="input-example">
|
<view class="input-example">
|
||||||
<view class="input-example__label">弹性成像最小值(kPa)</view>
|
<view class="input-example__label">弹性成像最小值(kPa)</view>
|
||||||
<t-input type="digit" placeholder="请输入" bind:change="onInput" value="{{form.elastography_median}}" data-key="elastography_median" borderless="{{true}}" style="{{style}}" />
|
<t-input type="digit" placeholder="请输入" bind:change="onInput" value="{{form.elastography_minimum}}" data-key="elastography_median" borderless="{{true}}" style="{{style}}" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</t-col>
|
</t-col>
|
||||||
@ -588,6 +588,6 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<t-button bindtap="clockIn" theme="primary" block bindtap="toQuestionnaire">提交</t-button>
|
<t-button bindtap="clockIn" theme="primary" block bindtap="toQuestionnaire">提交</t-button>
|
||||||
<t-date-time-picker auto-close bind:cancel="hidePicker" bind:change="onPickerChange" cancelBtn="取消" confirmBtn="确认" data-mode="birth" defaultValue="{{personInfo.birth}}" end="{{birthEnd}}" filter="{{birthFilter}}" format="YYYY-MM-DD" mode="date" popup-props="{{ { usingCustomNavbar: true } }}" start="{{birthStart}}" title="选择期日" value="{{personInfo.birth}}" visible="{{birthVisible}}" />
|
<t-date-time-picker auto-close bind:cancel="hidePicker" bind:change="onPickerChange" cancelBtn="取消" confirmBtn="确认" data-mode="birth" defaultValue="{{personInfo.birth}}" end="{{birthEnd}}" filter="{{birthFilter}}" format="YYYY-MM-DD" mode="date" popup-props="{{ { usingCustomNavbar: true } }}" start="{{startTimePicker}}" title="选择日期" value="{{personInfo.birth}}" visible="{{birthVisible}}" />
|
||||||
<t-image-viewer usingCustomNavbar deleteBtn="{{false}}" closeBtn="{{true}}" showIndex="{{true}}" initial-index="{{imageIndex}}" visible="{{imageVisible}}" images="{{imageList}}" bind:change="onChange" bind:delete="onDelete" bind:close="onClose"></t-image-viewer>
|
<t-image-viewer usingCustomNavbar deleteBtn="{{false}}" closeBtn="{{true}}" showIndex="{{true}}" initial-index="{{imageIndex}}" visible="{{imageVisible}}" images="{{imageList}}" bind:change="onChange" bind:delete="onDelete" bind:close="onClose"></t-image-viewer>
|
||||||
</view>
|
</view>
|
||||||
@ -241,7 +241,7 @@ Page({
|
|||||||
canvas.setChart(chart);
|
canvas.setChart(chart);
|
||||||
chart.setOption({
|
chart.setOption({
|
||||||
title: { text: '', left: 'left', fontSize: 6 },
|
title: { text: '', left: 'left', fontSize: 6 },
|
||||||
grid: { containLabel: true, top: '5%', left: '5%', right: '5%', bottom: '3%' },
|
grid: { containLabel: true, top: '5%', left: '5%', right: '7%', bottom: '3%' },
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: true,
|
show: true,
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
@ -311,7 +311,7 @@ Page({
|
|||||||
canvas.setChart(chart);
|
canvas.setChart(chart);
|
||||||
chart.setOption({
|
chart.setOption({
|
||||||
title: { text: '', left: 'left', fontSize: 6 },
|
title: { text: '', left: 'left', fontSize: 6 },
|
||||||
grid: { containLabel: true, top: '5%', left: '5%', right: '5%', bottom: '3%' },
|
grid: { containLabel: true, top: '5%', left: '5%', right: '7%', bottom: '3%' },
|
||||||
tooltip: {
|
tooltip: {
|
||||||
show: true,
|
show: true,
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
|
|||||||
@ -225,6 +225,9 @@
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.item-content-canvas{
|
||||||
|
padding-right: 10rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.item-content-1{
|
.item-content-1{
|
||||||
background: linear-gradient( 180deg, #EDF3F8 0%, #F7FAFC 100%);
|
background: linear-gradient( 180deg, #EDF3F8 0%, #F7FAFC 100%);
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<view class="item-title">
|
<view class="item-title">
|
||||||
<image class="item-title-icon" src="https://image-fudan.oss-cn-beijing.aliyuncs.com/mini_images/home/icon_1.svg"></image>
|
<image class="item-title-icon" src="https://image-fudan.oss-cn-beijing.aliyuncs.com/mini_images/home/icon_1.svg"></image>
|
||||||
宝宝生长曲线</view>
|
宝宝生长曲线</view>
|
||||||
<view class="item-content">
|
<view class="item-content item-content-canvas">
|
||||||
<view class="box_3">
|
<view class="box_3">
|
||||||
<view class="{{activeIndex == 0 ? 'text-wrapper_1 text-act' : 'text-wrapper_1'}}" data-index="0" bindtap="changeChart">
|
<view class="{{activeIndex == 0 ? 'text-wrapper_1 text-act' : 'text-wrapper_1'}}" data-index="0" bindtap="changeChart">
|
||||||
<text lines="1" class="text_2">身高曲线</text>
|
<text lines="1" class="text_2">身高曲线</text>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ Page({
|
|||||||
*/
|
*/
|
||||||
data: {
|
data: {
|
||||||
dataList: [],
|
dataList: [],
|
||||||
planId: '',
|
// planId: '',
|
||||||
},
|
},
|
||||||
|
|
||||||
async getList(){
|
async getList(){
|
||||||
@ -36,12 +36,12 @@ Page({
|
|||||||
this.setData({
|
this.setData({
|
||||||
dataList: processedList
|
dataList: processedList
|
||||||
})
|
})
|
||||||
const actObj = processedList.find(item => item.status === 2);
|
// const actObj = processedList.find(item => item.status === 2);
|
||||||
if (actObj) {
|
// if (actObj) {
|
||||||
this.setData({
|
// this.setData({
|
||||||
planId: actObj.id
|
// planId: actObj.id
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@ -102,7 +102,6 @@ Page({
|
|||||||
},
|
},
|
||||||
toQuestionnaire(e) {
|
toQuestionnaire(e) {
|
||||||
const { item } = e.currentTarget.dataset
|
const { item } = e.currentTarget.dataset
|
||||||
console.log(item)
|
|
||||||
wx.navigateTo({
|
wx.navigateTo({
|
||||||
url: `/pages/followUp/index?planId=${item.id}&name=${item.plan_name}&time=${item.plan_date}&questionnaire_id=${item.questionnaire_id}` ,
|
url: `/pages/followUp/index?planId=${item.id}&name=${item.plan_name}&time=${item.plan_date}&questionnaire_id=${item.questionnaire_id}` ,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="footer-example" wx:if="{{planId}}">
|
<view class="footer-example">
|
||||||
<view bindtap="goQuestionnaire" data-id="{{planId}}">
|
<view bindtap="goQuestionnaire" data-id="{{planId}}">
|
||||||
<text class="iconfont icon-zengjiatianjiajiahao"></text>
|
<text class="iconfont icon-zengjiatianjiajiahao"></text>
|
||||||
添加随访
|
添加随访
|
||||||
|
|||||||
@ -227,7 +227,7 @@
|
|||||||
border: 1px solid rgba(255,255,255,1);
|
border: 1px solid rgba(255,255,255,1);
|
||||||
padding-left: 20rpx;
|
padding-left: 20rpx;
|
||||||
// flex-direction: row;
|
// flex-direction: row;
|
||||||
width: 320rpx;
|
width: 340rpx;
|
||||||
height: 50rpx;
|
height: 50rpx;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|||||||
@ -32,7 +32,7 @@ Page({
|
|||||||
],
|
],
|
||||||
|
|
||||||
birthVisible: false,
|
birthVisible: false,
|
||||||
birthStart: '1970-01-01',
|
birthStart: '2010-01-01',
|
||||||
birthEnd: new Date().toISOString().split('T')[0],
|
birthEnd: new Date().toISOString().split('T')[0],
|
||||||
birthTime: 0,
|
birthTime: 0,
|
||||||
birthFilter: (type, options) => (type === 'year' ? options.sort((a, b) => b.value - a.value) : options),
|
birthFilter: (type, options) => (type === 'year' ? options.sort((a, b) => b.value - a.value) : options),
|
||||||
|
|||||||
@ -22,7 +22,36 @@ const getLocalUrl = (path, name) => {
|
|||||||
return tempFileName;
|
return tempFileName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析实验室结果字符串为结构化对象数组
|
||||||
|
* @param {string} str - 原始字符串
|
||||||
|
* @returns {Array} 结构化结果数组
|
||||||
|
*/
|
||||||
|
function parseLabResults(str) {
|
||||||
|
if (!str) return [];
|
||||||
|
// 替换特殊换行符为标准换行
|
||||||
|
str = str.replace(/↵/g, '\n');
|
||||||
|
const lines = str.split(/\n+/).filter(Boolean);
|
||||||
|
const result = [];
|
||||||
|
const regex = /^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/;
|
||||||
|
lines.forEach(line => {
|
||||||
|
// 尝试用正则提取
|
||||||
|
const match = line.match(/^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/);
|
||||||
|
if (match) {
|
||||||
|
result.push({
|
||||||
|
index: Number(match[1]),
|
||||||
|
name: match[2],
|
||||||
|
value: Number(match[3]),
|
||||||
|
unit: match[4] || '',
|
||||||
|
reference: match[5] || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
formatTime,
|
formatTime,
|
||||||
getLocalUrl,
|
getLocalUrl,
|
||||||
|
parseLabResults,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user