ss
This commit is contained in:
parent
48f566a560
commit
2e178c78b7
178
api/drugOcr.js
178
api/drugOcr.js
@ -22,19 +22,46 @@ export const getOcr = (url) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": "要求准确无误的提取上述关键信息、不要遗漏和捏造虚假信息,模糊或者强光遮挡的单个文字可以用英文问号?代替。返回数据格式以MD方式输出"
|
"text": "要求准确无误的提取图片中的药品名称、每次用量、每日服用次数等信息,模糊或者强光遮挡的单个文字可以用英文问号?代替,药品名称的key为'name',每次用量key为'jiliang',每日服用次数的key为'cishu',返回数据格式以JSON数组格式输出,不要将多个药品信息放到一个药品名称字段内,跟药品无关的信息不要"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
success(res) {
|
success(res) {
|
||||||
let data = parseOcrResult(res.data.choices[0].message.content)
|
let data = parseJsonBlock(res.data.choices[0].message.content)
|
||||||
console.log(data)
|
if(data.length == 0){
|
||||||
|
wx.showToast({
|
||||||
|
title: '识别失败,请重新选择照片!',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
reject('识别失败,请重新选择照片!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(data.some((item)=>{
|
||||||
|
return !item.name && item.text;
|
||||||
|
})){
|
||||||
|
let sss = extractDrugsFromOcr(data)
|
||||||
|
if(sss.length == 0){
|
||||||
|
wx.showToast({
|
||||||
|
title: '识别失败,请重新选择照片!',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
reject('识别失败!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resolve(sss);
|
||||||
|
} else {
|
||||||
resolve(data);
|
resolve(data);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fail(err) {
|
fail(err) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '识别失败,请重新选择照片!',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
console.log(err)
|
console.log(err)
|
||||||
// 断网、服务器挂了都会fail回调,直接reject即可
|
// 断网、服务器挂了都会fail回调,直接reject即可
|
||||||
reject(err);
|
reject(err);
|
||||||
@ -43,32 +70,7 @@ export const getOcr = (url) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ... ``` 格式的字符串,提取检测项目数组
|
* 解析类似 ```json ... ``` 格式的字符串,提取检测项目数组
|
||||||
@ -76,82 +78,58 @@ function parseMarkdownTable(md) {
|
|||||||
* @returns {Array<Object>}
|
* @returns {Array<Object>}
|
||||||
*/
|
*/
|
||||||
function parseJsonBlock(str) {
|
function parseJsonBlock(str) {
|
||||||
// 去除包裹的代码块标记
|
// 匹配 ```json ... ``` 或 ``` ... ```
|
||||||
const jsonStr = str.replace(/^[\s`]*```json[\s`]*|```$/g, '').replace(/↵/g, '\n').trim();
|
const match = str.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
|
||||||
|
let jsonStr = match ? match[1] : str;
|
||||||
|
jsonStr = jsonStr.trim();
|
||||||
|
|
||||||
// 用正则提取所有 "key": "value"
|
// 尝试直接解析
|
||||||
const regex = /"([^"]+)":\s*"([^"]*)"/g;
|
try {
|
||||||
const pairs = [];
|
return JSON.parse(jsonStr);
|
||||||
let match;
|
} catch (e) {
|
||||||
while ((match = regex.exec(jsonStr)) !== null) {
|
// 替换单引号包裹的 key 和 value 为双引号
|
||||||
pairs.push([match[1], match[2]]);
|
let fixedStr = jsonStr
|
||||||
}
|
// 替换 key 的单引号(允许有空格、括号等)
|
||||||
|
.replace(/'([\w\u4e00-\u9fa5\(\)\s]+)'(?=\s*:)/g, '"$1"')
|
||||||
|
// 替换 value 的单引号(允许有空格、括号等,非贪婪匹配)
|
||||||
|
.replace(/:\s*'([^']*?)'/g, ': "$1"');
|
||||||
|
try {
|
||||||
|
return JSON.parse(fixedStr);
|
||||||
|
|
||||||
// 按“序号”分组
|
} catch (e2) {
|
||||||
const items = [];
|
console.error('JSON parse error:', e2, fixedStr);
|
||||||
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 [];
|
return [];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
function extractDrugsFromOcr(ocrArray) {
|
||||||
|
// 1. 合并所有 text 字段
|
||||||
|
const lines = ocrArray.map(item => item.text.trim()).filter(Boolean);
|
||||||
|
|
||||||
|
// 2. 分组药品(以“1、”“2、”等开头)
|
||||||
|
const drugGroups = [];
|
||||||
|
let currentDrug = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析实验室结果字符串为结构化对象数组
|
|
||||||
* @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 => {
|
lines.forEach(line => {
|
||||||
// 尝试用正则提取
|
// 判断是否为新药品的开始
|
||||||
const match = line.match(/^(\d+)([\u4e00-\u9fa5A-Za-z]+)([\d.]+)([a-zA-Zμ\/]+)?([\d.\-]+)?/);
|
if (/^\d+、/.test(line)) {
|
||||||
if (match) {
|
if (currentDrug) drugGroups.push(currentDrug);
|
||||||
result.push({
|
currentDrug = { name: line.replace(/^\d+、/, '').trim(), jiliang: '', cishu: '' };
|
||||||
index: Number(match[1]),
|
} else if (currentDrug) {
|
||||||
name: match[2],
|
// 判断是否为用量
|
||||||
value: Number(match[3]),
|
if (/每次|mg|片|粒|ml|g|单位/.test(line) && !currentDrug.jiliang) {
|
||||||
unit: match[4] || '',
|
currentDrug.jiliang = line;
|
||||||
reference: match[5] || ''
|
}
|
||||||
});
|
// 判断是否为次数
|
||||||
|
else if (/每日|每天|次|早|晚|中/.test(line) && !currentDrug.cishu) {
|
||||||
|
currentDrug.cishu = line;
|
||||||
|
}
|
||||||
|
// 其他信息可根据需要扩展
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
if (currentDrug) drugGroups.push(currentDrug);
|
||||||
|
|
||||||
|
// 过滤掉无效项
|
||||||
|
return drugGroups.filter(d => d.name);
|
||||||
}
|
}
|
||||||
225
api/ocr copy.js
Normal file
225
api/ocr copy.js
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
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)
|
||||||
|
// 新增:统一字段名
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
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;
|
||||||
|
}
|
||||||
248
api/ocr.js
248
api/ocr.js
@ -22,87 +22,46 @@ export const getOcr = (url) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"text": "要求准确无误的提取上述关键信息、不要遗漏和捏造虚假信息,模糊或者强光遮挡的单个文字可以用英文问号?代替。返回数据格式以MD方式输出"
|
"text": "请只返回提取好的检查项目及其结果,格式为 JSON 数组,每个元素包含 'name' 和 'value' 两个字段。例如:[{\"name\": \"白细胞\", \"value\": \"5.2\"}]。不要返回包含 rotate_rect、text 等字段的原始 OCR 结构化表格数据。"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
success(res) {
|
success(res) {
|
||||||
let data = parseOcrResult(res.data.choices[0].message.content)
|
let data = parseJsonBlock(res.data.choices[0].message.content)
|
||||||
// 新增:统一字段名
|
if(data.length == 0){
|
||||||
if (Array.isArray(data)) {
|
wx.showToast({
|
||||||
data = data.map(item => {
|
title: '识别失败,请重新选择照片!',
|
||||||
const newItem = { ...item };
|
icon: 'none',
|
||||||
if ('项目' in newItem) {
|
duration: 2000
|
||||||
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;
|
|
||||||
});
|
});
|
||||||
|
reject('识别失败!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 判断是否为 rotate_rect 格式
|
||||||
|
if (Array.isArray(data) && data.length && data[0].rotate_rect) {
|
||||||
|
let items = extractCheckItemsFromOcrTable(data);
|
||||||
|
if(items.length==0){
|
||||||
|
wx.showToast({
|
||||||
|
title: '识别失败,请重新选择照片!',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
reject('识别失败!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resolve(items);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
resolve(data);
|
resolve(data);
|
||||||
|
|
||||||
},
|
},
|
||||||
fail(err) {
|
fail(err) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '识别失败,请重新选择照片!',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
console.log(err)
|
console.log(err)
|
||||||
// 断网、服务器挂了都会fail回调,直接reject即可
|
// 断网、服务器挂了都会fail回调,直接reject即可
|
||||||
reject(err);
|
reject(err);
|
||||||
@ -111,32 +70,7 @@ export const getOcr = (url) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ... ``` 格式的字符串,提取检测项目数组
|
* 解析类似 ```json ... ``` 格式的字符串,提取检测项目数组
|
||||||
@ -144,82 +78,62 @@ function parseMarkdownTable(md) {
|
|||||||
* @returns {Array<Object>}
|
* @returns {Array<Object>}
|
||||||
*/
|
*/
|
||||||
function parseJsonBlock(str) {
|
function parseJsonBlock(str) {
|
||||||
// 去除包裹的代码块标记
|
// 匹配 ```json ... ``` 或 ``` ... ```
|
||||||
const jsonStr = str.replace(/^[\s`]*```json[\s`]*|```$/g, '').replace(/↵/g, '\n').trim();
|
const match = str.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
|
||||||
|
let jsonStr = match ? match[1] : str;
|
||||||
|
jsonStr = jsonStr.trim();
|
||||||
|
|
||||||
// 用正则提取所有 "key": "value"
|
// 尝试直接解析
|
||||||
const regex = /"([^"]+)":\s*"([^"]*)"/g;
|
try {
|
||||||
const pairs = [];
|
return JSON.parse(jsonStr);
|
||||||
let match;
|
} catch (e) {
|
||||||
while ((match = regex.exec(jsonStr)) !== null) {
|
// 替换单引号包裹的 key 和 value 为双引号
|
||||||
pairs.push([match[1], match[2]]);
|
let fixedStr = jsonStr
|
||||||
}
|
// 替换 key 的单引号(允许有空格、括号等)
|
||||||
|
.replace(/'([\w\u4e00-\u9fa5\(\)\s]+)'(?=\s*:)/g, '"$1"')
|
||||||
|
// 替换 value 的单引号(允许有空格、括号等,非贪婪匹配)
|
||||||
|
.replace(/:\s*'([^']*?)'/g, ': "$1"');
|
||||||
|
try {
|
||||||
|
return JSON.parse(fixedStr);
|
||||||
|
|
||||||
// 按“序号”分组
|
} catch (e2) {
|
||||||
const items = [];
|
console.error('JSON parse error:', e2, fixedStr);
|
||||||
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 [];
|
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] || ''
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function extractCheckItemsFromOcrTable(ocrArray) {
|
||||||
|
// 1. 找到表头的 x 坐标
|
||||||
|
const nameHeader = ocrArray.find(item => item.text.includes('检验项目'));
|
||||||
|
const valueHeader = ocrArray.find(item => item.text.includes('结果'));
|
||||||
|
if (!nameHeader || !valueHeader) return [];
|
||||||
|
|
||||||
|
const nameX = nameHeader.rotate_rect[0];
|
||||||
|
const valueX = valueHeader.rotate_rect[0];
|
||||||
|
|
||||||
|
// 2. 过滤掉表头,按 y 坐标分组(每一行)
|
||||||
|
const rows = {};
|
||||||
|
ocrArray.forEach(item => {
|
||||||
|
if (item.text && !['检验项目', '结果', '单位', '提示', '参考区间'].includes(item.text)) {
|
||||||
|
// 以 y 坐标为 key,允许有一定误差(如±5)
|
||||||
|
const y = Math.round(item.rotate_rect[1] / 5) * 5;
|
||||||
|
if (!rows[y]) rows[y] = [];
|
||||||
|
rows[y].push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. 每一行找 name/value
|
||||||
|
const result = [];
|
||||||
|
Object.values(rows).forEach(items => {
|
||||||
|
let name = null, value = null;
|
||||||
|
items.forEach(item => {
|
||||||
|
if (Math.abs(item.rotate_rect[0] - nameX) < 50) name = item.text.trim();
|
||||||
|
if (Math.abs(item.rotate_rect[0] - valueX) < 50) value = item.text.trim();
|
||||||
|
});
|
||||||
|
if (name && value) result.push({ name, value });
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
import request from '~/api/request';
|
import request from '~/api/request';
|
||||||
import { getOcr } from '~/api/drugOcr';
|
import {
|
||||||
|
getOcr
|
||||||
|
} from '~/api/drugOcr';
|
||||||
|
|
||||||
let modeType = '';
|
let modeType = '';
|
||||||
let mode2 = '';
|
let mode2 = '';
|
||||||
@ -116,7 +118,10 @@ Page({
|
|||||||
|
|
||||||
},
|
},
|
||||||
showSelect(e) {
|
showSelect(e) {
|
||||||
const { mode, index } = e.currentTarget.dataset;
|
const {
|
||||||
|
mode,
|
||||||
|
index
|
||||||
|
} = e.currentTarget.dataset;
|
||||||
modeText = mode
|
modeText = mode
|
||||||
modeIndex = index
|
modeIndex = index
|
||||||
this.setData({
|
this.setData({
|
||||||
@ -131,7 +136,9 @@ Page({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
showPicker(e) {
|
showPicker(e) {
|
||||||
const { mode } = e.currentTarget.dataset;
|
const {
|
||||||
|
mode
|
||||||
|
} = e.currentTarget.dataset;
|
||||||
modeType = mode;
|
modeType = mode;
|
||||||
this.setData({
|
this.setData({
|
||||||
birthVisible: true,
|
birthVisible: true,
|
||||||
@ -145,7 +152,9 @@ Page({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
showPickertime(e) {
|
showPickertime(e) {
|
||||||
const { mode } = e.currentTarget.dataset;
|
const {
|
||||||
|
mode
|
||||||
|
} = e.currentTarget.dataset;
|
||||||
mode2 = mode;
|
mode2 = mode;
|
||||||
this.setData({
|
this.setData({
|
||||||
minuteVisible: true,
|
minuteVisible: true,
|
||||||
@ -165,22 +174,30 @@ Page({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onRadioChange(e) {
|
onRadioChange(e) {
|
||||||
const { index } = e.currentTarget.dataset;
|
const {
|
||||||
|
index
|
||||||
|
} = e.currentTarget.dataset;
|
||||||
this.setData({
|
this.setData({
|
||||||
[`detail[${index}].time`]: e.detail.value
|
[`detail[${index}].time`]: e.detail.value
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
handleSuccess(e) {
|
handleSuccess(e) {
|
||||||
console.log(e.detail)
|
console.log(e.detail)
|
||||||
const { files } = e.detail;
|
const {
|
||||||
|
files
|
||||||
|
} = e.detail;
|
||||||
this.setData({
|
this.setData({
|
||||||
originFiles: files,
|
originFiles: files,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleRemove(e) {
|
handleRemove(e) {
|
||||||
console.log(e.detail.file);
|
console.log(e.detail.file);
|
||||||
const { index } = e.detail;
|
const {
|
||||||
const { originFiles } = this.data;
|
index
|
||||||
|
} = e.detail;
|
||||||
|
const {
|
||||||
|
originFiles
|
||||||
|
} = this.data;
|
||||||
originFiles.splice(index, 1);
|
originFiles.splice(index, 1);
|
||||||
this.setData({
|
this.setData({
|
||||||
originFiles,
|
originFiles,
|
||||||
@ -191,7 +208,9 @@ Page({
|
|||||||
},
|
},
|
||||||
|
|
||||||
deleteItem(e) {
|
deleteItem(e) {
|
||||||
const { index } = e.currentTarget.dataset;
|
const {
|
||||||
|
index
|
||||||
|
} = e.currentTarget.dataset;
|
||||||
this.setData({
|
this.setData({
|
||||||
detail: this.data.detail.filter((item, i) => i !== index)
|
detail: this.data.detail.filter((item, i) => i !== index)
|
||||||
})
|
})
|
||||||
@ -222,7 +241,10 @@ Page({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onInput(e) {
|
onInput(e) {
|
||||||
const { mode, index } = e.currentTarget.dataset;
|
const {
|
||||||
|
mode,
|
||||||
|
index
|
||||||
|
} = e.currentTarget.dataset;
|
||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
[`detail[${index}].${mode}`]: e.detail.value,
|
[`detail[${index}].${mode}`]: e.detail.value,
|
||||||
@ -279,7 +301,7 @@ Page({
|
|||||||
* 生命周期函数--监听页面加载
|
* 生命周期函数--监听页面加载
|
||||||
*/
|
*/
|
||||||
onLoad(options) {
|
onLoad(options) {
|
||||||
console.log(options)
|
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
this.setData({
|
this.setData({
|
||||||
id: options.id
|
id: options.id
|
||||||
@ -304,8 +326,8 @@ Page({
|
|||||||
|
|
||||||
const policyData = await request('admin/policy_token', 'post')
|
const policyData = await request('admin/policy_token', 'post')
|
||||||
const res = JSON.parse(policyData.token)
|
const res = JSON.parse(policyData.token)
|
||||||
const fileNameWithExt = file.tempFilePath.split('/').pop(); // hello.png
|
const fileName = file.tempFilePath.split('/').pop(); // hello.png
|
||||||
const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
// const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
key: 'upload_file/' + fileName, //上传文件名称
|
key: 'upload_file/' + fileName, //上传文件名称
|
||||||
@ -338,7 +360,10 @@ Page({
|
|||||||
},
|
},
|
||||||
fail(err) {
|
fail(err) {
|
||||||
console.error('上传失败:', err); // 输出错误信息
|
console.error('上传失败:', err); // 输出错误信息
|
||||||
wx.showToast({ title: '上传失败,请重试!', icon: 'none' });
|
wx.showToast({
|
||||||
|
title: '上传失败,请重试!',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
callback(err); // 调用回调处理错误
|
callback(err); // 调用回调处理错误
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -350,37 +375,84 @@ Page({
|
|||||||
mediaType: ['image'],
|
mediaType: ['image'],
|
||||||
sourceType: ['album', 'camera'],
|
sourceType: ['album', 'camera'],
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
wx.showToast({ title: '文件上传中,请稍等!', icon: 'none' });
|
wx.showToast({
|
||||||
|
title: '文件上传中,请稍等!',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
console.log('选择的文件:', res.tempFiles); // 输出选择的文件信息
|
console.log('选择的文件:', res.tempFiles); // 输出选择的文件信息
|
||||||
if (res.tempFiles.length > 0) {
|
if (res.tempFiles.length > 0) {
|
||||||
const tempFilePath = res.tempFiles[0];
|
const tempFilePath = res.tempFiles[0];
|
||||||
console.log('选择的文件路径:', tempFilePath); // 输出文件路径
|
console.log('选择的文件路径:', tempFilePath); // 输出文件路径
|
||||||
this.uploadFileToOSS(tempFilePath, (error, data) => {
|
this.uploadFileToOSS(tempFilePath, (error, data) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
wx.showToast({ title: '上传失败!', icon: 'none' });
|
wx.showToast({
|
||||||
|
title: '上传失败!',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
console.error('上传失败:', error); // 输出具体的错误信息
|
console.error('上传失败:', error); // 输出具体的错误信息
|
||||||
} else {
|
} else {
|
||||||
wx.showToast({ title: '上传成功!', icon: 'success' });
|
wx.showToast({ title: '上传成功,正在识别内容!', icon: 'none' });
|
||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
imageFile: data
|
imageFile: data
|
||||||
})
|
})
|
||||||
getOcr(data).then(res => {
|
getOcr(data).then(res => {
|
||||||
|
wx.showToast({ title: '识别完成!', icon: 'none' })
|
||||||
|
this.ocrAdditem(res)
|
||||||
})
|
})
|
||||||
console.log('上传成功:', data); // 输出上传成功后的数据
|
console.log('上传成功:', data); // 输出上传成功后的数据
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
wx.showToast({ title: '未选择文件!', icon: 'none' });
|
wx.showToast({
|
||||||
|
title: '未选择文件!',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
wx.showToast({ title: '选择文件失败!', icon: 'none' });
|
wx.showToast({
|
||||||
|
title: '选择文件失败!',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
console.error('选择文件失败:', err); // 输出选择文件的错误信息
|
console.error('选择文件失败:', err); // 输出选择文件的错误信息
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ocrAdditem(data) {
|
||||||
|
let arr = [];
|
||||||
|
data.forEach(item => {
|
||||||
|
if (item.name) {
|
||||||
|
arr.push({
|
||||||
|
"name": item.name,
|
||||||
|
"dose": item.jiliang,
|
||||||
|
"frequency": item.cishu.replace("次", ""),
|
||||||
|
"time": ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (arr.length === 0) return;
|
||||||
|
let detail = [...this.data.detail];
|
||||||
|
const last = detail[detail.length - 1];
|
||||||
|
const hasEmpty = !last.name || !last.dose || !last.frequency || !last.time;
|
||||||
|
if (hasEmpty) {
|
||||||
|
// 用 arr[0] 填充最后一条
|
||||||
|
detail[detail.length - 1] = arr[0];
|
||||||
|
// 剩余的插入末尾
|
||||||
|
if (arr.length > 1) {
|
||||||
|
detail = detail.concat(arr.slice(1));
|
||||||
|
}
|
||||||
|
this.setData({
|
||||||
|
detail
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 全部插入末尾
|
||||||
|
this.setData({
|
||||||
|
detail: detail.concat(arr)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
handleDelete(e) {
|
handleDelete(e) {
|
||||||
this.setData({
|
this.setData({
|
||||||
imageFile: ''
|
imageFile: ''
|
||||||
|
|||||||
@ -253,8 +253,8 @@ Page({
|
|||||||
const policyData = await request('admin/policy_token', 'post')
|
const policyData = await request('admin/policy_token', 'post')
|
||||||
const res = JSON.parse(policyData.token)
|
const res = JSON.parse(policyData.token)
|
||||||
|
|
||||||
const fileNameWithExt = file.tempFilePath.split('/').pop(); // hello.png
|
const fileName = file.tempFilePath.split('/').pop(); // hello.png
|
||||||
const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
// const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
key: 'upload_file/' + fileName, //上传文件名称
|
key: 'upload_file/' + fileName, //上传文件名称
|
||||||
@ -315,19 +315,23 @@ Page({
|
|||||||
wx.showToast({ title: '上传失败!', icon: 'none' });
|
wx.showToast({ title: '上传失败!', icon: 'none' });
|
||||||
console.error('上传失败:', error); // 输出具体的错误信息
|
console.error('上传失败:', error); // 输出具体的错误信息
|
||||||
} else {
|
} else {
|
||||||
// getOcr(data)
|
|
||||||
wx.showToast({ title: '上传成功,正在识别内容!', icon: 'success' });
|
|
||||||
const { mode } = e.currentTarget.dataset;
|
const { mode } = e.currentTarget.dataset;
|
||||||
let arr = this.data.form[mode]
|
let arr = this.data.form[mode]
|
||||||
arr.unshift(data)
|
arr.unshift(data)
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.${mode}`]: arr
|
[`form.${mode}`]: arr
|
||||||
})
|
})
|
||||||
|
if(mode != 'mdt_image'){
|
||||||
|
wx.showToast({ title: '上传成功,正在识别内容!', icon: 'none' });
|
||||||
getOcr(data).then(ocrRes => {
|
getOcr(data).then(ocrRes => {
|
||||||
console.log(ocrRes)
|
console.log(ocrRes)
|
||||||
wx.showToast({ title: '识别完成!', icon: 'success' })
|
wx.showToast({ title: '识别完成!', icon: 'none' })
|
||||||
this.setFormData(ocrRes, mode)
|
this.setFormData(ocrRes, mode)
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
wx.showToast({ title: '上传成功!', icon: 'none' });
|
||||||
|
}
|
||||||
|
|
||||||
console.log('上传成功:', data); // 输出上传成功后的数据
|
console.log('上传成功:', data); // 输出上传成功后的数据
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -414,17 +418,17 @@ Page({
|
|||||||
ocrs.forEach(ocr => {
|
ocrs.forEach(ocr => {
|
||||||
// 血常规
|
// 血常规
|
||||||
if (mode == 'blood_routine_image') {
|
if (mode == 'blood_routine_image') {
|
||||||
if (ocr.name == '血红蛋白') {
|
if (ocr.name == '血红蛋白' || ocr.name == '血红蛋白检查') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.hemoglobin`]: ocr.value
|
[`form.hemoglobin`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr.name == '血小板') {
|
if (ocr.name == '血小板' || ocr.name == '血小板计数') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.platelets`]: ocr.value
|
[`form.platelets`]: ocr.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (ocr.name == '白细胞') {
|
if (ocr.name == '白细胞' || ocr.name == '白细胞计数') {
|
||||||
this.setData({
|
this.setData({
|
||||||
[`form.white_blood_cells`]: ocr.value
|
[`form.white_blood_cells`]: ocr.value
|
||||||
})
|
})
|
||||||
|
|||||||
@ -30,7 +30,9 @@ Page({
|
|||||||
formKey: '',
|
formKey: '',
|
||||||
|
|
||||||
|
|
||||||
|
getUserinfo(e) {
|
||||||
|
console.log(e)
|
||||||
|
},
|
||||||
|
|
||||||
//上传文件方法
|
//上传文件方法
|
||||||
async uploadFileToOSS(file, callback) {
|
async uploadFileToOSS(file, callback) {
|
||||||
@ -38,8 +40,8 @@ async uploadFileToOSS(file, callback) {
|
|||||||
|
|
||||||
const policyData = await request('admin/policy_token', 'post')
|
const policyData = await request('admin/policy_token', 'post')
|
||||||
const res = JSON.parse(policyData.token)
|
const res = JSON.parse(policyData.token)
|
||||||
const fileNameWithExt = file.tempFilePath.split('/').pop(); // hello.png
|
const fileName = file.tempFilePath.split('/').pop(); // hello.png
|
||||||
const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
// const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
key: 'upload_file/' + fileName, //上传文件名称
|
key: 'upload_file/' + fileName, //上传文件名称
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
<t-input bindchange="onInput" data-mode="mobile" placeholder="请输入手机号" align="right" type="number" value="{{form.mobile}}" status="{{isMobile ? '' : 'error'}}" tips="{{isMobile ? '' : '请输入手机号'}}">
|
<t-input bindchange="onInput" data-mode="mobile" placeholder="请输入手机号" align="right" type="number" value="{{form.mobile}}" status="{{isMobile ? '' : 'error'}}" tips="{{isMobile ? '' : '请输入手机号'}}">
|
||||||
<view slot="label" class="custom-label">手机号</view>
|
<view slot="label" class="custom-label">手机号</view>
|
||||||
</t-input>
|
</t-input>
|
||||||
|
<!-- <button open-type="getUserInfo" bindgetuserinfo="getUserinfo">用户信息</button> -->
|
||||||
</view>
|
</view>
|
||||||
<view class="follow-item">
|
<view class="follow-item">
|
||||||
<view class="custom-label">胆囊</view>
|
<view class="custom-label">胆囊</view>
|
||||||
|
|||||||
@ -76,6 +76,13 @@
|
|||||||
</view>
|
</view>
|
||||||
<text class="iconfont icon-youjiantou thumbnail_3"></text>
|
<text class="iconfont icon-youjiantou thumbnail_3"></text>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="block_7" data-url="/pages/mmp-7/index" bind:tap="toPath">
|
||||||
|
<view class="image-text_6">
|
||||||
|
<image src="https://image-fudan.oss-cn-beijing.aliyuncs.com/mini_images/my/jkjy.svg" class="thumbnail_4"></image>
|
||||||
|
<text lines="1" class="text-group_7">MMP-7</text>
|
||||||
|
</view>
|
||||||
|
<text class="iconfont icon-youjiantou thumbnail_3"></text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@ -364,8 +364,8 @@ Page({
|
|||||||
const policyData = await request('admin/policy_token', 'post')
|
const policyData = await request('admin/policy_token', 'post')
|
||||||
const res = JSON.parse(policyData.token)
|
const res = JSON.parse(policyData.token)
|
||||||
|
|
||||||
const fileNameWithExt = file.split('/').pop(); // hello.png
|
const fileName = file.split('/').pop(); // hello.png
|
||||||
const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
// const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
||||||
|
|
||||||
const formData = {
|
const formData = {
|
||||||
key: 'upload_file/' + fileName, //上传文件名称
|
key: 'upload_file/' + fileName, //上传文件名称
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user