feat:データ集計処理作成
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
<html lang="ja-jp">
|
<html lang="ja-jp">
|
||||||
<head>
|
<head>
|
||||||
<title><%= productName %></title>
|
<title><%= productName %></title>
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="description" content="<%= productDescription %>">
|
<meta name="description" content="<%= productDescription %>">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Router } from 'vue-router';
|
|||||||
import { App } from 'vue';
|
import { App } from 'vue';
|
||||||
|
|
||||||
export default boot(({ app, router }: { app: App<Element>; router: Router }) => {
|
export default boot(({ app, router }: { app: App<Element>; router: Router }) => {
|
||||||
|
document.documentElement.lang="ja-JP";
|
||||||
app.config.errorHandler = (err: any, instance: any, info: string) => {
|
app.config.errorHandler = (err: any, instance: any, info: string) => {
|
||||||
if (err.response && err.response.status === 401) {
|
if (err.response && err.response.status === 401) {
|
||||||
// 認証エラーの場合再ログインする
|
// 認証エラーの場合再ログインする
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<show-dialog v-model:visible="showflg" name="条件エディタ" @close="closeDg" min-width="60vw" min-height="60vh">
|
<show-dialog v-model:visible="showflg" name="条件エディタ" @close="closeDg" min-width="50vw" min-height="60vh">
|
||||||
<template v-slot:toolbar>
|
<template v-slot:toolbar>
|
||||||
<q-btn flat round dense icon="more_vert" >
|
<q-btn flat round dense icon="more_vert" >
|
||||||
<q-menu auto-close anchor="bottom start">
|
<q-menu auto-close anchor="bottom start">
|
||||||
|
|||||||
@@ -13,14 +13,14 @@
|
|||||||
<q-icon name="search" class="cursor-pointer" @click="showDg"/>
|
<q-icon name="search" class="cursor-pointer" @click="showDg"/>
|
||||||
</template>
|
</template>
|
||||||
</q-field>
|
</q-field>
|
||||||
<show-dialog v-model:visible="show" name="条件設定項目一覧" @close="closeDg" width="600px">
|
<show-dialog v-model:visible="show" name="設定項目一覧" @close="closeDg" min-width="400px">
|
||||||
<template v-slot:toolbar>
|
<template v-slot:toolbar>
|
||||||
<q-input dense debounce="200" v-model="filter" placeholder="検索" clearable>
|
<q-input dense debounce="200" v-model="filter" placeholder="検索" clearable>
|
||||||
<template v-slot:before>
|
<template v-slot:before>
|
||||||
<q-icon name="search" />
|
<q-icon name="search" />
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
</template>
|
</template>
|
||||||
<condition-objects ref="appDg" name="フィールド" type="single" :filter="filter" :appId="store.appInfo?.appId" :vars="vars"></condition-objects>
|
<condition-objects ref="appDg" name="フィールド" type="single" :filter="filter" :appId="store.appInfo?.appId" :vars="vars"></condition-objects>
|
||||||
</show-dialog>
|
</show-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <div class="q-pa-md q-gutter-sm" > -->
|
<!-- <div class="q-pa-md q-gutter-sm" > -->
|
||||||
<q-dialog :model-value="visible" persistent bordered >
|
<q-dialog :model-value="visible" persistent bordered >
|
||||||
<q-card :style="cardStyle" style=" min-width: 40vw; max-width: 80vw; max-height: 95vh;">
|
<q-card style="min-width: 40vw; max-width: 80vw; max-height: 95vh;" :style="cardStyle">
|
||||||
<q-toolbar class="bg-grey-4">
|
<q-toolbar class="bg-grey-4">
|
||||||
<q-toolbar-title>{{ name }}</q-toolbar-title>
|
<q-toolbar-title>{{ name }}</q-toolbar-title>
|
||||||
<q-space></q-space>
|
<q-space></q-space>
|
||||||
|
|||||||
@@ -1,59 +1,60 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<q-field :label="displayName" labelColor="primary" stack-label>
|
<q-field :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="() => { dgIsShow = true }">クリックで設定</q-btn>
|
<q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">クリックで設定</q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
<q-card-section class="text-caption">
|
<q-card-section class="text-caption">
|
||||||
<div v-for="(item) in processingObjectsInputDisplay" :key="item">{{ item }}</div>
|
<div v-if="processingObjectsInputDisplay && processingObjectsInputDisplay.length>0">
|
||||||
</q-card-section>
|
<div v-for="(item) in processingObjectsInputDisplay" :key="item">{{ item }}</div>
|
||||||
</q-card>
|
|
||||||
</template>
|
|
||||||
</q-field>
|
|
||||||
<show-dialog v-model:visible="dgIsShow" name="条件エディタ" @close="closeDg" min-width="60vw" min-height="60vh">
|
|
||||||
<div class="q-mx-md q-mb-md">
|
|
||||||
<q-input v-model="processingProps.name" type="text" label-color="primary" label="変数名を入力してください"
|
|
||||||
placeholder="varName" />
|
|
||||||
</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="q-mx-md">
|
||||||
<div class="row q-col-gutter-x-xs flex-center">
|
<div class="row q-col-gutter-x-xs flex-center">
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
<div class="q-mx-xs">数据源</div>
|
<div class="q-mx-xs">データソース</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<div class="q-mx-xs">运算符</div>
|
<div class="q-mx-xs">集計計算</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<div class="q-mx-xs">目标变量</div>
|
<div class="q-mx-xs">集計結果変数名</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addProcessingObject" />
|
<div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addProcessingObject" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="q-my-sm" v-for="(item, index) in processingObjects" :key="item.id">
|
<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="row q-col-gutter-x-xs flex-center">
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
<ConditionObject v-model="item.field" />
|
<ConditionObject v-model="item.field" />
|
||||||
</div>
|
|
||||||
<div class="col-2">
|
|
||||||
<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" label="Label" outlined dense />
|
|
||||||
</div>
|
|
||||||
<div class="col-1">
|
|
||||||
<q-btn flat round dense icon="delete" size="sm"
|
|
||||||
@click="() => deleteProcessingObject(index)" />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</show-dialog>
|
<div class="col-2">
|
||||||
</div>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -63,128 +64,166 @@ import ConditionObject from '../ConditionEditor/ConditionObject.vue';
|
|||||||
import ShowDialog from '../ShowDialog.vue';
|
import ShowDialog from '../ShowDialog.vue';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
props?: {
|
props?: {
|
||||||
name: string;
|
name: string;
|
||||||
modelValue?: {
|
modelValue?: {
|
||||||
fields: {
|
fields: {
|
||||||
type: string;
|
type: string;
|
||||||
label: string;
|
label: string;
|
||||||
code: string;
|
code: string;
|
||||||
}[]
|
}[]
|
||||||
} | string
|
} | string
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type ProcessingObjectType = {
|
type ProcessingObjectType = {
|
||||||
field?: {
|
field?: {
|
||||||
name: string | {
|
name: string | {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
|
||||||
objectType: string;
|
|
||||||
type: string;
|
|
||||||
code: string;
|
|
||||||
label: string;
|
|
||||||
noLabel: boolean;
|
|
||||||
};
|
};
|
||||||
logicalOperator?: string;
|
objectType: string;
|
||||||
vName?: string;
|
type: string;
|
||||||
id: string;
|
code: string;
|
||||||
|
label: string;
|
||||||
|
noLabel: boolean;
|
||||||
|
};
|
||||||
|
logicalOperator?: string;
|
||||||
|
vName?: string;
|
||||||
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValueType = {
|
type ValueType = {
|
||||||
name: string;
|
name: string;
|
||||||
actionName: string,
|
actionName: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
vars: ProcessingObjectType[];
|
vars: ProcessingObjectType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'DataProcessing',
|
name: 'DataProcessing',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
components: {
|
components: {
|
||||||
ShowDialog,
|
ShowDialog,
|
||||||
ConditionObject,
|
ConditionObject,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
context: {
|
||||||
|
type: Array<Props>,
|
||||||
|
default: '',
|
||||||
},
|
},
|
||||||
props: {
|
displayName: {
|
||||||
context: {
|
type: String,
|
||||||
type: Array<Props>,
|
default: '',
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
displayName: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
modelValue: {
|
|
||||||
type: Object as () => ValueType,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: Object as () => ValueType,
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const source = props.context.find(element => element?.props?.name === 'sources')
|
const source = props.context.find(element => element?.props?.name === 'sources')
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
provide('sourceFields', computed(() => {
|
provide('sourceFields', computed(() => {
|
||||||
const modelValue = source.props?.modelValue;
|
const modelValue = source.props?.modelValue;
|
||||||
if (modelValue && typeof modelValue !== 'string') {
|
if (modelValue && typeof modelValue !== 'string') {
|
||||||
return modelValue.fields;
|
return modelValue.fields;
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
const actionName = props.context.find(element => element?.props?.name === 'displayName')
|
const actionName = props.context.find(element => element?.props?.name === 'displayName')
|
||||||
|
|
||||||
const processingProps: ValueType = props.modelValue && props.modelValue.vars
|
const processingProps: ValueType = props.modelValue && props.modelValue.vars
|
||||||
? props.modelValue
|
? props.modelValue
|
||||||
: reactive({
|
: reactive({
|
||||||
name: '',
|
name: '',
|
||||||
actionName: actionName?.props?.modelValue as string,
|
actionName: actionName?.props?.modelValue as string,
|
||||||
displayName: '結果(戻り値)',
|
displayName: '結果(戻り値)',
|
||||||
vars: [{ id: uuidv4() }]
|
vars: [{ id: uuidv4() }]
|
||||||
});
|
});
|
||||||
|
|
||||||
const closeDg = () => {
|
const closeDg = () => {
|
||||||
emit('update:modelValue', processingProps
|
emit('update:modelValue', processingProps
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const processingObjects = processingProps.vars;
|
const processingObjects = processingProps.vars;
|
||||||
|
|
||||||
const deleteProcessingObject = (index: number) => processingObjects.length === 1
|
const deleteProcessingObject = (index: number) => processingObjects.length === 1
|
||||||
? processingObjects.splice(0, processingObjects.length, { id: uuidv4() })
|
? processingObjects.splice(0, processingObjects.length, { id: uuidv4() })
|
||||||
: processingObjects.splice(index, 1);
|
: processingObjects.splice(index, 1);
|
||||||
const processingObjectsInputDisplay = computed(() =>
|
|
||||||
processingObjects ?
|
|
||||||
processingObjects
|
|
||||||
.filter(item => item.field && item.logicalOperator && item.vName)
|
|
||||||
.map(item => {
|
|
||||||
const name = typeof item.field?.name === 'string'
|
|
||||||
? item.field.name
|
|
||||||
: item.field?.name.name;
|
|
||||||
return `${processingProps.name}.${item.vName} = ${item.logicalOperator}(${name})`
|
|
||||||
})
|
|
||||||
: ''
|
|
||||||
);
|
|
||||||
|
|
||||||
watchEffect(() => {
|
const processingObjectsInputDisplay = computed(() =>
|
||||||
emit('update:modelValue', processingProps);
|
processingObjects ?
|
||||||
});
|
processingObjects
|
||||||
return {
|
.filter(item => item.field && item.logicalOperator && item.vName)
|
||||||
uuidv4,
|
.map(item => {
|
||||||
dgIsShow: ref(false),
|
const name = typeof item.field?.name === 'string'
|
||||||
closeDg,
|
? item.field.name
|
||||||
processingObjects,
|
: item.field?.name.name;
|
||||||
processingProps,
|
return item.logicalOperator.operator!==''?
|
||||||
addProcessingObject: () => processingObjects.push({ id: uuidv4() }),
|
`${processingProps.name}.${item.vName} = ${item.logicalOperator.operator}(${name})`
|
||||||
deleteProcessingObject,
|
:`${processingProps.name}.${item.vName} = ${name}`
|
||||||
logicalOperators: reactive(['MAX', 'SUM']),
|
})
|
||||||
processingObjectsInputDisplay,
|
: []
|
||||||
};
|
);
|
||||||
},
|
//集計処理方法
|
||||||
|
const logicalOperators = ref([
|
||||||
|
{
|
||||||
|
"operator": "",
|
||||||
|
"label": "なし"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"operator": "SUM",
|
||||||
|
"label": "合計"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"operator": "AVG",
|
||||||
|
"label": "平均"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"operator": "MAX",
|
||||||
|
"label": "最大値"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"operator": "MIN",
|
||||||
|
"label": "最小値"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"operator": "COUNT",
|
||||||
|
"label": "カウント"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"operator": "FIRST",
|
||||||
|
"label": "最初の値"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
emit('update:modelValue', processingProps);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
uuidv4,
|
||||||
|
dgIsShow: ref(false),
|
||||||
|
closeDg,
|
||||||
|
processingObjects,
|
||||||
|
processingProps,
|
||||||
|
addProcessingObject: () => processingObjects.push({ id: uuidv4() }),
|
||||||
|
deleteProcessingObject,
|
||||||
|
logicalOperators,
|
||||||
|
processingObjectsInputDisplay,
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss"></style>
|
<style lang="scss"></style>
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-select v-model="selectedValue" :label="displayName" :options="options"/>
|
<q-select v-model="selectedValue" :use-chips="multiple" :label="displayName" label-color="primary" :options="options" stack-label
|
||||||
|
:multiple="multiple"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent,ref,watchEffect } from 'vue';
|
import { defineComponent,ref,watchEffect,computed } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SelectBox',
|
name: 'SelectBox',
|
||||||
@@ -23,20 +24,27 @@ export default defineComponent({
|
|||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
selectType:{
|
||||||
|
type:String,
|
||||||
|
default:'',
|
||||||
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: Object,
|
||||||
default: '',
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const selectedValue = ref(props.modelValue);
|
const selectedValue = ref(props.modelValue);
|
||||||
|
const multiple = computed(()=>{
|
||||||
|
return props.selectType==='multiple'
|
||||||
|
});
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', selectedValue.value);
|
emit('update:modelValue', selectedValue.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedValue
|
selectedValue,
|
||||||
|
multiple
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user