2つのデータ計算コンポーネントを追加する
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<q-tab-panels v-model="tab" animated>
|
<q-tab-panels v-model="tab" animated>
|
||||||
<q-tab-panel name="fields">
|
<q-tab-panel name="fields">
|
||||||
<field-list v-model="selected" type="single" :filter="filter" :appId="appId"></field-list>
|
<field-list v-model="selected" type="single" :filter="filter" :appId="appId" :fields="sourceFields"></field-list>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
|
|
||||||
<q-tab-panel name="vars" >
|
<q-tab-panel name="vars" >
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ref, onMounted, reactive } from 'vue'
|
import { ref, onMounted, reactive, inject } from 'vue'
|
||||||
import FieldList from './FieldList.vue';
|
import FieldList from './FieldList.vue';
|
||||||
import VariableList from './VariableList.vue';
|
import VariableList from './VariableList.vue';
|
||||||
|
|
||||||
@@ -48,10 +48,13 @@ export default {
|
|||||||
filter:String
|
filter:String
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
const selected = ref([]);
|
||||||
|
console.log(selected);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
sourceFields : inject('sourceFields'),
|
||||||
tab: ref('fields'),
|
tab: ref('fields'),
|
||||||
selected: ref([])
|
selected
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="q-pa-md">
|
<div class="q-pa-md">
|
||||||
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type"
|
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type" :selected="modelValue"
|
||||||
:selected="modelValue"
|
@update:selected="$emit('update:modelValue', $event)" :filter="filter" :columns="columns" :rows="rows" />
|
||||||
@update:selected="$emit('update:modelValue', $event)"
|
|
||||||
:filter="filter"
|
|
||||||
:columns="columns" :rows="rows" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { ref, onMounted, reactive } from 'vue'
|
import { useAsyncState } from '@vueuse/core';
|
||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FieldList',
|
name: 'FieldList',
|
||||||
props: {
|
props: {
|
||||||
|
fields: Array,
|
||||||
name: String,
|
name: String,
|
||||||
type: String,
|
type: String,
|
||||||
appId: Number,
|
appId: Number,
|
||||||
modelValue:Array,
|
modelValue: Array,
|
||||||
filter:String
|
filter: String
|
||||||
},
|
},
|
||||||
emits:[
|
emits: [
|
||||||
'update:modelValue'
|
'update:modelValue'
|
||||||
],
|
],
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const isLoaded = ref(false);
|
// const rows = ref([]);
|
||||||
|
// const isLoaded = ref(false);
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'name', required: true, label: 'フィールド名', align: 'left', field: row => row.name, sortable: true },
|
{ name: 'name', required: true, label: 'フィールド名', align: 'left', field: 'name', sortable: true },
|
||||||
{ name: 'code', label: 'フィールドコード', align: 'left', field: 'code', sortable: true },
|
{ name: 'code', label: 'フィールドコード', align: 'left', field: 'code', sortable: true },
|
||||||
{ name: 'type', label: 'フィールドタイプ', align: 'left', field: 'type', sortable: true }
|
{ name: 'type', label: 'フィールドタイプ', align: 'left', field: 'type', sortable: true }
|
||||||
]
|
]
|
||||||
const rows = reactive([]);
|
|
||||||
onMounted(async () => {
|
|
||||||
const res = await api.get('api/v1/appfields', {
|
|
||||||
params: {
|
|
||||||
app: props.appId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let fields = res.data.properties;
|
|
||||||
console.log(fields);
|
|
||||||
Object.keys(fields).forEach((key) => {
|
|
||||||
const fld = fields[key];
|
|
||||||
rows.push({ name: fld.label, objectType: 'field', ...fld });
|
|
||||||
});
|
|
||||||
isLoaded.value = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
const { state : rows, isReady: isLoaded, isLoading } = useAsyncState((args) => {
|
||||||
|
if (props.fields) {
|
||||||
|
return props.fields.map(f => ({ name: f.label, objectType: 'field', ...f }));
|
||||||
|
} else {
|
||||||
|
return api.get('api/v1/appfields', {
|
||||||
|
params: {
|
||||||
|
app: props.appId
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
console.log(res);
|
||||||
|
return Object.values(res.data.properties).map(f => ({ name: f.label, objectType: 'field', ...f }));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [{ name: '', objectType: '', type: '', code: '', label: '' }])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
columns,
|
columns,
|
||||||
rows,
|
rows,
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }">
|
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }">
|
||||||
<q-item :key="index" dense clickable >
|
<q-item :key="index" dense clickable >
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>
|
<q-item-label>
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section side>
|
<q-item-section side>
|
||||||
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
||||||
@@ -128,7 +128,7 @@ interface IAppFields{
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inheritAttrs:false,
|
inheritAttrs:false,
|
||||||
name: 'FieldInput',
|
name: 'AppFieldSelect',
|
||||||
components: {
|
components: {
|
||||||
ShowDialog,
|
ShowDialog,
|
||||||
FieldSelect,
|
FieldSelect,
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-field v-model="tree" :label="displayName" labelColor="primary" stack-label >
|
<q-field v-model="tree" :label="displayName" labelColor="primary" stack-label>
|
||||||
<template v-slot:control >
|
<template v-slot:control>
|
||||||
<q-card flat class="full-width">
|
<q-card flat class="full-width">
|
||||||
<q-card-actions vertical>
|
<q-card-actions vertical>
|
||||||
<q-btn color="grey-3" text-color="black" @click="showDg()">クリックで設定:{{ isSetted?'設定済み':'未設定' }}</q-btn>
|
<q-btn color="grey-3" text-color="black" @click="showDg()">クリックで設定:{{ isSetted ? '設定済み' : '未設定' }}</q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
<q-card-section class="text-caption" >
|
<q-card-section class="text-caption">
|
||||||
<div v-if="!isSetted">{{ placeholder }}</div>
|
<div v-if="!isSetted">{{ placeholder }}</div>
|
||||||
<div v-else>{{ conditionString }}</div>
|
<div v-else>{{ conditionString }}</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
@@ -17,82 +17,109 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref ,watchEffect,computed,reactive} from 'vue';
|
|
||||||
import { ConditionTree,GroupNode,ConditionNode,LogicalOperator,Operator } from 'app/src/types/Conditions';
|
|
||||||
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue'
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'FieldInput',
|
|
||||||
inheritAttrs:false,
|
|
||||||
components: {
|
|
||||||
ConditionEditor
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
displayName:{
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
name:{
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
hint:{
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
modelValue: {
|
|
||||||
type: String,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const appDg = ref();
|
|
||||||
const show = ref(false);
|
|
||||||
const tree = reactive(new ConditionTree());
|
|
||||||
if(props.modelValue && props.modelValue!==''){
|
|
||||||
tree.fromJson(props.modelValue);
|
|
||||||
}else{
|
|
||||||
const newNode = new ConditionNode({},Operator.Equal,'',tree.root);
|
|
||||||
tree.addNode(tree.root,newNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isSetted=ref(props.modelValue && props.modelValue!=='');
|
<script lang="ts">
|
||||||
|
import { ConditionNode, ConditionTree, Operator } from 'app/src/types/Conditions';
|
||||||
|
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
|
||||||
|
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue';
|
||||||
|
|
||||||
const conditionString = computed(()=>{
|
type Props = {
|
||||||
return tree.buildConditionString(tree.root);
|
props?: {
|
||||||
});
|
name: string;
|
||||||
|
modelValue?: {
|
||||||
const showDg = () => {
|
fields: {
|
||||||
show.value = true;
|
type: string;
|
||||||
};
|
label: string;
|
||||||
|
code: string;
|
||||||
const onClosed = (val:string) => {
|
}[]
|
||||||
if (val == 'OK') {
|
|
||||||
const conditionJson = tree.toJson();
|
|
||||||
isSetted.value=true;
|
|
||||||
emit('update:modelValue', conditionJson);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
const conditionJson = tree.toJson();
|
|
||||||
emit('update:modelValue', conditionJson);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
appDg,
|
|
||||||
isSetted,
|
|
||||||
show,
|
|
||||||
showDg,
|
|
||||||
onClosed,
|
|
||||||
tree,
|
|
||||||
conditionString
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
</script>
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'FieldInput',
|
||||||
|
inheritAttrs: false,
|
||||||
|
components: {
|
||||||
|
ConditionEditor
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
context: {
|
||||||
|
type: Array<Props>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
displayName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
hint: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const source = props.context.find(element => element?.props?.name === 'sources')
|
||||||
|
|
||||||
|
if (source) {
|
||||||
|
provide('sourceFields', computed( () => source.props?.modelValue?.fields ?? []));
|
||||||
|
}
|
||||||
|
|
||||||
|
const appDg = ref();
|
||||||
|
const show = ref(false);
|
||||||
|
const tree = reactive(new ConditionTree());
|
||||||
|
if (props.modelValue && props.modelValue !== '') {
|
||||||
|
tree.fromJson(props.modelValue);
|
||||||
|
} else {
|
||||||
|
const newNode = new ConditionNode({}, Operator.Equal, '', tree.root);
|
||||||
|
tree.addNode(tree.root, newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSetted = ref(props.modelValue && props.modelValue !== '');
|
||||||
|
|
||||||
|
const conditionString = computed(() => {
|
||||||
|
return tree.buildConditionString(tree.root);
|
||||||
|
});
|
||||||
|
|
||||||
|
const showDg = () => {
|
||||||
|
show.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClosed = (val: string) => {
|
||||||
|
if (val == 'OK') {
|
||||||
|
const conditionJson = tree.toJson();
|
||||||
|
isSetted.value = true;
|
||||||
|
emit('update:modelValue', conditionJson);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
const conditionJson = tree.toJson();
|
||||||
|
emit('update:modelValue', conditionJson);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
appDg,
|
||||||
|
isSetted,
|
||||||
|
show,
|
||||||
|
showDg,
|
||||||
|
onClosed,
|
||||||
|
tree,
|
||||||
|
conditionString
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|||||||
95
frontend/src/components/right/DataProcessing.vue
Normal file
95
frontend/src/components/right/DataProcessing.vue
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<template>
|
||||||
|
<q-input v-model="value" type="text" :label="displayName" label-color="primary">
|
||||||
|
<q-tooltip persistent no-parent-event v-model="tooltipEnable" anchor="center left" self="center right">
|
||||||
|
<div style="max-width: 24vw; ">
|
||||||
|
<div v-if="p">
|
||||||
|
<div class="row">字段名称:</div>
|
||||||
|
<div class="row q-col-gutter-x-xs q-col-gutter-y-sm">
|
||||||
|
<div class="col-4" style="min-width: 8vw;"
|
||||||
|
v-for="(item, index) in sources?.props?.modelValue?.fields" :key="index">
|
||||||
|
<div style="pointer-events: auto;">{{ item.type }}</div>
|
||||||
|
<div><i>{{ item.label }}</i></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row q-mt-md">示例:</div>
|
||||||
|
<div class="row" style="pointer-events: auto;"> {{ p }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
请先选择计算来源
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-tooltip>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-btn round size="sm" padding="xs" color="secondary" icon="school"
|
||||||
|
@click="() => tooltipEnable = !tooltipEnable" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</q-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { computed, defineComponent, ref } from 'vue';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
props?: {
|
||||||
|
name: string;
|
||||||
|
modelValue?: {
|
||||||
|
fields: {
|
||||||
|
type: string;
|
||||||
|
label: string;
|
||||||
|
code: string;
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'DataProcessing',
|
||||||
|
inheritAttrs: false,
|
||||||
|
props: {
|
||||||
|
context: {
|
||||||
|
type: Array<Props>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
displayName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const value = ref(' ');
|
||||||
|
const tooltipEnable = ref(false);
|
||||||
|
const sources = props.context.find(element => element?.props?.name === 'sources');
|
||||||
|
|
||||||
|
const p = computed(() => {
|
||||||
|
const fields = sources?.props?.modelValue?.fields
|
||||||
|
if (!fields || fields.length === 0) {
|
||||||
|
return '';
|
||||||
|
} else if (fields.length === 1) {
|
||||||
|
return fields[0].type;
|
||||||
|
} else if (fields.length === 2) {
|
||||||
|
return fields.map(field => field.type).join('+');
|
||||||
|
} else {
|
||||||
|
return `(${fields[0].type} + ${fields[1].type}) * ${fields[2].type}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
sources,
|
||||||
|
p,
|
||||||
|
value,
|
||||||
|
tooltipEnable,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="scss"></style>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div v-for="(item, index) in properties" :key="index" >
|
<div v-for="(item, index) in properties" :key="index" >
|
||||||
<component :is="item.component" v-bind="item.props" :connectProps="connectProps(item.props)" v-model="item.props.modelValue"></component>
|
<component :is="item.component" v-bind="item.props" :context="properties" :connectProps="connectProps(item.props)" v-model="item.props.modelValue"></component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -21,6 +21,7 @@ import ConditionInput from '../right/ConditionInput.vue';
|
|||||||
import EventSetter from '../right/EventSetter.vue';
|
import EventSetter from '../right/EventSetter.vue';
|
||||||
import ColorPicker from './ColorPicker.vue';
|
import ColorPicker from './ColorPicker.vue';
|
||||||
import NumInput from './NumInput.vue';
|
import NumInput from './NumInput.vue';
|
||||||
|
import DataProcessing from './DataProcessing.vue';
|
||||||
import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes';
|
import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -35,7 +36,8 @@ export default defineComponent({
|
|||||||
ConditionInput,
|
ConditionInput,
|
||||||
EventSetter,
|
EventSetter,
|
||||||
ColorPicker,
|
ColorPicker,
|
||||||
NumInput
|
NumInput,
|
||||||
|
DataProcessing
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
nodeProps: {
|
nodeProps: {
|
||||||
@@ -50,7 +52,7 @@ export default defineComponent({
|
|||||||
setup(props, context) {
|
setup(props, context) {
|
||||||
const properties=ref(props.nodeProps);
|
const properties=ref(props.nodeProps);
|
||||||
const connectProps=(props:IProp)=>{
|
const connectProps=(props:IProp)=>{
|
||||||
const connProps:any={};
|
const connProps:any={context:properties};
|
||||||
if(props && "connectProps" in props && props.connectProps!=undefined){
|
if(props && "connectProps" in props && props.connectProps!=undefined){
|
||||||
for(let connProp of props.connectProps){
|
for(let connProp of props.connectProps){
|
||||||
let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName);
|
let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName);
|
||||||
|
|||||||
Reference in New Issue
Block a user