feat:完成输出结果处理
This commit is contained in:
parent
83d035180f
commit
50b04a4adf
@ -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"
|
||||||
},
|
},
|
||||||
|
@ -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){
|
if(content.content.length > mergedContentList.length){
|
||||||
content.content = mergedContentList;
|
content.content = mergedContentList;
|
||||||
// 更新新内容
|
// 更新新内容
|
||||||
editor.commands.setContent(content)
|
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())
|
||||||
})
|
})
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
@ -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,10 +16,19 @@
|
|||||||
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">
|
||||||
|
<div class=" font-bold">
|
||||||
<span>{{ item.title }}</span>
|
<span>{{ item.title }}</span>
|
||||||
<!-- <span>{{ parseExpression(item.expression) }}</span>-->
|
<!-- <span>{{ parseExpression(item.expression) }}</span>-->
|
||||||
</div>
|
</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 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>
|
||||||
</div>
|
</div>
|
||||||
@ -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,7 +58,6 @@ 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";
|
||||||
|
|
||||||
@ -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 testExpression(item: ResultExpression) {
|
function getResultValues(){
|
||||||
|
// 结果集
|
||||||
|
const result:{
|
||||||
|
[key: string]: number
|
||||||
|
} = {};
|
||||||
|
ResultExpressionList.value.forEach(it=>{
|
||||||
|
const expression = parseExpression(it.expression);
|
||||||
|
if(expression.length == 0) return;
|
||||||
try{
|
try{
|
||||||
const expression = parseExpression(item.expression);
|
const value = runCode(expression, {
|
||||||
const result = runCode(expression, {
|
|
||||||
...(productValues.value),
|
...(productValues.value),
|
||||||
|
...result,
|
||||||
|
input: inputValues.value,
|
||||||
|
})
|
||||||
|
result[it.key] = value;
|
||||||
|
}catch (e) {}
|
||||||
|
})
|
||||||
|
return result;
|
||||||
|
// console.log(result)
|
||||||
|
}
|
||||||
|
function testExpression(item: ResultExpression) {
|
||||||
|
const expression = parseExpression(item.expression);
|
||||||
|
try {
|
||||||
|
const result = getResultValues()
|
||||||
|
const value = runCode(expression, {
|
||||||
|
...(productValues.value),
|
||||||
|
...(result),
|
||||||
input: inputValues.value,
|
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;
|
||||||
}
|
}
|
||||||
|
@ -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' },
|
||||||
|
@ -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})
|
||||||
|
@ -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 ['']
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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
|
||||||
|
@ -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],
|
||||||
|
1
src/types/product.d.ts
vendored
1
src/types/product.d.ts
vendored
@ -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;
|
||||||
|
@ -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"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user