2つのデータ計算コンポーネントを追加する
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
|
||||
<q-tab-panels v-model="tab" animated>
|
||||
<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 name="vars" >
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import { ref, onMounted, reactive, inject } from 'vue'
|
||||
import FieldList from './FieldList.vue';
|
||||
import VariableList from './VariableList.vue';
|
||||
|
||||
@@ -48,10 +48,13 @@ export default {
|
||||
filter:String
|
||||
},
|
||||
setup(props) {
|
||||
|
||||
const selected = ref([]);
|
||||
console.log(selected);
|
||||
|
||||
return {
|
||||
sourceFields : inject('sourceFields'),
|
||||
tab: ref('fields'),
|
||||
selected: ref([])
|
||||
selected
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
<template>
|
||||
<div class="q-pa-md">
|
||||
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type"
|
||||
:selected="modelValue"
|
||||
@update:selected="$emit('update:modelValue', $event)"
|
||||
:filter="filter"
|
||||
:columns="columns" :rows="rows" />
|
||||
<q-table flat bordered :loading="!isLoaded" row-key="name" :selection="type" :selected="modelValue"
|
||||
@update:selected="$emit('update:modelValue', $event)" :filter="filter" :columns="columns" :rows="rows" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
<script lang="ts">
|
||||
import { useAsyncState } from '@vueuse/core';
|
||||
import { api } from 'boot/axios';
|
||||
import { computed } from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'FieldList',
|
||||
props: {
|
||||
fields: Array,
|
||||
name: String,
|
||||
type: String,
|
||||
appId: Number,
|
||||
modelValue:Array,
|
||||
filter:String
|
||||
},
|
||||
emits:[
|
||||
'update:modelValue'
|
||||
],
|
||||
modelValue: Array,
|
||||
filter: String
|
||||
},
|
||||
emits: [
|
||||
'update:modelValue'
|
||||
],
|
||||
setup(props) {
|
||||
const isLoaded = ref(false);
|
||||
// const rows = ref([]);
|
||||
// const isLoaded = ref(false);
|
||||
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: '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 {
|
||||
columns,
|
||||
rows,
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }">
|
||||
<q-item :key="index" dense clickable >
|
||||
<q-item-section>
|
||||
<q-item-label>
|
||||
{{ item.label }}
|
||||
</q-item-label>
|
||||
<q-item-label>
|
||||
{{ item.label }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
||||
@@ -128,7 +128,7 @@ interface IAppFields{
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs:false,
|
||||
name: 'FieldInput',
|
||||
name: 'AppFieldSelect',
|
||||
components: {
|
||||
ShowDialog,
|
||||
FieldSelect,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div v-bind="$attrs">
|
||||
<q-field v-model="tree" :label="displayName" labelColor="primary" stack-label >
|
||||
<template v-slot:control >
|
||||
<q-field v-model="tree" :label="displayName" labelColor="primary" stack-label>
|
||||
<template v-slot:control>
|
||||
<q-card flat class="full-width">
|
||||
<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-section class="text-caption" >
|
||||
<q-card-section class="text-caption">
|
||||
<div v-if="!isSetted">{{ placeholder }}</div>
|
||||
<div v-else>{{ conditionString }}</div>
|
||||
</q-card-section>
|
||||
@@ -17,82 +17,109 @@
|
||||
</div>
|
||||
</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(()=>{
|
||||
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
|
||||
};
|
||||
type Props = {
|
||||
props?: {
|
||||
name: string;
|
||||
modelValue?: {
|
||||
fields: {
|
||||
type: string;
|
||||
label: string;
|
||||
code: string;
|
||||
}[]
|
||||
}
|
||||
});
|
||||
</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>
|
||||
<div>
|
||||
<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>
|
||||
</template>
|
||||
@@ -21,6 +21,7 @@ import ConditionInput from '../right/ConditionInput.vue';
|
||||
import EventSetter from '../right/EventSetter.vue';
|
||||
import ColorPicker from './ColorPicker.vue';
|
||||
import NumInput from './NumInput.vue';
|
||||
import DataProcessing from './DataProcessing.vue';
|
||||
import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes';
|
||||
|
||||
export default defineComponent({
|
||||
@@ -35,7 +36,8 @@ export default defineComponent({
|
||||
ConditionInput,
|
||||
EventSetter,
|
||||
ColorPicker,
|
||||
NumInput
|
||||
NumInput,
|
||||
DataProcessing
|
||||
},
|
||||
props: {
|
||||
nodeProps: {
|
||||
@@ -50,7 +52,7 @@ export default defineComponent({
|
||||
setup(props, context) {
|
||||
const properties=ref(props.nodeProps);
|
||||
const connectProps=(props:IProp)=>{
|
||||
const connProps:any={};
|
||||
const connProps:any={context:properties};
|
||||
if(props && "connectProps" in props && props.connectProps!=undefined){
|
||||
for(let connProp of props.connectProps){
|
||||
let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName);
|
||||
|
||||
Reference in New Issue
Block a user