feat:完成输出结果处理

This commit is contained in:
LittleBoy 2025-01-05 11:01:36 +08:00
parent 83d035180f
commit 50b04a4adf
13 changed files with 102 additions and 60 deletions

View File

@ -4,8 +4,8 @@
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --host", "dev-front": "vite --host",
"dev-test": "vite --host --mode=test", "dev-front-test": "vite --host --mode=test",
"build": "vue-tsc && vite build", "build": "vue-tsc && vite build",
"preview": "vite preview" "preview": "vite preview"
}, },

View File

@ -37,20 +37,22 @@ const editor = new Editor({
function getMergeContent(){ function getMergeContent(){
const content = editor.getJSON() const content = editor.getJSON()
const mergedContentList:ExpressionValue[] = []; const mergedContentList:ExpressionValue[] = [];
content.content?.forEach(it=>{ if(content.content){
if(it.type == "paragraph" && it.content?.length > 0){ content.content.forEach(it=>{
mergedContentList.push(it) if(it.type == "paragraph" && it.content && it.content?.length > 0){
mergedContentList.push(it as any)
}
})
if(content.content.length > mergedContentList.length){
content.content = mergedContentList;
//
editor.commands.setContent(content)
} }
})
if(content.content?.length > mergedContentList.length){
content.content = mergedContentList;
//
editor.commands.setContent(content)
} }
return content; return content;
} }
onMounted(() => { onMounted(() => {
if (model.value?.trim().length > 0) editor.commands.setContent(JSON.parse(model.value)) if (model.value && model.value.trim().length > 0) editor.commands.setContent(JSON.parse(model.value))
editor.on('update', () => { editor.on('update', () => {
model.value = JSON.stringify(getMergeContent()) model.value = JSON.stringify(getMergeContent())
}) })

View File

@ -198,7 +198,7 @@ function handleHideModal() {
} }
.app-main-container { .app-main-container {
min-width: 1100px; min-width: 500px;
padding: 30px; padding: 30px;
overflow: auto; overflow: auto;
background: #f0f2f0; background: #f0f2f0;

View File

@ -42,15 +42,15 @@
</Tabs> </Tabs>
</div> </div>
<template #footer> <template #footer>
<div class="flex justify-center"> <div class="flex justify-center mt-10">
<Button key="submit" type="primary" @click="handleOk">确定</Button> <Button key="submit" type="primary" @click="handleOk">确定</Button>
</div> </div>
</template> </template>
</Modal> </Modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {Input, Modal, Button, Tabs, TabPane} from 'ant-design-vue' import {Modal, Button, Tabs, TabPane} from 'ant-design-vue'
import {defineComponent, onMounted, ref, watch} from "vue"; import {defineComponent, onMounted, ref} from "vue";
import {inputProducts} from "@/pages/result/test/data-input.ts"; import {inputProducts} from "@/pages/result/test/data-input.ts";
type InputValuesType = { type InputValuesType = {
@ -62,7 +62,7 @@ type SettingItem = {
key: string; key: string;
placeholder: string; placeholder: string;
type: string; type: string;
unit: string; unit?: string;
} }
const inputValues = defineModel('inputValues') const inputValues = defineModel('inputValues')
const commonValues = ref({ const commonValues = ref({
@ -150,7 +150,8 @@ function handleOk() {
} }
.unit { .unit {
@apply px-2 py-1 bg-gray-200 block h-full; @apply px-2 py-1 bg-gray-200 block h-full text-center;
min-width: 34px;
} }
} }
</style> </style>

View File

@ -2,9 +2,10 @@
<div class="result-container"> <div class="result-container">
<PageHeader title="输出指标编辑" description="*输出指标: 使用输入参数进行计算,可对指标进行编辑操作。"> <PageHeader title="输出指标编辑" description="*输出指标: 使用输入参数进行计算,可对指标进行编辑操作。">
<Space> <Space>
<Button :icon="h(SettingOutlined)" :loading="loading" type="info" @click="settingVisible=true"> <Button :icon="h(SettingOutlined)" @click="settingVisible=true">
设置输入数据 设置输入数据
</Button> </Button>
<Button @click="getResultValues">getResultValues</Button>
<Button :icon="h(SaveOutlined)" :loading="loading" type="primary" @click="save">保存</Button> <Button :icon="h(SaveOutlined)" :loading="loading" type="primary" @click="save">保存</Button>
</Space> </Space>
</PageHeader> </PageHeader>
@ -15,9 +16,18 @@
style="max-height: calc(100vh - 240px);margin-right:-5px;padding-right:5px;"> style="max-height: calc(100vh - 240px);margin-right:-5px;padding-right:5px;">
<div class="result-item bg-gray-100 p-3 rounded" v-for="item in ResultExpressionList" :key="item.key"> <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="result-item-title flex justify-between">
<div class=" text-base font-bold"> <div class=" text-base">
<span>{{ item.title }}</span> <div class=" font-bold">
<!-- <span>{{ parseExpression(item.expression) }}</span>--> <span>{{ item.title }}</span>
<!-- <span>{{ parseExpression(item.expression) }}</span>-->
</div>
<div class="alias text-sm text-gray-400 flex item-center">
<div><span>别名</span><Tooltip placement="bottom" color="#00ab99">
<template #title>上一步的计算结果可用于后面表达式</template>
<InfoCircleOutlined style="font-size: 12px" />
</Tooltip></div>
<div>{{item.key}}</div>
</div>
</div> </div>
<div class="action"> <div class="action">
<Button :icon="h(CodeOutlined)" type="text" @click="testExpression(item)">测试公式</Button> <Button :icon="h(CodeOutlined)" type="text" @click="testExpression(item)">测试公式</Button>
@ -38,9 +48,9 @@
</div> --> </div> -->
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {Button, Space,App } from "ant-design-vue"; import {Button, Space, App, Tooltip} from "ant-design-vue";
import {h, ref} from "vue"; import {h, ref} from "vue";
import {CodeOutlined, SaveOutlined, SettingOutlined} from '@ant-design/icons-vue'; import {CodeOutlined, SaveOutlined, SettingOutlined,InfoCircleOutlined} from '@ant-design/icons-vue';
import {expressionList, saveExpression} from "@/service/api/result"; import {expressionList, saveExpression} from "@/service/api/result";
@ -48,11 +58,10 @@ import PageHeader from "@/components/page-header.vue";
import Tiptap from "@/components/editor/tiptap.vue"; import Tiptap from "@/components/editor/tiptap.vue";
// import Button from "@/components/button/button.vue"; // import Button from "@/components/button/button.vue";
import useRequest from "@/service/useRequest"; import useRequest from "@/service/useRequest";
import input from "./test/data-input.ts"
import {getAllProduct} from "@/service/use-result-vars.ts"; import {getAllProduct} from "@/service/use-result-vars.ts";
import InputSetting from "@/pages/result/components/input-setting.vue"; import InputSetting from "@/pages/result/components/input-setting.vue";
const {notification,message,modal} = App.useApp() const {notification, message, modal} = App.useApp()
const ResultExpressionList = ref<ResultExpression[]>([]); const ResultExpressionList = ref<ResultExpression[]>([]);
const inputValues = ref<{ const inputValues = ref<{
[key: string]: number [key: string]: number
@ -74,31 +83,53 @@ function runCode(expression: string, vars: any) {
return new Function('vars', `with(vars) { return ${expression};}`)(vars) return new Function('vars', `with(vars) { return ${expression};}`)(vars)
} }
function getResultValues(){
//
const result:{
[key: string]: number
} = {};
ResultExpressionList.value.forEach(it=>{
const expression = parseExpression(it.expression);
if(expression.length == 0) return;
try{
const value = runCode(expression, {
...(productValues.value),
...result,
input: inputValues.value,
})
result[it.key] = value;
}catch (e) {}
})
return result;
// console.log(result)
}
function testExpression(item: ResultExpression) { function testExpression(item: ResultExpression) {
try{ const expression = parseExpression(item.expression);
const expression = parseExpression(item.expression); try {
const result = runCode(expression, { const result = getResultValues()
const value = runCode(expression, {
...(productValues.value), ...(productValues.value),
input:inputValues.value, ...(result),
input: inputValues.value,
}) })
// console.log('result', result,expression,inputValues.value) console.log('result', value,expression,result) // ,JSON.stringify(productValues.value)
notification.info({ notification.info({
message:'提示', message: '提示',
description:`${item.title}${result}`, description: `${item.title}${value}`,
duration:2 duration: 2
}) })
}catch (e){ } catch (e) {
modal.warning({ modal.warning({
title:'测试公式失败', title: '测试公式失败',
content:`错误详情:${e.message}` content: `错误详情:${(e as Error).message}`
}) })
console.log('expression =>', expression) // ,input,productValues.value
} }
// console.log('expression =>', expression,input,productValues.value)
} }
function parseExpression(str: string) { function parseExpression(str: string) {
if (!str) return; if (!str) return '';
const doc = JSON.parse(str) as TiptapContentValue; const doc = JSON.parse(str) as TiptapContentValue;
if (!doc.content || doc.content.length == 0) { if (!doc.content || doc.content.length == 0) {
return ''; return '';
@ -121,6 +152,7 @@ function parseExpression(str: string) {
.tiptap { .tiptap {
@apply outline-none min-h-[40px]; @apply outline-none min-h-[40px];
line-height: 26px; line-height: 26px;
:first-child { :first-child {
margin-top: 0; margin-top: 0;
} }

View File

@ -17,13 +17,13 @@ export const inputProducts = [
{ name: '伊力佳', key: 'yilijia', placeholder: '入液量ml', unit: 'ml', type: 'gut' }, { name: '伊力佳', key: 'yilijia', placeholder: '入液量ml', unit: 'ml', type: 'gut' },
{ name: '瑞易西', key: 'ruiyixi', placeholder: '入液量ml', unit: 'ml', type: 'gut' }, { name: '瑞易西', key: 'ruiyixi', placeholder: '入液量ml', unit: 'ml', type: 'gut' },
{ name: '能全素', key: 'nengquansu', placeholder: '入量(勺)', unit: 'ml', type: 'gut', addition: { key: 'nengquansu_ruye', placeholder: '入液量ml' } }, { name: '能全素', key: 'nengquansu', placeholder: '入量(勺)', unit: '', type: 'gut', addition: { key: 'nengquansu_ruye', placeholder: '入液量ml', unit: 'ml' } },
{ name: '安素', key: 'ansu', placeholder: '入量(勺)', unit: '勺', type: 'gut', addition: { key: 'ansu_ruye', placeholder: '入液量ml' } }, { name: '安素', key: 'ansu', placeholder: '入量(勺)', unit: '勺', type: 'gut', addition: { key: 'ansu_ruye', placeholder: '入液量ml', unit: 'ml' } },
{ name: '全安素', key: 'quanansu', placeholder: '入量(勺)', unit: '勺', type: 'gut', addition: { key: 'quanansu_ruye', placeholder: '入液量ml' } }, { name: '全安素', key: 'quanansu', placeholder: '入量(勺)', unit: '勺', type: 'gut', addition: { key: 'quanansu_ruye', placeholder: '入液量ml', unit: 'ml' } },
// 新增 230409 // 新增 230409
{ name: '益力佳', key: 'yilijia100', placeholder: '入量(勺)', unit: 'ml', type: 'gut', addition: { key: 'yilijia100_ruye', placeholder: '入液量ml' } }, { name: '益力佳', key: 'yilijia100', placeholder: '入量(勺)', unit: '', type: 'gut', addition: { key: 'yilijia100_ruye', placeholder: '入液量ml', unit: 'ml' } },
// o water // o water
{ name: '乳清蛋白量(g)', key: 'ruqingdanbailiang', placeholder: '入量g', unit: 'g', type: 'gut', addition: { key: 'ruqingdanbailiang_ruye', placeholder: '入液量ml' } }, { name: '乳清蛋白量(g)', key: 'ruqingdanbailiang', placeholder: '入量g', unit: 'g', type: 'gut', addition: { key: 'ruqingdanbailiang_ruye', placeholder: '入液量ml', unit: 'ml' } },
// { name: '雀巢Beneprotein', key: 'quecaoBeneprotein', placeholder: '入量g',unit:'g',type: 'gut' }, // { name: '雀巢Beneprotein', key: 'quecaoBeneprotein', placeholder: '入量g',unit:'g',type: 'gut' },
{ name: '瑞安吉', key: 'ruianji', placeholder: '入液量ml', unit: 'ml', type: 'gut' }, { name: '瑞安吉', key: 'ruianji', placeholder: '入液量ml', unit: 'ml', type: 'gut' },

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="dropdown-menu"> <div class="dropdown-menu">
<div class="dropdown-menu-list" v-if="items.length"> <div class="dropdown-menu-list" v-if="items?.length">
<div <div
class="dropdown-item" class="dropdown-item"
:class="{ 'is-selected': index === selectedIndex }" :class="{ 'is-selected': index === selectedIndex }"
@ -42,8 +42,9 @@ const selectedIndex = ref(0)
watch(()=>props.query, () => { watch(()=>props.query, () => {
selectedIndex.value = 0; selectedIndex.value = 0;
if(props.query){ if(props.query){
const q = String(props.query)
varList.value = productList.value.filter(item => ( varList.value = productList.value.filter(item => (
item.value.includes(props.query) || item.label.includes(props.query) || item.text.includes(props.query) item.value.includes(q) || item.label.includes(q) || (item.text && item.text.includes(q))
));//.filter((_,index)=> index < 10) ));//.filter((_,index)=> index < 10)
}else{ }else{
varList.value = productList.value.filter((_,index)=> index < 10) varList.value = productList.value.filter((_,index)=> index < 10)
@ -59,7 +60,7 @@ const downHandler = () => {
const enterHandler = () => { const enterHandler = () => {
selectItem(selectedIndex.value) selectItem(selectedIndex.value)
} }
const selectItem = (index) => { const selectItem = (index:number) => {
const item = varList.value[index] const item = varList.value[index]
if (item) { if (item) {
props.command({id: item.value, label: item.text || item.label}) props.command({id: item.value, label: item.text || item.label})

View File

@ -4,7 +4,7 @@ import tippy from 'tippy.js'
import vars from './var.vue' import vars from './var.vue'
export default { export default {
items: ({query}) => { items: () => {
return [''] return ['']
}, },

View File

@ -31,15 +31,15 @@ export const routes:RouteRecordRaw[] = [
}, },
component: () => import('./pages/result/index.vue') component: () => import('./pages/result/index.vue')
}, },
{ // {
path: 'ttt', // path: 'ttt',
name: 'ttt', // name: 'ttt',
meta: { // meta: {
title: '输出计算', // title: '输出计算',
icon:'icon-calculator' // icon:'icon-calculator'
}, // },
component: () => import('./pages/T.vue') // component: () => import('./pages/T.vue')
}, // },
{ {
path: 'product-data', path: 'product-data',
name: 'product', name: 'product',

View File

@ -208,7 +208,7 @@ const ValueKeys = [
export function getAllProduct() { export function getAllProduct() {
const list = ref<{ const list = ref<{
[key: string]: ProductInfoModel [key: string]: ProductInfoModel
}>([]) }>({})
getList({ getList({
page: 1, page: 1,
limit: 10000 limit: 10000

View File

@ -37,7 +37,7 @@
--primary-border-radius: 3px; --primary-border-radius: 3px;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 4px; width: 6px;
border-radius: 5px border-radius: 5px
} }
@ -51,6 +51,9 @@
background: #279b83; background: #279b83;
cursor: pointer cursor: pointer
} }
.overflow-auto{
scrollbar-gutter: stable;
}
[type=reset], [type=reset],
[type=submit], [type=submit],

View File

@ -30,6 +30,7 @@ declare type ResultExpression = {
id: number; id: number;
key: string; key: string;
title: string; title: string;
alias: string;
expression: string; expression: string;
created_at: Date | string; created_at: Date | string;
updated_at: Date | string; updated_at: Date | string;

View File

@ -21,8 +21,10 @@
/* Linting */ /* Linting */
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": false,
"noUnusedParameters": true, "noUnusedParameters": false,
"noImplicitAny": false,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true
}, },
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],