276 lines
7.3 KiB
Vue
276 lines
7.3 KiB
Vue
<template>
|
|
<div>
|
|
<q-field :label="displayName" labelColor="primary" stack-label
|
|
v-model="processingProps"
|
|
:rules="rulesExp"
|
|
lazy-rules="ondemand"
|
|
ref="fieldRef"
|
|
>
|
|
<template v-slot:control>
|
|
<q-card flat class="full-width">
|
|
<q-card-actions vertical>
|
|
<q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">クリックで設定</q-btn>
|
|
</q-card-actions>
|
|
<q-card-section class="text-caption">
|
|
<div v-if="processingObjectsInputDisplay && processingObjectsInputDisplay.length>0">
|
|
<div v-for="(item) in processingObjectsInputDisplay" :key="item">{{ item }}</div>
|
|
</div>
|
|
<div v-else>{{ placeholder }}</div>
|
|
</q-card-section>
|
|
</q-card>
|
|
</template>
|
|
</q-field>
|
|
<show-dialog v-model:visible="dgIsShow" name="集計処理" @close="closeDg" min-width="50vw" min-height="60vh">
|
|
<div class="q-mx-md q-mb-md">
|
|
<q-input v-model="processingProps.name" type="text" label-color="primary" label="集計結果の変数名"
|
|
placeholder="集計結果を格納する変数名を入力してください" stack-label />
|
|
</div>
|
|
|
|
<div class="q-mx-md">
|
|
<div class="row q-col-gutter-x-xs flex-center">
|
|
<div class="col-5">
|
|
<div class="q-mx-xs">データソース</div>
|
|
</div>
|
|
<div class="col-2">
|
|
<div class="q-mx-xs">集計計算</div>
|
|
</div>
|
|
<div class="col-4">
|
|
<div class="q-mx-xs">集計結果変数名</div>
|
|
</div>
|
|
<div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addProcessingObject" />
|
|
</div>
|
|
</div>
|
|
<div class="q-my-sm" v-for="(item, index) in processingObjects" :key="item.id">
|
|
<div class="row q-col-gutter-x-xs flex-center">
|
|
<div class="col-5">
|
|
<ConditionObject v-model="item.field" />
|
|
</div>
|
|
<div class="col-2 q-pa-sm">
|
|
<q-select v-model="item.logicalOperator" :options="logicalOperators" outlined dense></q-select>
|
|
</div>
|
|
<div class="col-4">
|
|
<q-input v-model="item.vName" type="text" outlined dense />
|
|
</div>
|
|
<div class="col-1">
|
|
<q-btn flat round dense icon="delete" size="sm" @click="() => deleteProcessingObject(index)" />
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</show-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
|
|
import ConditionObject from '../ConditionEditor/ConditionObject.vue';
|
|
import ShowDialog from '../ShowDialog.vue';
|
|
|
|
type Props = {
|
|
props?: {
|
|
name: string;
|
|
modelValue?: {
|
|
fields: {
|
|
type: string;
|
|
label: string;
|
|
code: string;
|
|
}[]
|
|
} | string
|
|
}
|
|
};
|
|
|
|
type ProcessingObjectType = {
|
|
field?: {
|
|
sharedText: string;
|
|
objectType: 'field';
|
|
};
|
|
logicalOperator?: string;
|
|
vName?: string;
|
|
id: string;
|
|
}
|
|
|
|
type ValueType = {
|
|
name: string;
|
|
actionName: string,
|
|
displayName: string,
|
|
vars: ProcessingObjectType[];
|
|
}
|
|
|
|
export default defineComponent({
|
|
name: 'DataProcessing',
|
|
inheritAttrs: false,
|
|
components: {
|
|
ShowDialog,
|
|
ConditionObject,
|
|
},
|
|
props: {
|
|
context: {
|
|
type: Array<Props>,
|
|
default: '',
|
|
},
|
|
displayName: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
name: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
modelValue: {
|
|
type: Object as () => ValueType,
|
|
},
|
|
placeholder: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
//例:[val=>!!val ||'入力してください']
|
|
rules: {
|
|
type: String,
|
|
default: undefined
|
|
},
|
|
required: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
|
|
setup(props, { emit }) {
|
|
const fieldRef=ref();
|
|
const source = props.context.find(element => element?.props?.name === 'sources')
|
|
|
|
if (source) {
|
|
provide('sourceFields', computed(() => {
|
|
const modelValue = source.props?.modelValue;
|
|
if (modelValue && typeof modelValue !== 'string') {
|
|
return modelValue.fields;
|
|
}
|
|
return null;
|
|
}));
|
|
provide('sourceApp', computed(() => source.props?.modelValue?.app?.id));
|
|
}
|
|
|
|
const actionName = props.context.find(element => element?.props?.name === 'displayName')
|
|
|
|
const processingProps: ValueType = props.modelValue && props.modelValue.vars
|
|
? reactive(props.modelValue)
|
|
: reactive({
|
|
name: '',
|
|
actionName: actionName?.props?.modelValue as string,
|
|
displayName: '結果(戻り値)',
|
|
vars: [
|
|
{
|
|
id: uuidv4(),
|
|
field:{
|
|
objectType:'field',
|
|
sharedText:''
|
|
}
|
|
}]
|
|
});
|
|
|
|
const closeDg = () => {
|
|
fieldRef.value.validate();
|
|
emit('update:modelValue', processingProps);
|
|
}
|
|
|
|
const processingObjects = processingProps.vars;
|
|
|
|
const deleteProcessingObject = (index: number) => {
|
|
if(processingObjects.length >0){
|
|
processingObjects.splice(index, 1);
|
|
}
|
|
if(processingObjects.length===0){
|
|
addProcessingObject();
|
|
}
|
|
}
|
|
const processingObjectsInputDisplay = computed(() =>
|
|
processingObjects ?
|
|
processingObjects
|
|
.filter(item => item.field && item.logicalOperator && item.vName)
|
|
.map(item => {
|
|
return`var(${processingProps.name}.${item.vName}) = ${item.field?.sharedText}`
|
|
})
|
|
: []
|
|
);
|
|
|
|
const addProcessingObject=()=>{
|
|
processingObjects.push({
|
|
id: uuidv4(),
|
|
field:{
|
|
objectType:'field',
|
|
sharedText:''
|
|
}
|
|
});
|
|
}
|
|
//集計処理方法
|
|
const logicalOperators = ref([
|
|
{
|
|
"operator": "",
|
|
"label": "なし"
|
|
},
|
|
{
|
|
"operator": "SUM",
|
|
"label": "合計"
|
|
},
|
|
{
|
|
"operator": "AVG",
|
|
"label": "平均"
|
|
},
|
|
{
|
|
"operator": "MAX",
|
|
"label": "最大値"
|
|
},
|
|
{
|
|
"operator": "MIN",
|
|
"label": "最小値"
|
|
},
|
|
{
|
|
"operator": "COUNT",
|
|
"label": "カウント"
|
|
},
|
|
{
|
|
"operator": "FIRST",
|
|
"label": "最初の値"
|
|
}
|
|
]);
|
|
const checkInput=(val:ValueType)=>{
|
|
if(!val){
|
|
return false;
|
|
}
|
|
if(!val.name){
|
|
return "集計結果の変数名を入力してください";
|
|
}
|
|
if(!val.vars || val.vars.length==0){
|
|
return "集計処理を設定してください";
|
|
}
|
|
if(val.vars.some((x)=>!x.vName)){
|
|
return "集計結果変数名を入力してください";
|
|
}
|
|
return true;
|
|
}
|
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
|
const requiredExp = props.required ? [(val: any) => checkInput(val)] : [];
|
|
const rulesExp = [...requiredExp, ...customExp];
|
|
|
|
watchEffect(() => {
|
|
emit('update:modelValue', processingProps);
|
|
});
|
|
return {
|
|
uuidv4,
|
|
dgIsShow: ref(false),
|
|
closeDg,
|
|
processingObjects,
|
|
processingProps,
|
|
addProcessingObject,
|
|
deleteProcessingObject,
|
|
logicalOperators,
|
|
processingObjectsInputDisplay,
|
|
rulesExp,
|
|
fieldRef
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
<style lang="scss"></style>
|