feat:分析

This commit is contained in:
houjunxiang
2025-11-11 09:58:12 +08:00
parent 5916b8c833
commit fb41fa9a03
9 changed files with 311 additions and 149 deletions

View File

@@ -1,6 +1,6 @@
// 在此不用配置接口前缀 // 在此不用配置接口前缀
const isDev = process.env.NODE_ENV === 'development' const isDev = process.env.NODE_ENV === 'development'
const BaseUrl = isDev ? 'http://192.168.26.116:888/admin-api' : 'http://172.33.199.28:8088/api' const BaseUrl = isDev ? 'http://192.168.26.190:48080/admin-api' : 'http://172.33.199.28:8088/api'
// const BaseUrl = isDev ? 'http://localhost:9999' : '' // const BaseUrl = isDev ? 'http://localhost:9999' : ''
const upgradeBaseUrl = 'http://172.33.199.28:8088' const upgradeBaseUrl = 'http://172.33.199.28:8088'
@@ -31,5 +31,5 @@ export function getUpgradeBaseUrl() {
} }
export function getWebSocketUrl() { export function getWebSocketUrl() {
// return uni.getStorageSync('base_url').replace('/api', '') + '/ws' // return uni.getStorageSync('base_url').replace('/api', '') + '/ws'
return 'ws://192.168.26.178:8330' return 'ws://192.168.26.190:8330'
} }

View File

