update 更新编辑器;完成动态代码测试
This commit is contained in:
parent
f0a1b687b7
commit
a2e27103a4
@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@tiptap/core": "^2.10.4",
|
||||
"@tiptap/pm": "^2.10.4",
|
||||
"@tiptap/suggestion": "^2.10.4",
|
||||
"@tiptap/vue-3": "^2.10.4",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"autoprefixer": "^10.4.20",
|
||||
|
@ -4,7 +4,6 @@ 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()
|
||||
|
||||
|
@ -35,10 +35,8 @@
|
||||
position: relative;
|
||||
}
|
||||
.icon-loading{
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
animation: loading-360 linear 1s infinite;
|
||||
vertical-align: middle;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
|
@ -6,6 +6,7 @@ const props = defineProps<{
|
||||
block?: boolean;
|
||||
shape?: 'default' | 'circle' | 'round';
|
||||
loading?: boolean;
|
||||
icon?:import("vue-types").VueTypeValidableDef<any>
|
||||
}>()
|
||||
const btnClass = {
|
||||
'btn-primary': props.type == 'primary',
|
||||
@ -20,6 +21,7 @@ const btnClass = {
|
||||
<template>
|
||||
<button class="btn" :class="btnClass">
|
||||
<span v-if="props.loading" class="icon-loading"></span>
|
||||
<template v-else-if="!!props.icon" ><props.icon /></template>
|
||||
<span><slot/></span>
|
||||
</button>
|
||||
</template>
|
||||
|
17
src/components/editor/test.vue
Normal file
17
src/components/editor/test.vue
Normal file
@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div class="bg-blue-500 p-2 rounded">
|
||||
<textarea ref="txtBox" class="w-full block rounded outline-none"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from "vue";
|
||||
|
||||
const txtBox = ref<HTMLTextAreaElement>();
|
||||
const content = defineModel<string>()
|
||||
|
||||
onMounted(() => {
|
||||
txtBox.value?.addEventListener('input', () => {
|
||||
content.value = txtBox.value?.value || ''
|
||||
}, false)
|
||||
})
|
||||
</script>
|
@ -1,36 +1,61 @@
|
||||
<template>
|
||||
<EditorContent :editor="editor" />
|
||||
<EditorContent :editor="editor"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Editor, EditorContent } from '@tiptap/vue-3'
|
||||
import { extensions, Placeholder } from './tiptap'
|
||||
import { watch, onMounted, onUnmounted } from 'vue'
|
||||
import {Editor, EditorContent} from '@tiptap/vue-3'
|
||||
import {extensions, Mention, Placeholder} from './tiptap'
|
||||
import {watch, onMounted, onUnmounted} from 'vue'
|
||||
import vars from "@/pages/result/vars.ts";
|
||||
|
||||
defineOptions({
|
||||
name: 'Tiptap',
|
||||
})
|
||||
|
||||
const props = defineProps<{
|
||||
placeholder?: string
|
||||
}>()
|
||||
|
||||
const model = defineModel<string>()
|
||||
|
||||
const editor = new Editor({
|
||||
content: ``,
|
||||
// extensions: [StarterKit],
|
||||
extensions: [
|
||||
...extensions,
|
||||
Mention.configure({
|
||||
HTMLAttributes: {
|
||||
class: 'result-var',
|
||||
},
|
||||
suggestion: vars
|
||||
}),
|
||||
|
||||
Placeholder.configure({
|
||||
placeholder: props.placeholder || '请输入内容',
|
||||
})
|
||||
}),
|
||||
]
|
||||
})
|
||||
function getMergeContent(){
|
||||
const content = editor.getJSON()
|
||||
const mergedContentList:ExpressionValue[] = [];
|
||||
content.content?.forEach(it=>{
|
||||
if(it.type == "paragraph" && it.content?.length > 0){
|
||||
mergedContentList.push(it)
|
||||
}
|
||||
})
|
||||
if(content.content?.length > mergedContentList.length){
|
||||
content.content = mergedContentList;
|
||||
// 更新新内容
|
||||
editor.commands.setContent(content)
|
||||
}
|
||||
return content;
|
||||
}
|
||||
onMounted(() => {
|
||||
if (model.value) editor.commands.setContent(model.value)
|
||||
if (model.value?.trim().length > 0) editor.commands.setContent(JSON.parse(model.value))
|
||||
editor.on('update', () => {
|
||||
model.value = editor.getText()
|
||||
model.value = JSON.stringify(getMergeContent())
|
||||
})
|
||||
})
|
||||
watch(model, (newValue) => {
|
||||
watch(()=>model, (newValue) => {
|
||||
editor.commands.setContent(newValue || '')
|
||||
})
|
||||
|
||||
@ -39,11 +64,26 @@ onUnmounted(() => {
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.tiptap .is-empty{
|
||||
.ProseMirror-trailingBreak{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.tiptap p.is-editor-empty:first-child::before {
|
||||
display: block;
|
||||
color: #adb5bd;
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tiptap .result-var {
|
||||
background-color: #3574f0;
|
||||
border-radius: 3px;
|
||||
-webkit-box-decoration-break: clone;
|
||||
box-decoration-break: clone;
|
||||
color: white;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
</style>
|
@ -5,15 +5,7 @@ import Suggestion, { SuggestionOptions } from '@tiptap/suggestion'
|
||||
|
||||
// See `addAttributes` below
|
||||
export interface MentionNodeAttrs {
|
||||
/**
|
||||
* The identifier for the selected item that was mentioned, stored as a `data-id`
|
||||
* attribute.
|
||||
*/
|
||||
id: string | null;
|
||||
/**
|
||||
* The label to be rendered by the editor as the displayed text for this mentioned
|
||||
* item, if provided. Stored as a `data-label` attribute. See `renderLabel`.
|
||||
*/
|
||||
label?: string | null;
|
||||
}
|
||||
|
||||
@ -136,13 +128,9 @@ export const Mention = Node.create<MentionOptions>({
|
||||
},
|
||||
|
||||
group: 'inline',
|
||||
|
||||
inline: true,
|
||||
|
||||
selectable: false,
|
||||
|
||||
atom: true,
|
||||
|
||||
addAttributes() {
|
||||
return {
|
||||
id: {
|
||||
@ -174,7 +162,6 @@ export const Mention = Node.create<MentionOptions>({
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
parseHTML() {
|
||||
return [
|
||||
{
|
||||
@ -182,7 +169,6 @@ export const Mention = Node.create<MentionOptions>({
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
renderHTML({ node, HTMLAttributes }) {
|
||||
if (this.options.renderLabel !== undefined) {
|
||||
console.warn('renderLabel is deprecated use renderText and renderHTML instead')
|
@ -2,6 +2,7 @@ import { Text } from './ext-text.ts'
|
||||
import { Paragraph } from './ext-paragraph.ts'
|
||||
import { Document } from './ext-document.ts'
|
||||
export {Placeholder } from './ext-placeholder.ts'
|
||||
export {Mention} from './ext-mention.ts'
|
||||
|
||||
|
||||
// export
|
||||
|
12
src/pages/T.vue
Normal file
12
src/pages/T.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<TestRef v-model="testrv"/>
|
||||
<div>{{ testrv }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import TestRef from "@/components/editor/test.vue";
|
||||
import {ref} from "vue";
|
||||
|
||||
const testrv = ref('')
|
||||
</script>
|
@ -1,50 +1,92 @@
|
||||
<template>
|
||||
<div class="result-container">
|
||||
<PageHeader title="输出指标编辑" description="*输出指标: 使用输入参数进行计算,可对指标进行编辑操作。">
|
||||
<Button :loading="loading" type="primary" @click="save">保存</Button>
|
||||
<Button :icon="h(SaveOutlined)" :loading="loading" type="primary" @click="save">保存</Button>
|
||||
</PageHeader>
|
||||
</div>
|
||||
<div class="result-calc-expression-list-container overflow-auto grid grid-cols-2 gap-4"
|
||||
style="max-height: calc(100vh - 240px);margin-right:-5px;padding-right:5px;">
|
||||
|
||||
<div class="result-calc-expression-list-container overflow-auto grid grid-cols-1 gap-4"
|
||||
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-title text-base font-bold">{{ item.title }}</div>
|
||||
<div class="result-item-title flex justify-between">
|
||||
<div class=" text-base font-bold">
|
||||
<span>{{ item.title }}</span>
|
||||
<span>{{ parseExpression(item.expression) }}</span>
|
||||
</div>
|
||||
<div class="action">
|
||||
<Button :icon="h(CodeOutlined)" type="primary" @click="testExpression(item)">测试</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="result-item-expression mt-3">
|
||||
<Tiptap v-model="item.expression" class="w-full bg-white rounded outline-none p-3 bg-none resize-none"
|
||||
:placeholder="`请输入 ${item.title} 的计算公式`" />
|
||||
<!-- <textarea class="w-full h-[66px] rounded outline-none p-3 bg-none resize-none" v-model="item.expression"
|
||||
:placeholder="`请输入${item.title}计算公式`" /> -->
|
||||
:placeholder="`请输入 ${item.title} 的计算公式`"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="hidden">
|
||||
<DataField />
|
||||
<DataField />
|
||||
<Button type="primary" @click="showMessage">test</Button>
|
||||
<p>输出计算</p>
|
||||
</div> -->
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {message,Button} from "ant-design-vue";
|
||||
import {h, ref} from "vue";
|
||||
import { CodeOutlined, SaveOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import { message } from "ant-design-vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
import { expressionList, saveExpression } from "@/service/api/result";
|
||||
import {expressionList, saveExpression} from "@/service/api/result";
|
||||
|
||||
import PageHeader from "@/components/page-header.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 input from "./test/data-input.ts"
|
||||
import {getAllProduct} from "@/service/use-result-vars.ts";
|
||||
|
||||
const ResultExpressionList = ref<ResultExpression[]>([]);
|
||||
|
||||
expressionList().then((res) => {
|
||||
console.log(res)
|
||||
ResultExpressionList.value = res.list;
|
||||
});
|
||||
const {loading,run:save} = useRequest(()=> saveExpression(ResultExpressionList.value),{
|
||||
const productValues = getAllProduct();
|
||||
const {loading, run: save} = useRequest(() => saveExpression(ResultExpressionList.value), {
|
||||
manual: true,
|
||||
onSuccess() {
|
||||
message.success("保存成功");
|
||||
}
|
||||
})
|
||||
function runCode(expression:string,vars: any){
|
||||
return new Function('vars',`with(vars) { return ${expression};}`)(vars)
|
||||
}
|
||||
|
||||
function testExpression(item: ResultExpression) {
|
||||
const expression = parseExpression(item.expression);
|
||||
const result = runCode(expression,{
|
||||
...(productValues.value),
|
||||
input,
|
||||
})
|
||||
|
||||
console.log('result',result)
|
||||
// console.log('expression =>', expression,input,productValues.value)
|
||||
}
|
||||
|
||||
function parseExpression(str: string) {
|
||||
if (!str) return;
|
||||
const doc = JSON.parse(str) as TiptapContentValue;
|
||||
if (!doc.content || doc.content.length == 0) {
|
||||
return '';
|
||||
}
|
||||
const expressionList = doc.content[0].content;
|
||||
if (!expressionList) return '';
|
||||
const expression = expressionList.map(item => {
|
||||
if (item.type == 'text') {
|
||||
return item.text;
|
||||
}
|
||||
return item.attrs.id
|
||||
}).join('');
|
||||
return expression;
|
||||
// console.log(JSON.stringify({content:doc.content[0].content}))
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -57,27 +99,4 @@ const {loading,run:save} = useRequest(()=> saveExpression(ResultExpressionList.v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .result-calc-expression-list-container {}
|
||||
|
||||
// .result-item {
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// margin-bottom: 20px;
|
||||
|
||||
|
||||
// .result-item-title {
|
||||
// font-size: 14px;
|
||||
// font-weight: 500;
|
||||
// color: #333333;
|
||||
// margin-bottom: 10px;
|
||||
// }
|
||||
|
||||
// .result-item-expression {}
|
||||
|
||||
// textarea {
|
||||
// width: 100%;
|
||||
// height: 40px;
|
||||
// outline: none;
|
||||
// }
|
||||
// }</style>
|
||||
</style>
|
50
src/pages/result/test/data-input.ts
Normal file
50
src/pages/result/test/data-input.ts
Normal file
@ -0,0 +1,50 @@
|
||||
export default {
|
||||
"weight": 50,
|
||||
"niaosu": 10,
|
||||
"ruineng": 1,
|
||||
"ruidai": 1,
|
||||
"ruixian": 0,
|
||||
"ruigao": 0,
|
||||
"ruisu": 0,
|
||||
"nengquanli": 0,
|
||||
"kangquanli": 0,
|
||||
"kangquangan": 0,
|
||||
"baipuli": 0,
|
||||
"ailunduo": 0,
|
||||
"weiwo": 0,
|
||||
"jiaweiti": 0,
|
||||
"yilijia": 0,
|
||||
"ruiyixi": 0,
|
||||
"nengquansu": 0,
|
||||
"ansu": 0,
|
||||
"quanansu": 0,
|
||||
"yilijia100": 0,
|
||||
"shui": 0,
|
||||
"anjisuan_ruye": 0,
|
||||
"yilijia100_ruye": 0,
|
||||
"quanansu_ruye": 0,
|
||||
"ansu_ruye": 0,
|
||||
"nengquansu_ruye": 0,
|
||||
"ruqingdanbailiang": 0,
|
||||
"ruianji": 0,
|
||||
"quanyingda": 0,
|
||||
"likawen": 0,
|
||||
"lefanming85": 0,
|
||||
"lefanming114": 0,
|
||||
"anjisuan": 0,
|
||||
"litai": 0,
|
||||
"lineng": 0,
|
||||
"liwen": 0,
|
||||
"youwen": 0,
|
||||
"yingtuolipite20": 0,
|
||||
"yingtuolipite30": 0,
|
||||
"putaotangluhuana5": 0,
|
||||
"putaotang5": 0,
|
||||
"putaotang10": 0,
|
||||
"putaotang50": 0,
|
||||
"luhuana09": 0,
|
||||
"luhuana10": 0,
|
||||
"geliefusi": 0,
|
||||
"luhuajia": 0,
|
||||
"baidanbai": 0
|
||||
}
|
718
src/pages/result/test/parser.js
Normal file
718
src/pages/result/test/parser.js
Normal file
@ -0,0 +1,718 @@
|
||||
/*
|
||||
* Generated by PEG.js 0.10.0.
|
||||
*
|
||||
* http://pegjs.org/
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
function peg$subclass(child, parent) {
|
||||
function ctor() { this.constructor = child; }
|
||||
ctor.prototype = parent.prototype;
|
||||
child.prototype = new ctor();
|
||||
}
|
||||
|
||||
function peg$SyntaxError(message, expected, found, location) {
|
||||
this.message = message;
|
||||
this.expected = expected;
|
||||
this.found = found;
|
||||
this.location = location;
|
||||
this.name = "SyntaxError";
|
||||
|
||||
if (typeof Error.captureStackTrace === "function") {
|
||||
Error.captureStackTrace(this, peg$SyntaxError);
|
||||
}
|
||||
}
|
||||
|
||||
peg$subclass(peg$SyntaxError, Error);
|
||||
|
||||
peg$SyntaxError.buildMessage = function(expected, found) {
|
||||
var DESCRIBE_EXPECTATION_FNS = {
|
||||
literal: function(expectation) {
|
||||
return "\"" + literalEscape(expectation.text) + "\"";
|
||||
},
|
||||
|
||||
"class": function(expectation) {
|
||||
var escapedParts = "",
|
||||
i;
|
||||
|
||||
for (i = 0; i < expectation.parts.length; i++) {
|
||||
escapedParts += expectation.parts[i] instanceof Array
|
||||
? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])
|
||||
: classEscape(expectation.parts[i]);
|
||||
}
|
||||
|
||||
return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
|
||||
},
|
||||
|
||||
any: function(expectation) {
|
||||
return "any character";
|
||||
},
|
||||
|
||||
end: function(expectation) {
|
||||
return "end of input";
|
||||
},
|
||||
|
||||
other: function(expectation) {
|
||||
return expectation.description;
|
||||
}
|
||||
};
|
||||
|
||||
function hex(ch) {
|
||||
return ch.charCodeAt(0).toString(16).toUpperCase();
|
||||
}
|
||||
|
||||
function literalEscape(s) {
|
||||
return s
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\0/g, '\\0')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
|
||||
}
|
||||
|
||||
function classEscape(s) {
|
||||
return s
|
||||
.replace(/\\/g, '\\\\')
|
||||
.replace(/\]/g, '\\]')
|
||||
.replace(/\^/g, '\\^')
|
||||
.replace(/-/g, '\\-')
|
||||
.replace(/\0/g, '\\0')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
|
||||
}
|
||||
|
||||
function describeExpectation(expectation) {
|
||||
return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
|
||||
}
|
||||
|
||||
function describeExpected(expected) {
|
||||
var descriptions = new Array(expected.length),
|
||||
i, j;
|
||||
|
||||
for (i = 0; i < expected.length; i++) {
|
||||
descriptions[i] = describeExpectation(expected[i]);
|
||||
}
|
||||
|
||||
descriptions.sort();
|
||||
|
||||
if (descriptions.length > 0) {
|
||||
for (i = 1, j = 1; i < descriptions.length; i++) {
|
||||
if (descriptions[i - 1] !== descriptions[i]) {
|
||||
descriptions[j] = descriptions[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
descriptions.length = j;
|
||||
}
|
||||
|
||||
switch (descriptions.length) {
|
||||
case 1:
|
||||
return descriptions[0];
|
||||
|
||||
case 2:
|
||||
return descriptions[0] + " or " + descriptions[1];
|
||||
|
||||
default:
|
||||
return descriptions.slice(0, -1).join(", ")
|
||||
+ ", or "
|
||||
+ descriptions[descriptions.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
function describeFound(found) {
|
||||
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
|
||||
}
|
||||
|
||||
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
|
||||
};
|
||||
|
||||
function peg$parse(input, options) {
|
||||
options = options !== void 0 ? options : {};
|
||||
|
||||
var peg$FAILED = {},
|
||||
|
||||
peg$startRuleFunctions = { start: peg$parsestart },
|
||||
peg$startRuleFunction = peg$parsestart,
|
||||
|
||||
peg$c0 = "+",
|
||||
peg$c1 = peg$literalExpectation("+", false),
|
||||
peg$c2 = "-",
|
||||
peg$c3 = peg$literalExpectation("-", false),
|
||||
peg$c4 = function(left, op, right) {
|
||||
return op === "+" ? left + right : left - right;
|
||||
},
|
||||
peg$c5 = "*",
|
||||
peg$c6 = peg$literalExpectation("*", false),
|
||||
peg$c7 = "/",
|
||||
peg$c8 = peg$literalExpectation("/", false),
|
||||
peg$c9 = function(left, op, right) {
|
||||
return op === "*" ? left * right : left / right;
|
||||
},
|
||||
peg$c10 = "(",
|
||||
peg$c11 = peg$literalExpectation("(", false),
|
||||
peg$c12 = ")",
|
||||
peg$c13 = peg$literalExpectation(")", false),
|
||||
peg$c14 = function(expr) { return expr; },
|
||||
peg$c15 = function() { return -factor; },
|
||||
peg$c16 = /^[a-zA-Z_]/,
|
||||
peg$c17 = peg$classExpectation([["a", "z"], ["A", "Z"], "_"], false, false),
|
||||
peg$c18 = /^[a-zA-Z0-9_]/,
|
||||
peg$c19 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"], "_"], false, false),
|
||||
peg$c20 = function(name) { return vars[name.join("")] || 0; },
|
||||
peg$c21 = /^[0-9]/,
|
||||
peg$c22 = peg$classExpectation([["0", "9"]], false, false),
|
||||
peg$c23 = ".",
|
||||
peg$c24 = peg$literalExpectation(".", false),
|
||||
peg$c25 = function() { return parseFloat(text()); },
|
||||
peg$c26 = /^[ \t\r\n]/,
|
||||
peg$c27 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false),
|
||||
|
||||
peg$currPos = 0,
|
||||
peg$savedPos = 0,
|
||||
peg$posDetailsCache = [{ line: 1, column: 1 }],
|
||||
peg$maxFailPos = 0,
|
||||
peg$maxFailExpected = [],
|
||||
peg$silentFails = 0,
|
||||
|
||||
peg$result;
|
||||
|
||||
if ("startRule" in options) {
|
||||
if (!(options.startRule in peg$startRuleFunctions)) {
|
||||
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
||||
}
|
||||
|
||||
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
||||
}
|
||||
|
||||
function text() {
|
||||
return input.substring(peg$savedPos, peg$currPos);
|
||||
}
|
||||
|
||||
function location() {
|
||||
return peg$computeLocation(peg$savedPos, peg$currPos);
|
||||
}
|
||||
|
||||
function expected(description, location) {
|
||||
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
|
||||
|
||||
throw peg$buildStructuredError(
|
||||
[peg$otherExpectation(description)],
|
||||
input.substring(peg$savedPos, peg$currPos),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function error(message, location) {
|
||||
location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
|
||||
|
||||
throw peg$buildSimpleError(message, location);
|
||||
}
|
||||
|
||||
function peg$literalExpectation(text, ignoreCase) {
|
||||
return { type: "literal", text: text, ignoreCase: ignoreCase };
|
||||
}
|
||||
|
||||
function peg$classExpectation(parts, inverted, ignoreCase) {
|
||||
return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
|
||||
}
|
||||
|
||||
function peg$anyExpectation() {
|
||||
return { type: "any" };
|
||||
}
|
||||
|
||||
function peg$endExpectation() {
|
||||
return { type: "end" };
|
||||
}
|
||||
|
||||
function peg$otherExpectation(description) {
|
||||
return { type: "other", description: description };
|
||||
}
|
||||
|
||||
function peg$computePosDetails(pos) {
|
||||
var details = peg$posDetailsCache[pos], p;
|
||||
|
||||
if (details) {
|
||||
return details;
|
||||
} else {
|
||||
p = pos - 1;
|
||||
while (!peg$posDetailsCache[p]) {
|
||||
p--;
|
||||
}
|
||||
|
||||
details = peg$posDetailsCache[p];
|
||||
details = {
|
||||
line: details.line,
|
||||
column: details.column
|
||||
};
|
||||
|
||||
while (p < pos) {
|
||||
if (input.charCodeAt(p) === 10) {
|
||||
details.line++;
|
||||
details.column = 1;
|
||||
} else {
|
||||
details.column++;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
peg$posDetailsCache[pos] = details;
|
||||
return details;
|
||||
}
|
||||
}
|
||||
|
||||
function peg$computeLocation(startPos, endPos) {
|
||||
var startPosDetails = peg$computePosDetails(startPos),
|
||||
endPosDetails = peg$computePosDetails(endPos);
|
||||
|
||||
return {
|
||||
start: {
|
||||
offset: startPos,
|
||||
line: startPosDetails.line,
|
||||
column: startPosDetails.column
|
||||
},
|
||||
end: {
|
||||
offset: endPos,
|
||||
line: endPosDetails.line,
|
||||
column: endPosDetails.column
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function peg$fail(expected) {
|
||||
if (peg$currPos < peg$maxFailPos) { return; }
|
||||
|
||||
if (peg$currPos > peg$maxFailPos) {
|
||||
peg$maxFailPos = peg$currPos;
|
||||
peg$maxFailExpected = [];
|
||||
}
|
||||
|
||||
peg$maxFailExpected.push(expected);
|
||||
}
|
||||
|
||||
function peg$buildSimpleError(message, location) {
|
||||
return new peg$SyntaxError(message, null, null, location);
|
||||
}
|
||||
|
||||
function peg$buildStructuredError(expected, found, location) {
|
||||
return new peg$SyntaxError(
|
||||
peg$SyntaxError.buildMessage(expected, found),
|
||||
expected,
|
||||
found,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
function peg$parsestart() {
|
||||
var s0;
|
||||
|
||||
s0 = peg$parseexpression();
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parseexpression() {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parseterm();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse_();
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 43) {
|
||||
s3 = peg$c0;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c1); }
|
||||
}
|
||||
if (s3 === peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 45) {
|
||||
s3 = peg$c2;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c3); }
|
||||
}
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parse_();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parseexpression();
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$c4(s1, s3, s5);
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parseterm();
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parseterm() {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parsefactor();
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse_();
|
||||
if (s2 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 42) {
|
||||
s3 = peg$c5;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c6); }
|
||||
}
|
||||
if (s3 === peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 47) {
|
||||
s3 = peg$c7;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c8); }
|
||||
}
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parse_();
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parseterm();
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$c9(s1, s3, s5);
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parsefactor();
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parsefactor() {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 40) {
|
||||
s1 = peg$c10;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c11); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parse_();
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parseexpression();
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parse_();
|
||||
if (s4 !== peg$FAILED) {
|
||||
if (input.charCodeAt(peg$currPos) === 41) {
|
||||
s5 = peg$c12;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s5 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c13); }
|
||||
}
|
||||
if (s5 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$c14(s3);
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 45) {
|
||||
s1 = peg$c2;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c3); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsefactor();
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$c15();
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parsevariable();
|
||||
if (s0 === peg$FAILED) {
|
||||
s0 = peg$parsenumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parsevariable() {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (peg$c16.test(input.charAt(peg$currPos))) {
|
||||
s1 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c17); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = [];
|
||||
if (peg$c18.test(input.charAt(peg$currPos))) {
|
||||
s3 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c19); }
|
||||
}
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
if (peg$c18.test(input.charAt(peg$currPos))) {
|
||||
s3 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c19); }
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$c20(s1);
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parsenumber() {
|
||||
var s0, s1, s2, s3, s4, s5, s6;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 45) {
|
||||
s1 = peg$c2;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c3); }
|
||||
}
|
||||
if (s1 === peg$FAILED) {
|
||||
s1 = null;
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = [];
|
||||
if (peg$c21.test(input.charAt(peg$currPos))) {
|
||||
s3 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c22); }
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
if (peg$c21.test(input.charAt(peg$currPos))) {
|
||||
s3 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c22); }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 46) {
|
||||
s4 = peg$c23;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c24); }
|
||||
}
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = [];
|
||||
if (peg$c21.test(input.charAt(peg$currPos))) {
|
||||
s6 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s6 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c22); }
|
||||
}
|
||||
if (s6 !== peg$FAILED) {
|
||||
while (s6 !== peg$FAILED) {
|
||||
s5.push(s6);
|
||||
if (peg$c21.test(input.charAt(peg$currPos))) {
|
||||
s6 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s6 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c22); }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s5 = peg$FAILED;
|
||||
}
|
||||
if (s5 !== peg$FAILED) {
|
||||
s4 = [s4, s5];
|
||||
s3 = s4;
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s3;
|
||||
s3 = peg$FAILED;
|
||||
}
|
||||
if (s3 === peg$FAILED) {
|
||||
s3 = null;
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s1 = peg$c25();
|
||||
s0 = s1;
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
function peg$parse_() {
|
||||
var s0, s1;
|
||||
|
||||
s0 = [];
|
||||
if (peg$c26.test(input.charAt(peg$currPos))) {
|
||||
s1 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c27); }
|
||||
}
|
||||
while (s1 !== peg$FAILED) {
|
||||
s0.push(s1);
|
||||
if (peg$c26.test(input.charAt(peg$currPos))) {
|
||||
s1 = input.charAt(peg$currPos);
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$c27); }
|
||||
}
|
||||
}
|
||||
|
||||
return s0;
|
||||
}
|
||||
|
||||
peg$result = peg$startRuleFunction();
|
||||
|
||||
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
|
||||
return peg$result;
|
||||
} else {
|
||||
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
|
||||
peg$fail(peg$endExpectation());
|
||||
}
|
||||
|
||||
throw peg$buildStructuredError(
|
||||
peg$maxFailExpected,
|
||||
peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
|
||||
peg$maxFailPos < input.length
|
||||
? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
|
||||
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SyntaxError: peg$SyntaxError,
|
||||
parse: peg$parse
|
||||
};
|
121
src/pages/result/var.vue
Normal file
121
src/pages/result/var.vue
Normal file
@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="dropdown-menu">
|
||||
<div class="dropdown-menu-list" v-if="items.length">
|
||||
<div
|
||||
class="dropdown-item"
|
||||
:class="{ 'is-selected': index === selectedIndex }"
|
||||
v-for="(item, index) in varList"
|
||||
:key="index"
|
||||
@click="selectItem(index)"
|
||||
>
|
||||
<div class="label"> {{ item.text }}</div>
|
||||
<span class="value">{{item.value}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="not-exists" v-else>
|
||||
<span>数据指标不存在</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {getProductValue} from "@/service/use-result-vars.js";
|
||||
import {watch, ref} from "vue";
|
||||
|
||||
const productList = getProductValue();
|
||||
const varList = ref<ResultVarItem[] >([])
|
||||
|
||||
const props = defineProps({
|
||||
items: {
|
||||
type: Array,
|
||||
},
|
||||
query:{
|
||||
type: String,
|
||||
},
|
||||
command: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const selectedIndex = ref(0)
|
||||
|
||||
watch(()=>props.query, () => {
|
||||
selectedIndex.value = 0;
|
||||
if(props.query){
|
||||
varList.value = productList.value.filter(item => (
|
||||
item.value.includes(props.query) || item.label.includes(props.query) || item.text.includes(props.query)
|
||||
)).filter((_,index)=> index < 10)
|
||||
}else{
|
||||
varList.value = productList.value.filter((_,index)=> index < 10)
|
||||
}
|
||||
});
|
||||
|
||||
const upHandler = () => {
|
||||
selectedIndex.value = ((selectedIndex.value + varList.value.length) - 1) % varList.value.length
|
||||
}
|
||||
const downHandler = () => {
|
||||
selectedIndex.value = (selectedIndex.value + 1) % varList.value.length
|
||||
}
|
||||
const enterHandler = () => {
|
||||
selectItem(selectedIndex.value)
|
||||
}
|
||||
const selectItem = (index) => {
|
||||
const item = varList.value[index]
|
||||
if (item) {
|
||||
props.command({id: item.value, label: item.text || item.label})
|
||||
}
|
||||
// selectedIndex.value = index
|
||||
}
|
||||
const onKeyDown = ({event}: { event: { key: string } }) => {
|
||||
if (event.key === 'ArrowUp') {
|
||||
upHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowDown') {
|
||||
downHandler()
|
||||
return true
|
||||
}
|
||||
|
||||
if (event.key === 'Enter') {
|
||||
enterHandler()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
defineExpose({onKeyDown})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* Dropdown menu */
|
||||
.dropdown-menu-list{}
|
||||
.dropdown-menu-list{}
|
||||
.dropdown-menu {
|
||||
@apply bg-white relative overflow-auto flex flex-col shadow rounded border border-gray-200;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@apply w-full p-2 gap-2 bg-transparent flex items-center cursor-pointer justify-between;
|
||||
text-align: left;
|
||||
|
||||
&:hover,
|
||||
&:hover.is-selected {
|
||||
@apply bg-gray-200;
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
@apply bg-gray-100;
|
||||
}
|
||||
.label{
|
||||
@apply text-gray-800;
|
||||
}
|
||||
.value{
|
||||
@apply text-gray-300 text-sm;
|
||||
}
|
||||
}
|
||||
|
||||
.not-exists {
|
||||
@apply p-2;
|
||||
}
|
||||
</style>
|
64
src/pages/result/vars.ts
Normal file
64
src/pages/result/vars.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import {VueRenderer} from '@tiptap/vue-3'
|
||||
import tippy from 'tippy.js'
|
||||
|
||||
import vars from './var.vue'
|
||||
|
||||
export default {
|
||||
items: ({query}) => {
|
||||
return ['1,2,3']
|
||||
},
|
||||
|
||||
render: () => {
|
||||
let component
|
||||
let popup
|
||||
|
||||
return {
|
||||
onStart: props => {
|
||||
component = new VueRenderer(vars, {
|
||||
props,
|
||||
editor: props.editor,
|
||||
})
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
popup = tippy('body', {
|
||||
getReferenceClientRect: props.clientRect,
|
||||
appendTo: () => document.body,
|
||||
content: component.element,
|
||||
showOnCreate: true,
|
||||
interactive: true,
|
||||
trigger: 'manual',
|
||||
placement: 'bottom-start',
|
||||
})
|
||||
},
|
||||
|
||||
onUpdate(props) {
|
||||
component.updateProps(props)
|
||||
|
||||
if (!props.clientRect) {
|
||||
return
|
||||
}
|
||||
|
||||
popup[0].setProps({
|
||||
getReferenceClientRect: props.clientRect,
|
||||
})
|
||||
},
|
||||
|
||||
onKeyDown(props) {
|
||||
if (props.event.key === 'Escape') {
|
||||
popup[0].hide()
|
||||
return true
|
||||
}
|
||||
// 将查询字符透传给组件
|
||||
return component.ref?.onKeyDown?.(props)
|
||||
},
|
||||
|
||||
onExit() {
|
||||
popup[0]?.destroy?.()
|
||||
component?.destroy?.()
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
@ -31,6 +31,15 @@ export const routes:RouteRecordRaw[] = [
|
||||
},
|
||||
component: () => import('./pages/result/index.vue')
|
||||
},
|
||||
{
|
||||
path: 'ttt',
|
||||
name: 'ttt',
|
||||
meta: {
|
||||
title: '输出计算',
|
||||
icon:'icon-calculator'
|
||||
},
|
||||
component: () => import('./pages/T.vue')
|
||||
},
|
||||
{
|
||||
path: 'product-data',
|
||||
name: 'product',
|
||||
|
@ -1,19 +1,6 @@
|
||||
import { sleep } from "@/core/sleep";
|
||||
import { post } from "./request";
|
||||
|
||||
export const ProductCols = [
|
||||
{ id: 1, name: "能量密度", alias: "power" },
|
||||
{ id: 2, name: "蛋白Pro", alias: "protein" },
|
||||
{ id: 3, name: "Glu", alias: "glu" },
|
||||
{ id: 4, name: "Fat", alias: "fat" },
|
||||
{ id: 5, name: "纤维素", alias: "cellulose" },
|
||||
{ id: 6, name: "Na", alias: "na" },
|
||||
{ id: 7, name: "K", alias: "k" },
|
||||
{ id: 8, name: "Ca", alias: "ca" },
|
||||
{ id: 9, name: "P", alias: "p" },
|
||||
{ id: 10, name: "Mg", alias: "mg" },
|
||||
];
|
||||
|
||||
export async function expressionList() {
|
||||
await sleep(200);
|
||||
return await post<DataList<ResultExpression>>(`/result/expression/all`);
|
||||
|
256
src/service/use-result-vars.ts
Normal file
256
src/service/use-result-vars.ts
Normal file
@ -0,0 +1,256 @@
|
||||
import {getList} from "@/service/api/product.ts";
|
||||
import {ref} from "vue";
|
||||
|
||||
type InputValue = {
|
||||
name: string;
|
||||
key: string;
|
||||
unit?: string;
|
||||
placeholder?: string;
|
||||
type?: string;
|
||||
addition?: {
|
||||
key: string
|
||||
placeholder: string
|
||||
unit?: string;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"weight": 50,
|
||||
"niaosu": 12,
|
||||
"ruineng": 10,
|
||||
"ruidai": 0,
|
||||
"ruixian": 0,
|
||||
"ruigao": 0,
|
||||
"ruisu": 0,
|
||||
"nengquanli": 0,
|
||||
"kangquanli": 0,
|
||||
"kangquangan": 0,
|
||||
"baipuli": 0,
|
||||
"ailunduo": 0,
|
||||
"weiwo": 0,
|
||||
"jiaweiti": 0,
|
||||
"yilijia": 0,
|
||||
"ruiyixi": 0,
|
||||
"nengquansu": 0,
|
||||
"ansu": 0,
|
||||
"quanansu": 0,
|
||||
"yilijia100": 0,
|
||||
"shui": 0,
|
||||
"anjisuan_ruye": 0,
|
||||
"yilijia100_ruye": 0,
|
||||
"quanansu_ruye": 0,
|
||||
"ansu_ruye": 0,
|
||||
"nengquansu_ruye": 0,
|
||||
"ruqingdanbailiang": 0,
|
||||
"ruianji": 0,
|
||||
"quanyingda": 0,
|
||||
"likawen": 0,
|
||||
"lefanming85": 0,
|
||||
"lefanming114": 0,
|
||||
"anjisuan": 0,
|
||||
"litai": 0,
|
||||
"lineng": 0,
|
||||
"liwen": 0,
|
||||
"youwen": 0,
|
||||
"yingtuolipite20": 0,
|
||||
"yingtuolipite30": 0,
|
||||
"putaotangluhuana5": 0,
|
||||
"putaotang5": 0,
|
||||
"putaotang10": 0,
|
||||
"putaotang50": 0,
|
||||
"luhuana09": 0,
|
||||
"luhuana10": 0,
|
||||
"geliefusi": 0,
|
||||
"luhuajia": 0,
|
||||
"baidanbai": 0
|
||||
}
|
||||
*/
|
||||
const inputList: InputValue[] = [
|
||||
{name: '体重', key: 'weight',},
|
||||
{name: '24h尿素', key: 'niaosu',},
|
||||
// 肠内制剂
|
||||
{name: '瑞能', key: 'ruineng', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '瑞代', key: 'ruidai', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '瑞先', key: 'ruixian', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '瑞高', key: 'ruigao', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '瑞素', key: 'ruisu', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '能全力', key: 'nengquanli', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '康全力', key: 'kangquanli', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '康全甘', key: 'kangquangan', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'}, // 新增
|
||||
{name: '百普力', key: 'baipuli', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '爱伦多', key: 'ailunduo', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '维沃', key: 'weiwo', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
// 新增 230409
|
||||
{name: '佳维体', key: 'jiaweiti', 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: 'nengquansu',
|
||||
placeholder: '入量(勺)',
|
||||
unit: 'ml',
|
||||
type: 'gut',
|
||||
addition: {key: 'nengquansu_ruye', placeholder: '入液量(ml)'}
|
||||
},
|
||||
{
|
||||
name: '安素',
|
||||
key: 'ansu',
|
||||
placeholder: '入量(勺)',
|
||||
unit: '勺',
|
||||
type: 'gut',
|
||||
addition: {key: 'ansu_ruye', placeholder: '入液量(ml)'}
|
||||
},
|
||||
{
|
||||
name: '全安素',
|
||||
key: 'quanansu',
|
||||
placeholder: '入量(勺)',
|
||||
unit: '勺',
|
||||
type: 'gut',
|
||||
addition: {key: 'quanansu_ruye', placeholder: '入液量(ml)'}
|
||||
},
|
||||
// 新增 230409
|
||||
{
|
||||
name: '益力佳',
|
||||
key: 'yilijia100',
|
||||
placeholder: '入量(勺)',
|
||||
unit: 'ml',
|
||||
type: 'gut',
|
||||
addition: {key: 'yilijia100_ruye', placeholder: '入液量(ml)'}
|
||||
},
|
||||
// o water
|
||||
{
|
||||
name: '乳清蛋白量(g)',
|
||||
key: 'ruqingdanbailiang',
|
||||
placeholder: '入量(g)',
|
||||
unit: 'g',
|
||||
type: 'gut',
|
||||
addition: {key: 'ruqingdanbailiang_ruye', placeholder: '入液量(ml)'}
|
||||
},
|
||||
|
||||
// { name: '雀巢Beneprotein', key: 'quecaoBeneprotein', placeholder: '入量(g)',unit:'g',type: 'gut' },
|
||||
{name: '瑞安吉', key: 'ruianji', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
|
||||
// 静脉制剂
|
||||
// { name: '卡文1440ml', key: 'kawen1440', placeholder: '入液量(ml)', unit:'ml', type: 'vein' },
|
||||
// { name: '卡文1920ml', key: 'kawen1920', placeholder: '入液量(ml)', unit:'ml', type: 'vein' },
|
||||
// 新增 230409
|
||||
{name: '水', key: 'shui', placeholder: '入液量(ml)', unit: 'ml', type: 'gut'},
|
||||
{name: '全营达', key: 'quanyingda', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '力卡文', key: 'likawen', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
|
||||
|
||||
{name: '乐凡命8.5%', key: 'lefanming85', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '乐凡命11.4%', key: 'lefanming114', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{
|
||||
name: '其他氨基酸',
|
||||
key: 'anjisuan',
|
||||
placeholder: '入液量(ml)',
|
||||
unit: 'ml',
|
||||
type: 'vein',
|
||||
addition: {key: 'anjisuan_ruye', placeholder: '', unit: '%',}
|
||||
},
|
||||
{name: '力太', key: 'litai', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
|
||||
{name: '力能', key: 'lineng', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '力文', key: 'liwen', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '尤文', key: 'youwen', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '英脱利匹特20%', key: 'yingtuolipite20', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},// 新增
|
||||
{name: '英脱利匹特30%', key: 'yingtuolipite30', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},// 新增
|
||||
{name: '5%葡萄糖氯化钠', key: 'putaotangluhuana5', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},// 新增
|
||||
{name: '5%葡萄糖', key: 'putaotang5', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '10%葡萄糖', key: 'putaotang10', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '50%葡萄糖', key: 'putaotang50', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '0.9%氯化钠', key: 'luhuana09', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '10%氯化钠', key: 'luhuana10', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '格列福斯', key: 'geliefusi', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
{name: '氯化钾', key: 'luhuajia', placeholder: '入液量(ml)', unit: 'ml', type: 'vein'},
|
||||
// { name: '其他液体', key: 'qitayeti', placeholder: '入液量(ml)', unit:'ml', type: 'vein' }, // 新增
|
||||
{name: '白蛋白', key: 'baidanbai', placeholder: '入液量(g)', unit: 'ml', type: 'vein'}, // 新增
|
||||
]
|
||||
|
||||
export function getInputValue() {
|
||||
const list: ResultVarItem[] = [];
|
||||
inputList.forEach(item => {
|
||||
|
||||
if (item.addition) {
|
||||
const additionExt = item.addition.placeholder || item.addition.unit
|
||||
list.push({
|
||||
label: `${item.name}${additionExt ? '-' + additionExt : ''}`,
|
||||
text: `${item.name}${additionExt ? '-' + additionExt : ''}`,
|
||||
value: `input.${item.addition.key}`,
|
||||
})
|
||||
}
|
||||
const ext = item.placeholder || item.unit
|
||||
list.push({
|
||||
label: `${item.name}${ext ? '-' + ext : ''}`,
|
||||
text: `${item.name}${ext ? '-' + ext : ''}`,
|
||||
value: `input.${item.key}`,
|
||||
})
|
||||
})
|
||||
return list
|
||||
}
|
||||
|
||||
const ValueKeys = [
|
||||
'power',
|
||||
'protein',
|
||||
'glu',
|
||||
'fat',
|
||||
'cellulose',
|
||||
'na',
|
||||
'k',
|
||||
'ca',
|
||||
'p',
|
||||
'mg',
|
||||
]
|
||||
|
||||
export function getAllProduct() {
|
||||
const list = ref<{
|
||||
[key: string]: ProductInfoModel
|
||||
}>([])
|
||||
getList({
|
||||
page: 1,
|
||||
limit: 10000
|
||||
}).then(res => {
|
||||
const data: {
|
||||
[key: string]: ProductInfoModel
|
||||
} = {}
|
||||
res.list.forEach(it => {
|
||||
data[it.alias] = it;
|
||||
})
|
||||
list.value = data
|
||||
});
|
||||
return list
|
||||
}
|
||||
|
||||
export function getProductValue() {
|
||||
const list = ref<ResultVarItem[]>(getInputValue())
|
||||
|
||||
getList({
|
||||
page: 1,
|
||||
limit: 10000
|
||||
}).then(res => {
|
||||
const _list: ResultVarItem[] = [];
|
||||
res.list.forEach(it => {
|
||||
ValueKeys.forEach(key => {
|
||||
const label = `${it.name}-${key}`
|
||||
_list.push({
|
||||
label,
|
||||
value: `${it.alias}.${key}`,
|
||||
text: label,
|
||||
})
|
||||
// _list.push({
|
||||
// label: `${it.name}.${key}`,
|
||||
// value: `${it.alias}.${key}`,
|
||||
// text: label,
|
||||
// })
|
||||
})
|
||||
})
|
||||
list.value = [
|
||||
...list.value,
|
||||
..._list,
|
||||
];
|
||||
})
|
||||
return list;
|
||||
}
|
@ -62,7 +62,6 @@ export const useUserStore = defineStore('counter', () => {
|
||||
console.log('401 show login')
|
||||
}
|
||||
}).finally(() => {
|
||||
console.log('onMounted inited')
|
||||
setTimeout(() => {
|
||||
userInit.value = true
|
||||
}, 500)
|
||||
|
23
src/types/product.d.ts
vendored
23
src/types/product.d.ts
vendored
@ -34,4 +34,25 @@ declare type ResultExpression = {
|
||||
created_at: Date | string;
|
||||
updated_at: Date | string;
|
||||
status: number;
|
||||
}
|
||||
}
|
||||
declare type ResultVarItem = {
|
||||
label: string;
|
||||
value: string;
|
||||
text?: string;
|
||||
}
|
||||
declare type TiptapContentValue = {
|
||||
type:string;
|
||||
content: {
|
||||
type:string;
|
||||
content: ExpressionValue[];
|
||||
}[];
|
||||
}
|
||||
|
||||
interface ExpressionValue {
|
||||
type: 'text'|'mention';
|
||||
attrs: {
|
||||
id: string;
|
||||
label: string;
|
||||
}
|
||||
text: string;
|
||||
}
|
||||
|
@ -509,6 +509,11 @@
|
||||
prosemirror-transform "^1.10.2"
|
||||
prosemirror-view "^1.37.0"
|
||||
|
||||
"@tiptap/suggestion@^2.10.4":
|
||||
version "2.10.4"
|
||||
resolved "https://registry.npmmirror.com/@tiptap/suggestion/-/suggestion-2.10.4.tgz#732320b65bc55bcc2a33a8f32072f9478ffb7436"
|
||||
integrity sha512-7Bzcn1REA7OmVRxiMF2kVK9EhosXotdLAGaEvSbn4zQtHCJG0tREuYvPy53LGzVuPkBDR6Pf6sp1QbGvSne/8g==
|
||||
|
||||
"@tiptap/vue-3@^2.10.4":
|
||||
version "2.10.4"
|
||||
resolved "https://registry.npmmirror.com/@tiptap/vue-3/-/vue-3-2.10.4.tgz#9d44e4191d6e512673e44f760aceb909dd568132"
|
||||
|
Loading…
x
Reference in New Issue
Block a user