Conformance: layout done.(not time range)
This commit is contained in:
24
package-lock.json
generated
24
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.99.0",
|
||||
"version": "0.99.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "frontend",
|
||||
"version": "0.99.0",
|
||||
"version": "0.99.1",
|
||||
"dependencies": {
|
||||
"autoprefixer": "^10.4.13",
|
||||
"axios": "^1.2.2",
|
||||
@@ -33,6 +33,7 @@
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-sweetalert2": "^5.0.5",
|
||||
"vue-toast-notification": "^3.0.4",
|
||||
"vue3-timepicker": "^1.0.0-beta.2",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -6192,6 +6193,17 @@
|
||||
"vue": "^3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue3-timepicker": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/vue3-timepicker/-/vue3-timepicker-1.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-j4IVU7PPLrO5HADspv1E+tXTkMc9gWfCu/ruwJqJdX7qugAaVk3yNF7Mj4icRGlU4uKeSohlXWA8/Uj1ePiTxQ==",
|
||||
"dependencies": {
|
||||
"vue": "^3.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||
@@ -10961,6 +10973,14 @@
|
||||
"integrity": "sha512-rEhLtcKg8SVdBpdN7PrNst5nmY8dw0j3NkNImqurhlGurqR/QDKoou0t2PuCReEOCTKqHvfLCle2I3kwQWDWDQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"vue3-timepicker": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/vue3-timepicker/-/vue3-timepicker-1.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-j4IVU7PPLrO5HADspv1E+tXTkMc9gWfCu/ruwJqJdX7qugAaVk3yNF7Mj4icRGlU4uKeSohlXWA8/Uj1ePiTxQ==",
|
||||
"requires": {
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
},
|
||||
"vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||
|
||||
@@ -76,3 +76,10 @@ p-radiobutton-icon */
|
||||
.p-radiobutton-icon {
|
||||
@apply !bg-primary
|
||||
}
|
||||
/* Dialog */
|
||||
.p-dialog-header {
|
||||
@apply !p-0 !px-4 !bg-neutral-100
|
||||
}
|
||||
.p-dialog-content {
|
||||
@apply !p-0
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<section class="p-4 space-y-2 h-full w-[calc(100vw_-_316px)] overflow-y-auto float-right">
|
||||
<section class="p-4 mr-0.5 space-y-2 h-full w-[calc(100vw_-_316px)] overflow-y-auto scrollbar float-right">
|
||||
<!-- title -->
|
||||
<p class="h2 text-base">Conformance Checking Results<span class="material-symbols-outlined text-base align-middle ml-2" v-tooltip.bottom="tooltip.results" type="text">info</span></p>
|
||||
<!-- total group -->
|
||||
<ul class=" text-neutral-10 text-sm flex gap-2 py-2">
|
||||
<li class=" bg-cfm-primary rounded-full px-4 py-1 space-x-2">
|
||||
<span class="material-symbols-outlined text-base align-middle mr-2">check_circle</span>Conformance<span>3,890</span>
|
||||
<span class="material-symbols-outlined text-base align-middle mr-2">check_circle</span>Conforming<span>3,890</span>
|
||||
</li>
|
||||
<li class=" bg-cfm-secondary rounded-full px-4 py-1 space-x-2">
|
||||
<span class="material-symbols-outlined text-base align-middle mr-2">cancel</span>Non-Conformance<span>27,230</span>
|
||||
<span class="material-symbols-outlined text-base align-middle mr-2">cancel</span>Not Conforming<span>27,230</span>
|
||||
</li>
|
||||
<li class=" bg-neutral-700 rounded-full px-4 py-1 space-x-2">
|
||||
<iconNA class="inline-block mr-1"></iconNA>Not Applicable<span>7,780</span>
|
||||
@@ -198,7 +198,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<MoreModal :issusModal="issusModal"></MoreModal>
|
||||
<MoreModal :issusModal="issusModal" @update:visible="issusModal = $event"></MoreModal>
|
||||
</section>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@@ -9,16 +9,18 @@
|
||||
<div class="p-4 h-[calc(100%_-_40px)] flex">
|
||||
<div class="h-full flex flex-col justify-between w-[268px]">
|
||||
<!-- select -->
|
||||
<div class="h-full overflow-y-auto scrollbar">
|
||||
<!-- show and hidden button -->
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="h2">Activity Select</p>
|
||||
<span class="material-symbols-outlined cursor-pointer duration-300 hover:bg-primary/50 hover:rounded " @click="isShowBar = !isShowBar">{{ isShowBar ? 'keyboard_double_arrow_right' : 'keyboard_double_arrow_left' }}</span>
|
||||
</div>
|
||||
<div class="h-full overflow-y-auto scrollbar w-[268px]">
|
||||
<!-- radio group -->
|
||||
<ConformanceRadioGroup></ConformanceRadioGroup>
|
||||
<!-- show and hidden button -->
|
||||
<div class="flex items-center justify-between mr-1" :class="isShowBar ? 'text-primary' : ''">
|
||||
<p class="h2">Activity Selector</p>
|
||||
<span class="material-symbols-outlined cursor-pointer duration-300 hover:bg-primary/50 hover:rounded" @click="isShowBar = !isShowBar">{{ isShowBar ? 'keyboard_double_arrow_right' : 'keyboard_double_arrow_left' }}</span>
|
||||
</div>
|
||||
<!-- select result -->
|
||||
<ConformanceSelectResult></ConformanceSelectResult>
|
||||
<!-- time range -->
|
||||
<ConformanceTimeRange v-if="selectedRuleType === 'Activity duration' || selectedRuleType === 'Processing time' || selectedRuleType === 'Waiting time' || selectedRuleType === 'Cycle time'"></ConformanceTimeRange>
|
||||
</div>
|
||||
<!-- button -->
|
||||
<div class="space-x-4 p-4 flex justify-center items-content border-t border-neutral-300">
|
||||
@@ -33,11 +35,20 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { storeToRefs } from 'pinia';
|
||||
import ConformanceStore from '@/stores/conformance.js';
|
||||
import ConformanceRadioGroup from './ConformanceSidebar/ConformanceRadioGroup.vue';
|
||||
import ConformanceShowBar from './ConformanceSidebar/ConformanceShowBar.vue';
|
||||
import ConformanceTimeRange from './ConformanceSidebar/ConformanceTimeRange.vue';
|
||||
import ConformanceSelectResult from './ConformanceSidebar/ConformanceSelectResult.vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const conformanceStore = ConformanceStore();
|
||||
const { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore, selectedActSeqFromTo } = storeToRefs(conformanceStore);
|
||||
|
||||
return { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore, selectedActSeqFromTo }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShowBar: false,
|
||||
@@ -47,7 +58,16 @@ export default {
|
||||
components: {
|
||||
ConformanceRadioGroup,
|
||||
ConformanceShowBar,
|
||||
ConformanceTimeRange,
|
||||
ConformanceSelectResult,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.isShowBar = true;
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.text-shadow{
|
||||
text-shadow: 1.5px 1px 8px black;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
<template>
|
||||
<div class="h-full bg-neutral-10 border border-neutral-300 rounded-xl ml-4 p-2 space-y-2">
|
||||
<p class="h2 pl-2">Activity list</p>
|
||||
<div class="h-[calc(100%_-_48px)]">
|
||||
<p class="h2 pl-2 border-b mb-3">Activity</p>
|
||||
<p class="h2 pl-2 border-b mb-3">Sort</p>
|
||||
<div class="flex flex-wrap justify-start content-start gap-4 px-2 overflow-y-auto scrollbar h-[calc(100%_-_52px)]">
|
||||
<div class="flex items-center w-[166px]" v-for="(act, index) in data" :key="index">
|
||||
<Checkbox v-model="actList" :inputId="index.toString()" name="actList" :value="act" />
|
||||
<label :for="index" class="ml-2 p-2 whitespace-nowrap break-keep text-ellipsis overflow-hidden">{{ act }}{{ index }}</label>
|
||||
<label :for="index" class="ml-2 p-2 whitespace-nowrap break-keep text-ellipsis overflow-hidden">{{ act }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['data'],
|
||||
data() {
|
||||
return {
|
||||
actList: null,
|
||||
data:['到到到到到到到到到到到到到到到到到到到到到到院', '住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住院', '開開開開開開開開開開開開開開開開開開開開開開刀', '第第第第第第第第第第一次醫囑', 'aaaaaaaaaaaaaaaa', 'bb ccc ddddd eeee', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院 到院 到院 到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院', '住院', '開刀', '第一次醫囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院院院院院院院院院院院院院院院院院院院院院院院院院院院', '到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="h-full bg-neutral-10 border border-neutral-300 rounded-xl ml-4 p-2 space-y-2">
|
||||
<p class="h2 pl-2">{{ title }}</p>
|
||||
<div class="h-[calc(100%_-_48px)]">
|
||||
<p class="h2 pl-2 border-b mb-3">Sort</p>
|
||||
<div class="flex flex-wrap justify-start content-start gap-4 px-2 overflow-y-auto scrollbar h-[calc(100%_-_52px)]">
|
||||
<div class="flex items-center w-[166px]" v-for="(act, index) in data" :key="index">
|
||||
<RadioButton v-model="selectedRadio" :inputId="index.toString()" :name="vModel" :value="act" />
|
||||
<label :for="index" class="ml-2 p-2 whitespace-nowrap break-keep text-ellipsis overflow-hidden">{{ act }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['title', 'vModel', 'data',],
|
||||
data() {
|
||||
return {
|
||||
selectedRadio: this.vModel,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="h-full w-full flex justify-between items-center">
|
||||
<!-- Activity List -->
|
||||
<div class="h-full w-full bg-neutral-10 border border-neutral-300 rounded-xl ml-4 p-2 space-y-2">
|
||||
<p class="h2 pl-2">Activity list</p>
|
||||
<div class="h-[calc(100%_-_48px)]">
|
||||
<p class="h2 pl-2 border-b mb-3">Sort</p>
|
||||
<Draggable :list="datadata" group="activity" itemKey="name" animation="300" @end="onEnd" :fallbackTolerance="5" :forceFallback="true" :ghostClass="'ghostSelected'" :dragClass="'dragSelected'" class="flex flex-wrap justify-start content-start gap-4 px-2 overflow-y-auto scrollbar h-[calc(100%_-_52px)]">
|
||||
<template #item="{ element, index }">
|
||||
<div class="flex items-center w-[166px] border rounded p-2 bg-neutral-10 cursor-pointer hover:bg-primary/20" @dblclick="moveActItem(index, element)">
|
||||
<span class="whitespace-nowrap break-keep text-ellipsis overflow-hidden">{{ element }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</Draggable>
|
||||
</div>
|
||||
</div>
|
||||
<!-- sequence -->
|
||||
<div class="w-full h-full relative bg-neutral-10 border border-neutral-300 rounded-xl ml-4 p-2 space-y-2 text-sm">
|
||||
<p class="h2 border-b border-500 my-2">Sequence</p>
|
||||
<!-- No Data -->
|
||||
<div v-if="listSequence.length === 0" class="p-4 w-[calc(100%_-_32px)] h-5/6 flex justify-center items-center absolute">
|
||||
<p class="text-neutral-500">Please drag and drop activity(s) here and sort.</p>
|
||||
</div>
|
||||
<!-- Have Data -->
|
||||
<div class="py-4 m-auto w-full h-[calc(100%_-_56px)]">
|
||||
<div class="w-full h-full overflow-y-auto overflow-x-auto scrollbar px-4 text-center listSequence">
|
||||
<draggable class="h-full" :list="listSequence" group="activity" itemKey="name" animation="300" :forceFallback="true" :dragClass="'dragSelected'" :fallbackTolerance="5" @start="onStart" @end="onEnd">
|
||||
<template #item="{ element, index }">
|
||||
<div>
|
||||
<div class="w-full p-2 border rounded bg-neutral-10 cursor-pointer hover:bg-primary/20" @dblclick="moveSeqItem(index, element)">
|
||||
<span>{{ element }}</span>
|
||||
</div>
|
||||
<span v-show="index !== listSequence.length - 1 && index !== lastItemIndex - 1" class="pi pi-chevron-down !text-lg inline-block py-2"></span>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
import sortNumEngZhtw from '@/module/sortNumEngZhtw.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
actList: null,
|
||||
listSequence: [],
|
||||
lastItemIndex: null,
|
||||
data:['第三次醫囑', '第四次醫囑','第一次醫囑', '第二次醫囑', 'ddd', 'bbb', 'ccc', 'aaa', 'accc', 'abbb', '1234', '1111', '1222', '1333', '3333', '4444', '0', '1000', '100', '10', '9', '80']
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
datadata: function() {
|
||||
// TODO Activity List 的 dblclick, drag & drop 要改假刪除
|
||||
// Activity List 要排序
|
||||
return sortNumEngZhtw(this.data);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* double click Activity List
|
||||
* @param {number} index data item index
|
||||
* @param {object} element data item
|
||||
*/
|
||||
moveActItem(index, element){
|
||||
this.data.splice(index, 1);
|
||||
this.listSequence.push(element);
|
||||
},
|
||||
/**
|
||||
* double click Sequence List
|
||||
* @param {number} index data item index
|
||||
* @param {object} element data item
|
||||
*/
|
||||
moveSeqItem(index, element){
|
||||
this.listSequence.splice(index, 1);
|
||||
this.data.push(element);
|
||||
},
|
||||
/**
|
||||
* Element dragging started
|
||||
*/
|
||||
onStart(evt) {
|
||||
const lastChild = evt.to.lastChild.lastChild;
|
||||
lastChild.style.display = 'none';
|
||||
// 隱藏拖曳元素原位置
|
||||
const originalElement = evt.item;
|
||||
originalElement.style.display = 'none';
|
||||
// 拖曳最後一個元素時,倒數第二的元素的箭頭要隱藏
|
||||
const listIndex = this.listSequence.length - 1;
|
||||
if(evt.oldIndex === listIndex) this.lastItemIndex = listIndex;
|
||||
},
|
||||
/**
|
||||
* Element dragging ended
|
||||
*/
|
||||
onEnd(evt) {
|
||||
// 顯示拖曳元素
|
||||
const originalElement = evt.item;
|
||||
originalElement.style.display = '';
|
||||
// 拖曳結束要顯示箭頭,但最後一個不用
|
||||
const lastChild = evt.item.lastChild;
|
||||
const listIndex = this.listSequence.length - 1
|
||||
evt.oldIndex !== listIndex ? lastChild.style.display = '' : null;
|
||||
// reset: 拖曳最後一個元素時,倒數第二的元素的箭頭要隱藏
|
||||
this.lastItemIndex = null;
|
||||
this.$emit('update:listSeq', this.listSequence);
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.ghostSelected {
|
||||
@apply bg-primary/20
|
||||
}
|
||||
.dragSelected {
|
||||
@apply !opacity-100
|
||||
}
|
||||
</style>
|
||||
@@ -4,7 +4,7 @@
|
||||
<div>
|
||||
<p class="h2">Rule Type</p>
|
||||
<div v-for="rule in ruleType" :key="rule.id" class="ml-4 mb-2">
|
||||
<RadioButton v-model="selectedRuleType" :inputId="rule.id + rule.name" name="ruleType" :value="rule.name" />
|
||||
<RadioButton v-model="selectedRuleType" :inputId="rule.id + rule.name" name="ruleType" :value="rule.name" @change="changeRadio($event)"/>
|
||||
<label :for="rule.id + rule.name" class="ml-2">{{ rule.name }}</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Process Scope -->
|
||||
<div v-show="selectedRuleType === 'Processing time'">
|
||||
<div v-show="selectedRuleType === 'Processing time' || selectedRuleType === 'Waiting time'">
|
||||
<p class="h2">Process Scope</p>
|
||||
<div v-for="pro in processScope" :key="pro.id" class="ml-4 mb-2">
|
||||
<RadioButton v-model="selectedProcessScope" :inputId="pro.id + pro.name" name="processScope" :value="pro.name" />
|
||||
@@ -33,13 +33,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Activity Sequence (4 item) -->
|
||||
<div v-show="selectedRuleType === 'Processing time' || selectedRuleType === 'Cycle time'">
|
||||
<div v-show="(selectedRuleType === 'Processing time' && selectedProcessScope === 'End to end') || (selectedRuleType === 'Waiting time' && selectedProcessScope === 'End to end') || selectedRuleType === 'Cycle time'">
|
||||
<p class="h2">Activity Sequence</p>
|
||||
<div v-for="act in actSeqMore" :key="act.id" class="ml-4 mb-2">
|
||||
<RadioButton v-model="selectedActSeqMore" :inputId="act.id + act.name" name="activitySequenceMore" :value="act.name" />
|
||||
<label :for="act.id + act.name" class="ml-2">{{ act.name }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Activity Sequence (3 item) -->
|
||||
<div v-show="(selectedRuleType === 'Processing time' && selectedProcessScope === 'Partial') || (selectedRuleType === 'Waiting time' && selectedProcessScope === 'Partial')">
|
||||
<p class="h2">Activity Sequence</p>
|
||||
<div v-for="act in actSeqFromTo" :key="act.id" class="ml-4 mb-2">
|
||||
<RadioButton v-model="selectedActSeqFromTo" :inputId="act.id + act.name" name="activitySequenceFromTo" :value="act.name" />
|
||||
<label :for="act.id + act.name" class="ml-2">{{ act.name }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<script>
|
||||
@@ -49,9 +57,9 @@ import ConformanceStore from '@/stores/conformance.js';
|
||||
export default {
|
||||
setup() {
|
||||
const conformanceStore = ConformanceStore();
|
||||
const { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore } = storeToRefs(conformanceStore);
|
||||
const { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore, selectedActSeqFromTo } = storeToRefs(conformanceStore);
|
||||
|
||||
return { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore }
|
||||
return { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore, selectedActSeqFromTo }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -86,9 +94,24 @@ export default {
|
||||
{id: 1, name: 'All'},
|
||||
{id: 2, name: 'Start'},
|
||||
{id: 3, name: 'End'},
|
||||
{id: 4, name: 'Start & End '},
|
||||
{id: 4, name: 'Start & End'},
|
||||
],
|
||||
// selectedActSeqFromTo: '',
|
||||
actSeqFromTo: [
|
||||
{id: 1, name: 'From'},
|
||||
{id: 2, name: 'To'},
|
||||
{id: 3, name: 'From & To'},
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeRadio(event) {
|
||||
this.selectedActivitySequence = 'Start & End';
|
||||
this.selectedMode = 'Directly follows';
|
||||
this.selectedProcessScope = 'End to end';
|
||||
this.selectedActSeqMore = 'All';
|
||||
this.selectedActSeqFromTo = 'From';
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,11 +1,57 @@
|
||||
<template>
|
||||
<section class="animate-fadein w-full h-full bg-neutral-10 border border-neutral-300 rounded-xl ml-4 p-2 space-y-2">
|
||||
<section class="animate-fadein w-full h-full">
|
||||
<!-- {{ selectedRuleType }}
|
||||
{{ selectedActivitySequence }}
|
||||
{{ selectedMode }}
|
||||
{{ selectedProcessScope }}
|
||||
{{ selectedActSeqMore }} -->
|
||||
<ActList v-if="selectedRuleType === 'Have activity'"></ActList>
|
||||
|
||||
<!-- Have activity -->
|
||||
<ActList v-if="selectedRuleType === 'Have activity'" :data="conformanceTask"></ActList>
|
||||
<!-- Activity sequence -->
|
||||
<div v-if="selectedRuleType === 'Activity sequence' && selectedActivitySequence === 'Start & End'" class="flex h-full">
|
||||
<ActRadio :title="'Start activity'" :v-model="'actseqStartAndEndRadioStart'" :data="data" />
|
||||
<ActRadio :title="'End activity'" :v-model="'actseqStartAndEndRadioEnd'" :data="data" />
|
||||
</div>
|
||||
<!-- v-if="selectedRuleType === 'Activity sequence' && selectedActivitySequence === 'Sequence'" -->
|
||||
<!-- actSeqDrag -->
|
||||
<ActSeqDrag v-if="selectedRuleType === 'Activity sequence' && selectedActivitySequence === 'Sequence'"></ActSeqDrag>
|
||||
|
||||
<!-- Activity duration -->
|
||||
<ActRadio v-if="selectedRuleType === 'Activity duration'" :title="'Activities include'" :v-model="'actInclude'" :data="data" />
|
||||
<!-- Processing time -->
|
||||
<ActRadio v-if="selectedRuleType === 'Processing time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'Start'" :title="'Start'" :v-model="'protimeStartRadio'" :data="data" />
|
||||
<ActRadio v-if="selectedRuleType === 'Processing time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'End'" :title="'End'" :v-model="'protimeEndRadio'" :data="data" />
|
||||
<div v-if="selectedRuleType === 'Processing time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'Start & End'" class="flex h-full">
|
||||
<ActRadio :title="'Start'" :v-model="'protimeStartAndEndRadioStart'" :data="data" />
|
||||
<ActRadio :title="'End'" :v-model="'protimeStartAndEndRadioEnd'" :data="data" />
|
||||
</div>
|
||||
<ActRadio v-if="selectedRuleType === 'Processing time' && selectedProcessScope === 'Partial' && selectedActSeqFromTo === 'From'" :title="'From'" :v-model="'protimeFromRadio'" :data="data" />
|
||||
<ActRadio v-if="selectedRuleType === 'Processing time' && selectedProcessScope === 'Partial' && selectedActSeqFromTo === 'To'" :title="'To'" :v-model="'protimeToRadio'" :data="data" />
|
||||
<div v-if="selectedRuleType === 'Processing time' && selectedProcessScope === 'Partial' && selectedActSeqFromTo === 'From & To'" class="flex h-full">
|
||||
<ActRadio :title="'From'" :v-model="'protimeFromAndToRadioFrom'" :data="data" />
|
||||
<ActRadio :title="'To'" :v-model="'protimeFromAndToRadioTo'" :data="data" />
|
||||
</div>
|
||||
<!-- Waiting time -->
|
||||
<ActRadio v-if="selectedRuleType === 'Waiting time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'Start'" :title="'Start'" :v-model="'waittimeStartRadio'" :data="data" />
|
||||
<ActRadio v-if="selectedRuleType === 'Waiting time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'End'" :title="'End'" :v-model="'waittimeEndRadio'" :data="data" />
|
||||
<div v-if="selectedRuleType === 'Waiting time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'Start & End'" class="flex h-full">
|
||||
<ActRadio :title="'Start'" :v-model="'waittimeStartAndEndRadioStart'" :data="data" />
|
||||
<ActRadio :title="'End'" :v-model="'waittimeStartAndEndRadioEnd'" :data="data" />
|
||||
</div>
|
||||
<ActRadio v-if="selectedRuleType === 'Waiting time' && selectedProcessScope === 'Partial' && selectedActSeqFromTo === 'From'" :title="'From'" :v-model="'waittimeFromRadio'" :data="data" />
|
||||
<ActRadio v-if="selectedRuleType === 'Waiting time' && selectedProcessScope === 'Partial' && selectedActSeqFromTo === 'To'" :title="'To'" :v-model="'waittimeToRadio'" :data="data" />
|
||||
<div v-if="selectedRuleType === 'Waiting time' && selectedProcessScope === 'Partial' && selectedActSeqFromTo === 'From & To'" class="flex h-full">
|
||||
<ActRadio :title="'From'" :v-model="'waittimeFromAndToRadioFrom'" :data="data" />
|
||||
<ActRadio :title="'To'" :v-model="'waittimeFromAndToRadioTo'" :data="data" />
|
||||
</div>
|
||||
<!-- Cycle time -->
|
||||
<ActRadio v-if="selectedRuleType === 'Cycle time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'Start'" :title="'Start'" :v-model="'cyctimeStartRadio'" :data="data" />
|
||||
<ActRadio v-if="selectedRuleType === 'Cycle time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'End'" :title="'End'" :v-model="'cyctimeEndRadio'" :data="data" />
|
||||
<div v-if="selectedRuleType === 'Cycle time' && selectedProcessScope === 'End to end' && selectedActSeqMore === 'Start & End'" class="flex h-full">
|
||||
<ActRadio :title="'Start'" :v-model="'cyctimeStartAndEndRadioStart'" :data="data" />
|
||||
<ActRadio :title="'End'" :v-model="'cyctimeStartAndEndRadioEnd'" :data="data" />
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</template>
|
||||
@@ -14,18 +60,25 @@ import { storeToRefs } from 'pinia';
|
||||
import LoadingStore from '@/stores/loading.js';
|
||||
import ConformanceStore from '@/stores/conformance.js';
|
||||
import ActList from './ActList.vue';
|
||||
import ActRadio from './ActRadio.vue';
|
||||
import ActSeqDrag from './ActSeqDrag.vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const loadingStore = LoadingStore();
|
||||
const conformanceStore = ConformanceStore();
|
||||
const { isLoading } = storeToRefs(loadingStore);
|
||||
const { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore } = storeToRefs(conformanceStore);
|
||||
const { selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore, selectedActSeqFromTo, conformanceTask } = storeToRefs(conformanceStore);
|
||||
|
||||
return { isLoading, selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore }
|
||||
return { isLoading, selectedRuleType, selectedActivitySequence, selectedMode, selectedProcessScope, selectedActSeqMore, selectedActSeqFromTo, conformanceTask }
|
||||
},
|
||||
components: {
|
||||
ActList,
|
||||
ActList, ActRadio, ActSeqDrag
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
data:['到到到到到到到到到到到到到到到到到到到到到到院', '住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住住院', '開開開開開開開開開開開開開開開開開開開開開開刀', '第第第第第第第第第第一次醫囑', 'aaaaaaaaaaaaaaaa', 'bb ccc ddddd eeee', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院 到院 到院 到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院', '住院', '開刀', '第一次醫囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑囑', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院院院院院院院院院院院院院院院院院院院院院院院院院院院', '到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院', '到院', '住院', '開刀', '第一次醫囑', '第二次醫囑', '照會', '繳費', '領藥', '出院']
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="mt-2">
|
||||
<p class="h2">Time Range</p>
|
||||
<div>
|
||||
<Durationjs></Durationjs>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Durationjs from '@/components/durationjs.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectTimeRange: [20, 80],
|
||||
selectedStart: null,
|
||||
selectedEnd: null,
|
||||
timeStart: ['Sec(s)', 'Min(s)', 'Hour(s)', 'Day(s)', 'Week(s)', 'Mon(s)'],
|
||||
timeEnd: ['Sec(s)', 'Min(s)', 'Hour(s)', 'Day(s)', 'Week(s)', 'Mon(s)'],
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Durationjs,
|
||||
},
|
||||
created() {
|
||||
this.selectedStart = this.timeStart[1];
|
||||
this.selectedEnd = this.timeEnd[5];
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.time-preview {
|
||||
border: 1px solid #eee;
|
||||
max-width: 400px;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background: rgb(70, 25, 173);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.time-preview-time {
|
||||
font-size: 30px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,116 @@
|
||||
<template>
|
||||
<Dialog :visible="issusModal" modal header="Header" :style="{ width: '50vw' }">
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
<Dialog :visible="issusModal" @update:visible="$emit('update:isVisible', $event)" modal :style="{ width: '90vw', height: '90vh' }" :contentClass="contentClass">
|
||||
<template #header>
|
||||
<div class=" py-5">
|
||||
<p class="text-base font-bold">Non-conformance Issue</p>
|
||||
</div>
|
||||
</template>
|
||||
<div class="h-full flex items-start justify-start p-4">
|
||||
<!-- Trace List -->
|
||||
<section class="w-80 h-full pr-4">
|
||||
<p class="h2 px-2 mb-2">Trace List ({{ traceTotal }})</p>
|
||||
<p class="text-primary h2 px-2 mb-2">
|
||||
<span class="material-symbols-outlined text-sm align-[-10%] mr-2">info</span>Click trace number to see more.
|
||||
</p>
|
||||
<div class="overflow-y-scroll overflow-x-hidden scrollbar mx-[-8px] max-h-[calc(100%_-_96px)]" >
|
||||
<table class="border-separate border-spacing-x-2 text-sm">
|
||||
<thead class="sticky top-0 z-10 bg-neutral-100">
|
||||
<tr>
|
||||
<th class="h2 px-2 border-b border-neutral-500">Trace</th>
|
||||
<th class="h2 px-2 border-b border-neutral-500 text-start" colspan="3">Occurrences</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(trace, key) in traceList" :key="key" class=" cursor-pointer hover:text-primary" @click="switchCaseData(trace.id)">
|
||||
<td class="p-2">#{{ trace.id }}</td>
|
||||
<td class="p-2 w-24">
|
||||
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||
<div class="h-full bg-primary" :style="progressWidth(trace.value)"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-2 text-right">{{ trace.count }}</td>
|
||||
<td class="p-2">{{ trace.ratio }}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Trace item Table -->
|
||||
<section class="px-4 py-2 h-full w-[calc(100%_-_320px)] bg-neutral-10 rounded-xl">
|
||||
<p class="h2 mb-2 px-4">Trace #{{ showTraceId }}</p>
|
||||
<div class="h-52 w-full px-2 mb-2 border border-neutral-300 rounded">
|
||||
<div class="h-full w-full">
|
||||
<div id="cyTrace" ref="cyTrace" class="h-full min-w-full relative"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-auto overflow-x-auto scrollbar h-[calc(100%_-_264px)]">
|
||||
<DataTable :value="cases" showGridlines tableClass="text-sm" breakpoint="0">
|
||||
<Column field="id" header="Case ID" sortable></Column>
|
||||
<Column field="started_at" header="Start time" sortable></Column>
|
||||
<Column field="completed_at" header="End time" sortable></Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['issusModal'],
|
||||
data() {
|
||||
return {
|
||||
contentClass: '!bg-neutral-100 border-t border-neutral-300 h-full',
|
||||
traceList:[
|
||||
{
|
||||
id: 1,
|
||||
value: 80,
|
||||
count: 1234567890,
|
||||
ratio: 100,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: 80,
|
||||
count: 4567890,
|
||||
ratio: 100,
|
||||
},
|
||||
],
|
||||
showTraceId: 1,
|
||||
cases:[
|
||||
{
|
||||
id: 1,
|
||||
started_at: '2222/11/11',
|
||||
completed_at: '2222/11/11'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
started_at: '2222/11/11',
|
||||
completed_at: '2222/11/11'
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
traceTotal: function() {
|
||||
return this.traceList.length;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* set progress bar width
|
||||
* @param {number} value
|
||||
* @returns {string} 樣式的寬度設定
|
||||
*/
|
||||
progressWidth(value){
|
||||
return `width:${value}%;`
|
||||
},
|
||||
/**
|
||||
* switch case data
|
||||
* @param {number} id
|
||||
*/
|
||||
async switchCaseData(id) {
|
||||
this.showTraceId = id;
|
||||
this.$emit('switch-Trace-Id', this.showTraceId);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<template>
|
||||
<section class="w-full top-0">
|
||||
<!-- <section class="w-full top-0"> -->
|
||||
<section class="w-full top-0 absolute shadow-[0px_6px_6px_inset_rgba(0,0,0,0.1)]">
|
||||
<!-- status content -->
|
||||
<ul class="bg-neutral-100 flex justify-start shadow-[0px_1px_4px_rgba(0,0,0,0.2)] gap-3 p-3 text-sm overflow-x-auto scrollbar duration-700 " >
|
||||
<ul class="bg-neutral-100 flex justify-start shadow-[0px_1px_4px_rgba(0,0,0,0.2)] gap-3 p-3 text-sm overflow-x-auto scrollbar duration-700" :class="isPanel?'':'hidden'">
|
||||
<li class="bg-neutral-10 rounded p-3 w-full">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<p class="font-bold text-sm leading-8">Cases</p>
|
||||
@@ -76,12 +75,10 @@
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- absolute -->
|
||||
<!-- :class="isPanel?'':'hidden'" -->
|
||||
<!-- control button -->
|
||||
<!-- <div class="bg-neutral-300 rounded-b-full w-20 text-center mx-auto cursor-pointer hover:bg-neutral-500 hover:text-neutral-10 active:ring focus:outline-none focus:border-neutral-500 focus:ring" @click="isPanel = !isPanel">
|
||||
<div class="bg-neutral-300 rounded-b-full w-20 text-center mx-auto cursor-pointer hover:bg-neutral-500 hover:text-neutral-10 active:ring focus:outline-none focus:border-neutral-500 focus:ring" @click="isPanel = !isPanel">
|
||||
<span class="material-symbols-outlined block px-8 text-xs ">{{ isPanel ? 'keyboard_double_arrow_up' : 'keyboard_double_arrow_down' }}</span>
|
||||
</div> -->
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -92,6 +89,9 @@ export default {
|
||||
isPanel: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.isPanel = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
198
src/components/durationjs.vue
Normal file
198
src/components/durationjs.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="duration-box" v-for="(unit, index) in inputTypes" :key="unit">
|
||||
<input
|
||||
type="text"
|
||||
class="duration duration-val"
|
||||
:data-index="index"
|
||||
:data-tunit="unit"
|
||||
:data-max="tUnits[unit].max"
|
||||
:maxlength="tUnits[unit].dsp === 'd' ? 3 : 2"
|
||||
:value="tUnits[unit].val.toString().padStart(2, '0')"
|
||||
@focus="onFocus"
|
||||
@blur="onBlur"
|
||||
@keyup="onKeyUp"
|
||||
/>
|
||||
<label class="duration">{{ tUnits[unit].dsp }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
display: 'dhms',
|
||||
seconds: 0,
|
||||
minutes: 0,
|
||||
hours: 0,
|
||||
days: 0,
|
||||
totalSeconds: 0,
|
||||
apiTotal: 8740000,
|
||||
inputTypes: [],
|
||||
lastInput: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tUnits: {
|
||||
get() {
|
||||
return {
|
||||
s: { dsp: 's', inc: 1, val: this.seconds, max: 60, rate: 1 },
|
||||
m: { dsp: 'm', inc: 1, val: this.minutes, max: 60, rate: 60 },
|
||||
h: { dsp: 'h', inc: 1, val: this.hours, max: 24, rate: 3600 },
|
||||
d: { dsp: 'd', inc: 1, val: this.days, max: this.days, rate: 86400 }
|
||||
};
|
||||
},
|
||||
set(newValues) {
|
||||
// 大於最大值時要等於最大值
|
||||
for (const unit in newValues) {
|
||||
this[unit] = newValues[unit].val;
|
||||
const input = document.querySelector(`[data-tunit="${unit}"]`);
|
||||
if (input) {
|
||||
input.value = newValues[unit].val.toString().padStart(2, '0');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onFocus(event) {
|
||||
this.lastInput = event.target;
|
||||
this.lastInput.select(); // 當呼叫該方法時,文本框內的文字會被自動選中,這樣使用者可以方便地進行複製或刪除等操作。
|
||||
},
|
||||
onBlur(event) {
|
||||
isNaN(event.target.value) ?
|
||||
event.target.value = '00' :
|
||||
event.target.value = event.target.value.toString().padStart(2, '0');
|
||||
|
||||
// 手 key 數值大於最大值時,要等於最大值
|
||||
if(event.target.value > event.target.dataset.max) event.target.value = (event.target.dataset.max - 1).toString().padStart(2, '0');
|
||||
|
||||
// 數值更新, tUnits 也更新, 並計算 totalSeconds
|
||||
this.tUnits[event.target.dataset.tunit].val = event.target.value;
|
||||
this.calculateTotalSeconds();
|
||||
},
|
||||
onKeyUp(event) {
|
||||
event.target.value = event.target.value.replace(/\D/g, '');
|
||||
|
||||
if (event.keyCode === 38 || event.keyCode === 40) {
|
||||
this.actionUpDown(event.target, event.keyCode === 38, true);
|
||||
};
|
||||
},
|
||||
actionUpDown(input, goUp, selectIt = false) {
|
||||
const tUnit = input.dataset.tunit;
|
||||
let newVal = parseInt(input.value, 10);
|
||||
newVal = isNaN(newVal) ? 0 : newVal;
|
||||
newVal += (goUp ? 1 : -1) * this.tUnits[tUnit].inc;
|
||||
|
||||
if (newVal <= 0 || newVal >= this.tUnits[tUnit].max) {
|
||||
if (newVal === 0 || (newVal < 0 && input.dataset.index < 1)) {
|
||||
newVal = '00';
|
||||
} else if (input.dataset.index >= 1) {
|
||||
const nextUnit = document.querySelector(`input[data-index="${parseInt(input.dataset.index) - 1}"]`);
|
||||
let nextUnitVal = parseInt(nextUnit.value);
|
||||
|
||||
if (newVal < 0 && nextUnitVal > 0) {
|
||||
nextUnit.value = nextUnitVal - 1;
|
||||
nextUnit.dispatchEvent(new Event('blur'));
|
||||
newVal = this.tUnits[tUnit].max - this.tUnits[tUnit].inc;
|
||||
} else if (newVal > 0) {
|
||||
nextUnit.value = nextUnitVal + 1;
|
||||
nextUnit.dispatchEvent(new Event('blur'));
|
||||
newVal = '00';
|
||||
} else {
|
||||
newVal = '00';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.value = newVal.toString().padStart(2, '0');
|
||||
if (selectIt) input.select();
|
||||
},
|
||||
secondToDate(totalSeconds) {
|
||||
// .toString().padStart(2, '0')
|
||||
totalSeconds = parseInt(totalSeconds);
|
||||
if(!isNaN(totalSeconds)) {
|
||||
this.seconds = totalSeconds % 60;
|
||||
this.minutes = (Math.floor(totalSeconds - this.seconds) / 60) % 60;
|
||||
this.hours = (Math.floor(totalSeconds / 3600)) % 24;
|
||||
this.days = Math.floor(totalSeconds / (3600 * 24));
|
||||
}
|
||||
},
|
||||
calculateTotalSeconds() {
|
||||
let totalSeconds = 0;
|
||||
let tUnits = {
|
||||
s: { dsp: 's', inc: 1, val: this.seconds, max: 60, rate: 1 },
|
||||
m: { dsp: 'm', inc: 1, val: this.minutes, max: 60, rate: 60 },
|
||||
h: { dsp: 'h', inc: 1, val: this.hours, max: 24, rate: 3600 },
|
||||
d: { dsp: 'd', inc: 1, val: this.days, max: this.days, rate: 86400 },
|
||||
};
|
||||
|
||||
for (const unit in this.tUnits) {
|
||||
const val = parseInt(this.tUnits[unit].val, 10);
|
||||
if (!isNaN(val)) totalSeconds += val * this.tUnits[unit].rate;
|
||||
}
|
||||
|
||||
// 大於最大值時要等於最大值
|
||||
if(totalSeconds >= this.apiTotal){
|
||||
totalSeconds = this.apiTotal;
|
||||
this.tUnits = tUnits;
|
||||
this.secondToDate(this.apiTotal);
|
||||
} else {
|
||||
this.totalSeconds = totalSeconds;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.inputTypes = this.display.split('');
|
||||
this.secondToDate(this.apiTotal);
|
||||
this.totalSeconds = this.apiTotal;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.duration-box {
|
||||
float:left;
|
||||
overflow: auto;
|
||||
height: var(--main-input-height);
|
||||
}
|
||||
.duration-box > .duration {
|
||||
border: 1px solid var(--main-bg-light);
|
||||
border-right: 0;
|
||||
border-left: 0;
|
||||
background-color:transparent;
|
||||
color: var(--main-bg-light);
|
||||
}
|
||||
.duration-box > .duration:nth-child(1) {
|
||||
border-left: 1px solid var(--main-bg-light);
|
||||
border-top-left-radius: var(--main-input-br);
|
||||
border-bottom-left-radius: var(--main-input-br);
|
||||
}
|
||||
.duration-box > .duration:nth-last-child(1) {
|
||||
border-right: 1px solid var(--main-bg-light);
|
||||
border-top-right-radius: var(--main-input-br);
|
||||
border-bottom-right-radius: var(--main-input-br);
|
||||
}
|
||||
.duration {
|
||||
float:left;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
height: var(--main-input-height);
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
.duration-box > label.duration {
|
||||
line-height: 28px;
|
||||
width: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.duration-box > input[type="text"].duration {
|
||||
text-align: right;
|
||||
width: 26px;
|
||||
padding: 3px 2px 0px 0px;
|
||||
}
|
||||
.duration-box > input[type="button"].duration {
|
||||
width: 60px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
22
src/module/sortNumEngZhtw.js
Normal file
22
src/module/sortNumEngZhtw.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 數字、英文、中文,排序
|
||||
* @param {array} data
|
||||
* @returns
|
||||
*/
|
||||
export default function sortNumEngZhtw(data) {
|
||||
return data.sort((a, b) => {
|
||||
// 檢查兩個值是否都是數字
|
||||
var isANumber = !isNaN(parseFloat(a)) && isFinite(a);
|
||||
var isBNumber = !isNaN(parseFloat(b)) && isFinite(b);
|
||||
|
||||
// 如果兩個值都是數字,直接比較大小
|
||||
if (isANumber && isBNumber) return parseFloat(a) - parseFloat(b);
|
||||
|
||||
// 如果其中一個值是數字,將數字視為最小,排在前面
|
||||
if (isANumber) return -1;
|
||||
if (isBNumber) return 1;
|
||||
|
||||
// 其他情況下,使用 localeCompare 方法進行中文排序
|
||||
return a.localeCompare(b, 'zh-Hant-TW', { sensitivity: 'accent' });
|
||||
});
|
||||
}
|
||||
@@ -1,17 +1,53 @@
|
||||
import { defineStore } from "pinia";
|
||||
import loadingStore from "./loading";
|
||||
import pinia from '@/stores/main.js';
|
||||
import {useToast} from 'vue-toast-notification';
|
||||
import 'vue-toast-notification/dist/theme-sugar.css';
|
||||
|
||||
const loading = loadingStore(pinia);
|
||||
const $toast = useToast();
|
||||
// Delay loading and toast 待模組化
|
||||
let delay = (s = 0) => new Promise((resolve, reject) => setTimeout(resolve, s));
|
||||
|
||||
export default defineStore('conformanceStore', {
|
||||
state: () => ({
|
||||
selectedRuleType: 'Have activity',
|
||||
selectedActivitySequence: 'Start & End',
|
||||
selectedMode: 'Directly follows',
|
||||
selectedProcessScope: 'End to end',
|
||||
selectedActSeqMore: 'All',
|
||||
logId: null,
|
||||
filterId: null,
|
||||
allConformanceTask: [],
|
||||
selectedRuleType: 'Have activity', // radio
|
||||
selectedActivitySequence: 'Start & End', // radio
|
||||
selectedMode: 'Directly follows', // radio
|
||||
selectedProcessScope: 'End to end', // radio
|
||||
selectedActSeqMore: 'All', // radio
|
||||
selectedActSeqFromTo: 'From', // radio
|
||||
}),
|
||||
getters: {},
|
||||
actions: {},
|
||||
getters: {
|
||||
conformanceTask: state => {
|
||||
return state.allConformanceTask;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* fetch Log Conformance Parameters api for Rule Settings.
|
||||
*/
|
||||
async getLogConformanceParams() {
|
||||
let logId = this.logId;
|
||||
const api = `/api/log-checkers/params?log_id=${logId}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
console.log(response);
|
||||
this.allConformanceTask = response.data.tasks;
|
||||
|
||||
} catch(error) {
|
||||
console.log(error);
|
||||
await delay();
|
||||
loading.isLoading = true;
|
||||
await delay(1000);
|
||||
loading.isLoading = false;
|
||||
await delay(500);
|
||||
$toast.default('Failed to load the Conformance Parameters.',{position: 'bottom'});
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<template>
|
||||
<main class="h-screen-main">
|
||||
<StatusBar></StatusBar>
|
||||
<main class="h-screen-main relative">
|
||||
<!-- <StatusBar></StatusBar> -->
|
||||
<div class="h-full relative bg-neutral-50">
|
||||
<ConformanceSidebar></ConformanceSidebar>
|
||||
<ConformanceResults></ConformanceResults>
|
||||
</div>
|
||||
<!-- <StatusBar></StatusBar> -->
|
||||
<StatusBar></StatusBar>
|
||||
</main>
|
||||
</template>
|
||||
<script>
|
||||
import { storeToRefs } from 'pinia';
|
||||
import LoadingStore from '@/stores/loading.js';
|
||||
import ConformanceStore from '@/stores/conformance.js';
|
||||
import StatusBar from '@/components/Discover/Conformance/StatusBar.vue';
|
||||
import ConformanceResults from '@/components/Discover/Conformance/ConformanceResults.vue';
|
||||
import ConformanceSidebar from '@/components/Discover/Conformance/ConformanceSidebar.vue';
|
||||
@@ -18,9 +19,11 @@ import ConformanceSidebar from '@/components/Discover/Conformance/ConformanceSid
|
||||
export default {
|
||||
setup() {
|
||||
const loadingStore = LoadingStore();
|
||||
const conformanceStore = ConformanceStore();
|
||||
const { isLoading } = storeToRefs(loadingStore);
|
||||
const { logId } = storeToRefs(conformanceStore);
|
||||
|
||||
return { isLoading }
|
||||
return { isLoading, logId, conformanceStore }
|
||||
},
|
||||
components: {
|
||||
StatusBar,
|
||||
@@ -28,8 +31,11 @@ export default {
|
||||
ConformanceSidebar,
|
||||
},
|
||||
async created() {
|
||||
let logId;
|
||||
if(this.$route.params.type === 'log') logId = this.$route.params.fileId;
|
||||
// let logId;
|
||||
if(this.$route.params.type === 'log') this.logId = this.$route.params.fileId;
|
||||
console.log(this.logId);
|
||||
|
||||
await this.conformanceStore.getLogConformanceParams();
|
||||
|
||||
// this.isLoading = true;
|
||||
this.isLoading = false;
|
||||
|
||||
Reference in New Issue
Block a user