@@ -30,6 +30,14 @@ const getSampleAnalysisByTaskId = businessAssayTaskId => {
params: { businessAssayTaskId } params: { businessAssayTaskId }
}) })
} }
// 质控样
const batchSampleAndQcAnalysisByTaskId = businessAssayTaskId => {
return request({
url: '/qms/bus/sample/analysis/batchSampleAndQcAnalysisByTaskId',
method: 'GET',
params: { businessAssayTaskId }
})
}
// 获取指派单动态配置项 // 获取指派单动态配置项
const getDynamicBaseFormSchema = params => { const getDynamicBaseFormSchema = params => {
return request({ return request({
@@ -161,6 +169,17 @@ const saveDetailValue = data => {
} }
}) })
} }
// 批量保存任务
const saveBatchSmpleAndQcAnalysis = data => {
return request({
url: '/qms/bus/sample/analysis/saveBatchSmpleAndQcAnalysis',
method: 'POST',
data,
custom: {
showSuccess: true
}
})
}
// 提交任务明细-停用 // 提交任务明细-停用
const submitTaskDetail = params => { const submitTaskDetail = params => {
@@ -256,6 +275,8 @@ export default {
getAssayTaskList, getAssayTaskList,
getAssayTaskDataList, getAssayTaskDataList,
getSampleAnalysisByTaskId, getSampleAnalysisByTaskId,
batchSampleAndQcAnalysisByTaskId,
saveBatchSmpleAndQcAnalysis,
getDynamicBaseFormSchema, getDynamicBaseFormSchema,
getAssayTaskDetailListByTaskNo, getAssayTaskDetailListByTaskNo,
getAssayTaskDetailById, getAssayTaskDetailById,

View File

@@ -4,8 +4,9 @@ math.config({
number: 'BigNumber', number: 'BigNumber',
precision: 64 precision: 64
}) })
export { math }
/* /*
* 计算分析值*/ * 计算当前样品分析值*/
export function calcAnalysisValue(group) { export function calcAnalysisValue(group) {
try { try {
for (const g of group) { for (const g of group) {
@@ -57,6 +58,43 @@ export function calcAnalysisValue(group) {
} }
} }
// 根据样品和配置列计算分析值
export function calcRowAnalysisValue(row, columnObj, dynamicsColumns) {
if (!columnObj.paramNo) return
for (let i = 0; i < dynamicsColumns.length; i++) {
let curItem = dynamicsColumns[i]
if (curItem.fieldIndex === columnObj.fieldIndex) continue
let param = columnObj.fieldIndex.charAt(0) === 'p' ? 'p' + columnObj.paramNo : 'e' + columnObj.paramNo
if (curItem.formula && curItem.formula.includes(param)) {
let formula = curItem.formula
let formulas = formula.split('|')
let formulaVal = ''
formulas.forEach(f => {
if (f.charAt(0) === 'p') {
let o = dynamicsColumns.find(i => 'p' + i.paramNo === f)
formulaVal += row[o.fieldIndex]?.value ? row[o.fieldIndex].value : 0
} else if (f.charAt(0) === 'e') {
let o = dynamicsColumns.find(i => 'e' + i.paramNo === f)
formulaVal += row[o.fieldIndex]?.value ? row[o.fieldIndex].value : 0
} else {
formulaVal += f
}
})
let v
if (formulaVal.startsWith('Get')) {
formulaVal = formulaVal.replace(')', ",'" + row.conBaseSampleId + "')")
v = eval(formulaVal)
} else {
v = math.evaluate(formulaVal).toString()
v = isFinite(v) ? v : 0
}
row[curItem.fieldIndex].value = handleRoundFiveNumber(Number(v), row[curItem.fieldIndex].decimalPosition)
calcRowAnalysisValue(row, curItem, dynamicsColumns)
}
}
}
const findFieldInGroup = function (paramNo, group, p) { const findFieldInGroup = function (paramNo, group, p) {
for (const g of group) { for (const g of group) {
for (const f of g.fields) { for (const f of g.fields) {

View File

@@ -1,5 +1,6 @@
import $router from '@/nx/router' import $router from '@/nx/router'
import $helper from '@/nx/helper' import $helper from '@/nx/helper'
import $test from '@/nx/helper/test'
import $store from '@/nx/store' import $store from '@/nx/store'
import $measure from '@/nx/helper/measure' import $measure from '@/nx/helper/measure'
import $print from '@/nx/helper/print' import $print from '@/nx/helper/print'
@@ -21,7 +22,8 @@ const nx = {
$measure, $measure,
$print, $print,
$dayjs: dayjs, $dayjs: dayjs,
$api $api,
$test
} }
// 加载Nx底层依赖 // 加载Nx底层依赖

View File

@@ -48,6 +48,7 @@ onMounted(() => {
} }
} }
nx.$measure.setRegData(JSON.stringify(regData)) nx.$measure.setRegData(JSON.stringify(regData))
nx.$measure.open() nx.$measure.open()
// 监听 WebSocket 数据 // 监听 WebSocket 数据

View File

@@ -3,7 +3,7 @@
<view class="u-tab-item" :class="{ 'u-tab-item-active': active }" @tap.stop="handleClick"> <view class="u-tab-item" :class="{ 'u-tab-item-active': active }" @tap.stop="handleClick">
<u-row class="full-width"> <u-row class="full-width">
<u-col span="2" class="text-center" style="position: relative"> <u-col span="2" class="text-center" style="position: relative">
<u-icon :color="taskStyle(task)" name="tags-fill" size="34"></u-icon> <u-icon :color="taskStyle(task)" name="tags-fill" size="40"></u-icon>
<text class="seq">{{ seq }}</text> <text class="seq">{{ seq }}</text>
</u-col> </u-col>
<u-col span="10"> <u-col span="10">
@@ -72,7 +72,7 @@ const taskStyle = task => {
} }
.seq { .seq {
position: absolute; position: absolute;
top: 9px; top: 12px;
left: 12px; left: 12px;
color: #fff; color: #fff;
font-size: 11px; font-size: 11px;

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@
v-model="field.value" v-model="field.value"
clearable clearable
:placeholder="field.placeholder" :placeholder="field.placeholder"
:disabled="field.disabled || field.fillingWay == 3" :disabled="field.disabled || field.fillingWay == 'calculate'"
/> />
<!--数字限制小数位数--> <!--数字限制小数位数-->
<u-input <u-input
@@ -31,7 +31,7 @@
@blur="event => checkDecimal(event, field)" @blur="event => checkDecimal(event, field)"
v-model="field.value" v-model="field.value"
:placeholder="field.placeholder" :placeholder="field.placeholder"
:disabled="field.disabled || field.fillingWay == 3" :disabled="field.disabled || field.fillingWay == 'calculate'"
/> />
<!--select--> <!--select-->
<view v-if="field.type == 'select'" class="x-bc select-my" @click="handleFieldClick(field)"> <view v-if="field.type == 'select'" class="x-bc select-my" @click="handleFieldClick(field)">
@@ -150,12 +150,6 @@ function loadTaskDetail() {
// 点击字段(打开选择器) // 点击字段(打开选择器)
function handleFieldClick(field) { function handleFieldClick(field) {
if (field.type == 'date') {
field.showPicker = true
if (field.fillingWay == '1') {
}
return
}
field.showPicker = true field.showPicker = true
} }

View File

@@ -33,7 +33,7 @@
<block v-for="(sample, index) in sampleList" :key="index"> <block v-for="(sample, index) in sampleList" :key="index">
<view v-if="currentTask.reviewCount === sample.reviewCount" class="p5 fs16"> <view v-if="currentTask.reviewCount === sample.reviewCount" class="p5 fs16">
<u-row> <u-row>
<u-col span="3" class="text-center"> <u-col span="2" class="text-center">
<u-row> <u-row>
<u-col span="6" class="text-center"> <u-col span="6" class="text-center">
<!-- v-if=" <!-- v-if="
@@ -49,28 +49,30 @@
</u-col> </u-col>
</u-row> </u-row>
</u-col> </u-col>
<u-col span="9"> <u-col span="10" class="flex">
<view class="sample_desc"> <u-row>
<view> <u-col span="6">
<view <view class="sample_desc">
><text class="pl10">{{ sample.sampleCode }}</text></view <view>
> <view
><text class="pl10">{{ sample.sampleCode }}</text></view
>
<view>
<text class="pl10">
{{ getDataSourceTypeShow(sample.dataSourceType) }}{{ sample.sampleName }}
</text>
</view>
</view>
</view>
</u-col>
<u-col span="6">
<view> <view>
<text class="pl10"> <text class="pl10">
{{ getDataSourceTypeShow(sample.dataSourceType) }}{{ sample.sampleName }} {{ sample.assayProject }}
</text> </text>
</view> </view>
</view> </u-col>
</u-row>
<!-- <view class="sample_desc_warn" v-if="sample.sampleProcessNo !== currentNode">
当前节点{{ getProcessNameShow(sample.sampleProcessNo) }}
</view>
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'revoke'"> 样品退回被驳回 </view>
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'running'"> 样品退回审批中 </view>
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'finished'">
样品已退回请联系管理员处理
</view> -->
</view>
</u-col> </u-col>
</u-row> </u-row>
<u-line class="p5" color="#bbb" /> <u-line class="p5" color="#bbb" />
@@ -136,7 +138,7 @@ const customBack = () => {
uni.reLaunch({ url: '/pages/analysis/index/index' }) uni.reLaunch({ url: '/pages/analysis/index/index' })
} }
const showRollbackModal = () => { const showRollbackModal = () => {
if (checkedSampleCodes.length === 0) { if (checkedSampleCodes.value.length === 0) {
uni.showToast({ title: '请选择要退回的样品!', icon: 'none' }) uni.showToast({ title: '请选择要退回的样品!', icon: 'none' })
return return
} }