添加匿名计算测试页面

This commit is contained in:
LittleBoy 2025-01-10 19:47:26 +08:00
parent 702fc4ba0d
commit 19fc116f73
8 changed files with 234 additions and 32 deletions

View File

@ -1,11 +1,14 @@
<script setup lang="ts">
import { ConfigProvider,App } from 'ant-design-vue'
import {useRoute} from "vue-router"
import PageLoading from "@/components/page-loading/index.vue";
import { useUserStore } from "@/service/user-store.ts";
import Login from "@/components/login/index.vue";
//
const store = useUserStore()
const route = useRoute()
const themeConfig = {
token: { colorPrimary: '#2EC7A5', },
@ -15,7 +18,7 @@ const themeConfig = {
<template>
<div class="app-container">
<PageLoading :class="{ hideLoading: store.userInit }" />
<Login v-if="store.userInit && (!store.userInfo || store.userInfo.id < 1)" />
<Login v-if="store.userInit && (!store.userInfo || store.userInfo.id < 1) && route.name != 'calc'" />
<template v-if="store.userInit">
<ConfigProvider :theme="themeConfig">
<App>

View File

@ -0,0 +1,177 @@
<template>
<div class="calc-container">
<div class="setting-container">
<div class="grid list-container grid-cols-2 gap-4 py-2">
<div class="input-item">
<div class="title">体重</div>
<div class="input">
<input type="number" v-model="commonValues.weight" placeholder="单位(kg)"/>
</div>
</div>
<div class="input-item">
<div class="title">24h尿素</div>
<div class="input">
<input type="number" v-model="commonValues.niaosu" placeholder="单位(mmol)"/>
</div>
</div>
</div>
<Tabs>
<TabPane key="gut" tab="肠内制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 setting-input-scroller">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='gut')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
<TabPane key="vein" tab="静脉制剂">
<div class="grid list-container grid-cols-2 gap-4 py-2 setting-input-scroller">
<div class="input-item" v-for="(it,key) in settingList.filter(s=>s.type=='vein')" :key="key">
<div class="title">{{ it.title }}</div>
<div class="input">
<input type="number" v-model="it.value" :placeholder="it.placeholder"/>
<span class="unit">{{ it.unit }}</span>
</div>
</div>
</div>
</TabPane>
</Tabs>
</div>
<div class="text-center py-4">
<Button type="primary" @click="calcResult">测试计算</Button>
</div>
<ResultModal v-model:result="testResultValue" />
</div>
</template>
<script setup lang="ts">
import {onMounted,defineComponent, ref} from "vue";
import {TabPane, Tabs, Button, Modal} from "ant-design-vue";
import {inputProducts} from "@/pages/result/test/data-input.ts";
import ResultModal from "@/pages/result/components/result-modal.vue";
import {expressionList} from "@/service/api/result.ts";
import {parseExpression} from "@/core/string.ts";
import {getAllProduct} from "@/service/use-result-vars.ts";
const commonValues = ref({
weight: '',
niaosu: '',
})
defineComponent({
name: 'Calculation'
})
const ResultExpressionList = ref<ResultExpression[]>([]);
const settingList = ref<SettingItem[]>([])
const testResultValue = ref<ResultItem[]>([])
const productValues = getAllProduct();
onMounted(()=>{
expressionList().then((res) => {
ResultExpressionList.value = res.list;
});
const setting: SettingItem[] = []
inputProducts.forEach(it => {
setting.push({
title: it.name,
key: it.key,
value: '',
placeholder: it.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.unit,
})
if (it.addition) {
setting.push({
title: it.name,
key: it.addition.key,
value: '',
placeholder: it.addition.placeholder, // + (it.unit?`(${it.unit})`:'')
type: it.type,
unit: it.addition.unit,
})
}
})
settingList.value = setting
})
function runCode(expression: string, vars: any) {
return new Function('vars', `with(vars) { return ${expression};}`)(vars)
}
function getResultValues(){
//
const result:{
[key: string]: number
} = {};
const inputs: { [key: string]: number }= {
...commonValues.value,
}
settingList.value.forEach(it=>{
inputs[it.key] = it.value ? Number(it.value) : 0
})
ResultExpressionList.value.forEach(it=>{
const expression = parseExpression(it.expression);
if(expression.length == 0) return;
try{
const value = runCode(expression, {
...(productValues.value),
...result,
input: inputs,
})
result[it.key] = value;
}catch (e) {
Modal.warning({
title: '提示',
content: `计算出错:${e.message}`
})
console.error('getResultValues',e,expression)
}
})
return result;
}
function calcResult(){
const result = getResultValues();
console.log('result',result)
const resultList:ResultItem[] = [];
ResultExpressionList.value.forEach(it=>{
resultList.push({
title:it.title,
key:it.key,
value: result[it.key] || 0
})
})
console.log(resultList);
testResultValue.value = resultList;
}
</script>
<style scoped lang="scss">
.calc-container{
max-width: 90%;
margin: auto;
width: 600px;
}
.list-container {
margin-right: -4px;
padding-right: 4px;
}
.setting-input-scroller {
max-height: calc(100vh - 200px);
overflow: auto;
}
.setting-container {
.input {
@apply w-full relative border rounded mt-1 flex items-center bg-white overflow-hidden;
}
input {
@apply flex-1 outline-0 block ml-2 py-1 mr-1;
}
.unit {
@apply absolute inset-y-0 right-0 px-2 py-1 bg-gray-100 block h-full text-center;
min-width: 34px;
}
}
</style>

View File

@ -135,7 +135,7 @@ const handleSubmit = () => {
height: 30px;
line-height: 30px;
color: red;
text-align: left;
text-align: center;
}
.form-item {

View File

@ -8,4 +8,25 @@ export function getMd5(str: string) {
export function formatDatetime(date: Date | string | number, format = 'YYYY-MM-DD HH:mm:ss') {
if (!date) return date;
return dayjs(date).format(format);
}
export function parseExpression(str: string) {
if (!str) return '';
const doc = JSON.parse(str) as TiptapContentValue;
if (!doc.content || doc.content.length == 0) {
return '';
}
const expList: string[] = [];
doc.content.forEach(p=>{
const expressionList = p.content;
if (!expressionList) return;
const expression = expressionList.map(item => {
if (item.type == 'text') {
return item.text;
}
return item.attrs.id
}).join('');
expList.push(expression);
})
return expList.join('');
}

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { defineModel, reactive } from 'vue';
import { reactive } from 'vue';
import { Modal, Form, Input, Space, Button, Select, SelectOption } from 'ant-design-vue';
import useRequest from '@/service/useRequest';
import { saveProduct } from '@/service/api/product';

View File

@ -7,7 +7,7 @@
title="测试结果"
:footer="false"
>
<div class="grid result-list grid-cols-2 gap-4">
<div class="grid result-list grid-cols-1 md:grid-cols-2 gap-2">
<div class="flex result-item" v-for="(it,index) in result" :key="index">
<div class="title">{{it.title}}:</div>
<div class="value">{{getValue(it)}}</div>
@ -59,7 +59,11 @@ function getValue(item:ResultItem){
return Math.floor(item.value)
}
if(!percentKeys.includes(item.key)){
return toFixed(item.value, 3)
const value = toFixed(item.value, 3);
if(item.key == 'shijireka'){
return Math.round(value);
}
return value
}
const v = item.value * 100;

View File

@ -14,7 +14,7 @@
<InputSetting v-model:input-values="inputValues" v-model:visible="settingVisible"/>
<div class="result-calc-expression-list-container">
<div class="result-expressions-inner overflow-auto grid grid-cols-1 gap-4"
style="max-height: calc(100vh - 240px);margin-right:-5px;padding-right:5px;">
style="max-height: calc(100vh - 240px);margin-right:-7px;padding-right:7px;">
<div class="result-item bg-gray-100 p-3 rounded" v-for="item in ResultExpressionList" :key="item.key">
<div class="result-item-title flex justify-between">
<div class=" text-base">
@ -62,6 +62,7 @@ import useRequest from "@/service/useRequest";
import {getAllProduct} from "@/service/use-result-vars.ts";
import InputSetting from "@/pages/result/components/input-setting.vue";
import ResultModal from "./components/result-modal.vue";
import {parseExpression} from "@/core/string.ts";
const {notification, message, modal} = App.useApp()
const ResultExpressionList = ref<ResultExpression[]>([]);
@ -86,6 +87,14 @@ function runCode(expression: string, vars: any) {
return new Function('vars', `with(vars) { return ${expression};}`)(vars)
}
function showAllResult(){
if(!inputValues.value){
console.log('inputValues',inputValues.value)
modal.warning({
title: '提示',
content: `请先设置输入数据`
})
return;
}
const result = getResultValues();
const resultList:ResultItem[] = [];
ResultExpressionList.value.forEach(it=>{
@ -122,6 +131,14 @@ function getResultValues(){
function testExpression(item: ResultExpression) {
if(!inputValues.value){
console.log('inputValues',inputValues.value)
modal.warning({
title: '提示',
content: `请先设置输入数据`
})
return;
}
const expression = parseExpression(item.expression);
try {
const result = getResultValues()
@ -146,26 +163,6 @@ function testExpression(item: ResultExpression) {
}
}
function parseExpression(str: string) {
if (!str) return '';
const doc = JSON.parse(str) as TiptapContentValue;
if (!doc.content || doc.content.length == 0) {
return '';
}
const expList: string[] = [];
doc.content.forEach(p=>{
const expressionList = p.content;
if (!expressionList) return;
const expression = expressionList.map(item => {
if (item.type == 'text') {
return item.text;
}
return item.attrs.id
}).join('');
expList.push(expression);
})
return expList.join('');
}
</script>
<style lang="scss">

View File

@ -64,16 +64,16 @@ export const routes:RouteRecordRaw[] = [
export const router = createRouter({
routes: [
// 路由配置
{
path: '/calc',
name: 'calc',
component: () => import('./components/calc/index.vue')
},
{
path: '/',
component: () => import('./pages/Layout.vue'),
children: routes
},
// {
// path: '/login',
// name: 'login',
// component: () => import('./pages/login.vue')
// }
}
],
history: createWebHashHistory()
})