You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by wu...@apache.org on 2019/09/04 03:27:57 UTC

[skywalking-rocketbot-ui] branch master updated: #106 cache/persist page query states (#150)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-rocketbot-ui.git


The following commit(s) were added to refs/heads/master by this push:
     new 91aa38f  #106 cache/persist page query states (#150)
91aa38f is described below

commit 91aa38feb4fb965c5eb0596b8196dce71d30636d
Author: x22x22 <ro...@gmail.com>
AuthorDate: Wed Sep 4 11:27:53 2019 +0800

    #106 cache/persist page query states (#150)
    
    * #106:Cache/Persist page query states
---
 src/assets/lang/en.ts                       |   1 +
 src/assets/lang/zh.ts                       |   3 +-
 src/store/modules/global/index.ts           | 108 ++++---
 src/store/modules/trace/index.ts            |  68 +++--
 src/store/mutation-types.ts                 |   1 +
 src/types/topo.d.ts                         |   5 +
 src/utils/comparison.ts                     |   1 +
 src/utils/{comparison.ts => datetime.ts}    |  29 +-
 src/views/components/trace/trace-search.vue | 425 +++++++++++++++++-----------
 9 files changed, 405 insertions(+), 236 deletions(-)

diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts
index 7d36a8f..fb224ef 100644
--- a/src/assets/lang/en.ts
+++ b/src/assets/lang/en.ts
@@ -68,6 +68,7 @@ const m = {
   status: 'Status',
   endpointName: 'Endpoint Name',
   search: 'Search',
+  clear: 'Clear',
   more: 'More',
   traceID: 'TraceID',
   range: 'Range',
diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts
index 80ae5ed..11b15d8 100644
--- a/src/assets/lang/zh.ts
+++ b/src/assets/lang/zh.ts
@@ -68,6 +68,7 @@ const m = {
   status: '状态',
   endpointName: '端点名称',
   search: '搜索',
+  clear: '清空',
   more: '更多',
   traceID: '追踪ID',
   range: '范围',
@@ -77,7 +78,7 @@ const m = {
   start: '起始点',
   spans: '跨度',
   spanInfo: '跨度信息',
-  spanType:  '跨度类型',
+  spanType: '跨度类型',
   time: '时间',
   tags: '标记',
   logs: '日志',
diff --git a/src/store/modules/global/index.ts b/src/store/modules/global/index.ts
index f1f30cf..b38691a 100644
--- a/src/store/modules/global/index.ts
+++ b/src/store/modules/global/index.ts
@@ -15,52 +15,85 @@
  * limitations under the License.
  */
 
-import { Commit, ActionTree, MutationTree, GetterTree, Getter } from 'vuex';
-import getLocalTime from '@/utils/localtime';
-import { Duration, DurationTime } from '@/types/global';
 import * as types from '@/store/mutation-types';
+import { Duration, DurationTime } from '@/types/global';
+import getDurationRow from '@/utils/datetime';
+import getLocalTime from '@/utils/localtime';
 import Vue from 'vue';
+import { ActionTree, Commit, MutationTree } from 'vuex';
 
 let timer: any = null;
 
-const dateFormate = (date: Date, step: string): string => {
+const dateFormat = (date: Date, step: string): string => {
   const year = date.getFullYear();
   const monthTemp = date.getMonth() + 1;
   let month: string = `${monthTemp}`;
-  if (monthTemp < 10) { month = `0${monthTemp}`; }
-  if (step === 'MONTH') { return `${year}-${month}`; }
+  if (monthTemp < 10) {
+    month = `0${monthTemp}`;
+  }
+  if (step === 'MONTH') {
+    return `${year}-${month}`;
+  }
   const dayTemp = date.getDate();
   let day: string = `${dayTemp}`;
-  if (dayTemp < 10) { day = `0${dayTemp}`; }
-  if (step === 'DAY') { return `${year}-${month}-${day}`; }
+  if (dayTemp < 10) {
+    day = `0${dayTemp}`;
+  }
+  if (step === 'DAY') {
+    return `${year}-${month}-${day}`;
+  }
   const hourTemp = date.getHours();
   let hour: string = `${hourTemp}`;
-  if (hourTemp < 10) { hour = `0${hourTemp}`; }
-  if (step === 'HOUR') { return `${year}-${month}-${day} ${hour}`; }
+  if (hourTemp < 10) {
+    hour = `0${hourTemp}`;
+  }
+  if (step === 'HOUR') {
+    return `${year}-${month}-${day} ${hour}`;
+  }
   const minuteTemp = date.getMinutes();
   let minute: string = `${minuteTemp}`;
-  if (minuteTemp < 10) { minute = `0${minuteTemp}`; }
-  if (step === 'MINUTE') { return `${year}-${month}-${day} ${hour}${minute}`; }
+  if (minuteTemp < 10) {
+    minute = `0${minuteTemp}`;
+  }
+  if (step === 'MINUTE') {
+    return `${year}-${month}-${day} ${hour}${minute}`;
+  }
   return '';
 };
-const dateFormateTime = (date: Date, step: string): string => {
+const dateFormatTime = (date: Date, step: string): string => {
   const year = date.getFullYear();
   const monthTemp = date.getMonth() + 1;
   let month: string = `${monthTemp}`;
-  if (monthTemp < 10) { month = `0${monthTemp}`; }
-  if (step === 'MONTH') { return `${year}-${month}`; }
+  if (monthTemp < 10) {
+    month = `0${monthTemp}`;
+  }
+  if (step === 'MONTH') {
+    return `${year}-${month}`;
+  }
   const dayTemp = date.getDate();
   let day: string = `${dayTemp}`;
-  if (dayTemp < 10) { day = `0${dayTemp}`; }
-  if (step === 'DAY') { return `${month}-${day}`; }
+  if (dayTemp < 10) {
+    day = `0${dayTemp}`;
+  }
+  if (step === 'DAY') {
+    return `${month}-${day}`;
+  }
   const hourTemp = date.getHours();
   let hour: string = `${hourTemp}`;
-  if (hourTemp < 10) { hour = `0${hourTemp}`; }
-  if (step === 'HOUR') { return `${month}-${day} ${hour}`; }
+  if (hourTemp < 10) {
+    hour = `0${hourTemp}`;
+  }
+  if (step === 'HOUR') {
+    return `${month}-${day} ${hour}`;
+  }
   const minuteTemp = date.getMinutes();
   let minute: string = `${minuteTemp}`;
-  if (minuteTemp < 10) { minute = `0${minuteTemp}`; }
-  if (step === 'MINUTE') { return `${hour}:${minute}\n${month}-${day}`; }
+  if (minuteTemp < 10) {
+    minute = `0${minuteTemp}`;
+  }
+  if (step === 'MINUTE') {
+    return `${hour}:${minute}\n${month}-${day}`;
+  }
   return '';
 };
 
@@ -81,11 +114,7 @@ export interface State {
 }
 
 const initState: State = {
-  durationRow: {
-    start: new Date(new Date().getTime() - 900000),
-    end: new Date(),
-    step: 'MINUTE',
-  },
+  durationRow: getDurationRow(),
   eventStack: [],
   chartStack: [],
   edit: false,
@@ -120,8 +149,8 @@ const getters = {
         break;
       case 'MONTH':
         interval = (getter.duration.end.getTime() - getter.duration.start.getTime())
-        / (getter.duration.end.getFullYear() * 12 + getter.duration.end.getMonth()
-        - getter.duration.start.getFullYear() * 12 - getter.duration.start.getMonth());
+          / (getter.duration.end.getFullYear() * 12 + getter.duration.end.getMonth()
+            - getter.duration.start.getFullYear() * 12 - getter.duration.start.getMonth());
         break;
     }
     const utcSpace = (parseInt(state.utc + '', 10) + new Date().getTimezoneOffset() / 60) * 3600000;
@@ -129,15 +158,15 @@ const getters = {
     const endUnix: number = getter.duration.end.getTime();
     const timeIntervals: string[] = [];
     for (let i = 0; i <= endUnix - startUnix; i += interval) {
-      const temp: string = dateFormateTime(new Date(startUnix + i - utcSpace), getter.duration.step);
+      const temp: string = dateFormatTime(new Date(startUnix + i - utcSpace), getter.duration.step);
       timeIntervals.push(temp);
     }
     return timeIntervals;
   },
   durationTime(_: State, getter: any): DurationTime {
     return {
-      start: dateFormate(getter.duration.start, getter.duration.step),
-      end: dateFormate(getter.duration.end, getter.duration.step),
+      start: dateFormat(getter.duration.start, getter.duration.step),
+      end: dateFormat(getter.duration.end, getter.duration.step),
       step: getter.duration.step,
     };
   },
@@ -146,8 +175,13 @@ const getters = {
 // mutations
 const mutations: MutationTree<State> = {
   [types.SET_DURATION](state: State, data: Duration): void {
+    localStorage.setItem('durationRow', JSON.stringify(data, null, 0));
     state.durationRow = data;
   },
+  [types.RESET_DURATION](state: State): void {
+    localStorage.removeItem('durationRow');
+    state.durationRow = getDurationRow();
+  },
   [types.SET_UTC](state: State, data: number): void {
     state.utc = data;
   },
@@ -159,7 +193,9 @@ const mutations: MutationTree<State> = {
   },
   [types.RUN_EVENTS](state: State): void {
     clearTimeout(timer);
-    timer = setTimeout(() => state.eventStack.forEach((event: any) => { setTimeout(event(), 0); }), 500);
+    timer = setTimeout(() => state.eventStack.forEach((event: any) => {
+      setTimeout(event(), 0);
+    }), 500);
   },
   [types.SET_EDIT](state: State, status: boolean): void {
     state.edit = status;
@@ -172,9 +208,15 @@ const actions: ActionTree<State, any> = {
     context.commit(types.SET_DURATION, data);
     context.commit(types.RUN_EVENTS);
   },
+  RESET_DURATION(context: { commit: Commit }): void {
+    context.commit(types.RESET_DURATION);
+    context.commit(types.RUN_EVENTS);
+  },
   RUN_EVENTS(context: { commit: Commit }): void {
     if (window.axiosCancel.length !== 0) {
-      for (const event of window.axiosCancel) { setTimeout(event(), 0); }
+      for (const event of window.axiosCancel) {
+        setTimeout(event(), 0);
+      }
       window.axiosCancel = [];
     }
     context.commit(types.RUN_EVENTS);
diff --git a/src/store/modules/trace/index.ts b/src/store/modules/trace/index.ts
index 11dad00..3c986ee 100644
--- a/src/store/modules/trace/index.ts
+++ b/src/store/modules/trace/index.ts
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-import { Commit, ActionTree, MutationTree, Dispatch } from 'vuex';
-import { AxiosResponse } from 'axios';
 import graph from '@/graph';
 import * as types from '@/store/mutation-types';
 import { Option } from '@/types/global';
-import { Trace, Span } from '@/types/topo';
+import { Span, Trace } from '@/types/topo';
+import { AxiosResponse } from 'axios';
+import { ActionTree, Commit, Dispatch, MutationTree } from 'vuex';
 
 export interface State {
   services: Option[];
@@ -37,7 +37,7 @@ const initState: State = {
   instances: [],
   traceForm: {
     paging: {pageNum: 1, pageSize: 15, needTotal: true},
-    queryOrder: 'BY_DURATION',
+    queryOrder: localStorage.getItem('traceQueryOrder') || 'BY_DURATION',
   },
   traceList: [],
   traceTotal: 0,
@@ -63,10 +63,26 @@ const mutations: MutationTree<State> = {
   [types.SET_INSTANCES](state: State, data: Option[]): void {
     state.instances = [{label: 'All', key: ''}].concat(data);
   },
-  [types.SET_TRACE_FORM](state: State, data: Option[]): void {
+  [types.SET_TRACE_FORM](state: State, data: any): void {
+    if (data.queryOrder) {
+      if (data.queryOrder === '') {
+        data.queryOrder = 'BY_DURATION';
+        localStorage.setItem('traceQueryOrder', 'BY_DURATION');
+      } else {
+        localStorage.setItem('traceQueryOrder', data.queryOrder);
+      }
+    }
     state.traceForm = data;
   },
   [types.SET_TRACE_FORM_ITEM](state: State, params: any): void {
+    if (params.type && params.type === 'queryOrder') {
+      if (params.data === '') {
+        params.data = 'BY_DURATION';
+        localStorage.setItem('traceQueryOrder', 'BY_DURATION');
+      } else {
+        localStorage.setItem('traceQueryOrder', params.data);
+      }
+    }
     state.traceForm[params.type] = params.data;
   },
   [types.SET_TRACELIST](state: State, data: Trace[]): void {
@@ -97,19 +113,19 @@ const mutations: MutationTree<State> = {
 const actions: ActionTree<State, any> = {
   GET_SERVICES(context: { commit: Commit }, params: any): Promise<void> {
     return graph
-    .query('queryServices')
-    .params(params)
-    .then((res: AxiosResponse) => {
-      context.commit(types.SET_SERVICES, res.data.data.services);
-    });
+      .query('queryServices')
+      .params(params)
+      .then((res: AxiosResponse) => {
+        context.commit(types.SET_SERVICES, res.data.data.services);
+      });
   },
   GET_INSTANCES(context: { commit: Commit }, params: any): Promise<void> {
     return graph
-    .query('queryServiceInstance')
-    .params(params)
-    .then((res: AxiosResponse) => {
-      context.commit(types.SET_INSTANCES, res.data.data.instanceId);
-    });
+      .query('queryServiceInstance')
+      .params(params)
+      .then((res: AxiosResponse) => {
+        context.commit(types.SET_INSTANCES, res.data.data.instanceId);
+      });
   },
   SET_TRACE_FORM(context: { commit: Commit, dispatch: Dispatch }, params: any): void {
     context.commit(types.SET_TRACE_FORM, params);
@@ -117,21 +133,21 @@ const actions: ActionTree<State, any> = {
   GET_TRACELIST(context: { state: State, commit: Commit }): Promise<void> {
     context.commit(types.SET_TRACELIST, []);
     return graph
-    .query('queryTraces')
-    .params({condition: context.state.traceForm})
-    .then((res: AxiosResponse) => {
-      context.commit(types.SET_TRACELIST, res.data.data.traces.data);
-      context.commit(types.SET_TRACELIST_TOTAL, res.data.data.traces.total);
-    });
+      .query('queryTraces')
+      .params({condition: context.state.traceForm})
+      .then((res: AxiosResponse) => {
+        context.commit(types.SET_TRACELIST, res.data.data.traces.data);
+        context.commit(types.SET_TRACELIST_TOTAL, res.data.data.traces.total);
+      });
   },
   GET_TRACE_SPANS(context: { commit: Commit }, params: any): Promise<void> {
     context.commit(types.SET_TRACE_SPANS, []);
     return graph
-    .query('queryTrace')
-    .params(params)
-    .then((res: AxiosResponse) => {
-      context.commit(types.SET_TRACE_SPANS, res.data.data.trace.spans);
-    });
+      .query('queryTrace')
+      .params(params)
+      .then((res: AxiosResponse) => {
+        context.commit(types.SET_TRACE_SPANS, res.data.data.trace.spans);
+      });
   },
 };
 
diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts
index cde9349..1a4c6d0 100644
--- a/src/store/mutation-types.ts
+++ b/src/store/mutation-types.ts
@@ -32,6 +32,7 @@ export const SET_GROUP_QUERY = 'SET_GROUP_QUERY';
 
 // global
 export const SET_DURATION = 'SET_DURATION';
+export const RESET_DURATION = 'RESET_DURATION';
 export const SET_EVENTS = 'SET_EVENTS';
 export const RUN_EVENTS = 'RUN_EVENTS';
 export const SET_CHARTS = 'SET_CHARTS';
diff --git a/src/types/topo.d.ts b/src/types/topo.d.ts
index db71d0b..2932ef5 100644
--- a/src/types/topo.d.ts
+++ b/src/types/topo.d.ts
@@ -20,6 +20,7 @@ export interface CompsContainer {
   database: CompsItem[];
   proxy: CompsItem[];
 }
+
 export interface CompsItem {
   o: string;
   comp: string;
@@ -28,10 +29,12 @@ export interface CompsItem {
   type?: string;
   w: number;
 }
+
 export interface CompsGroup {
   name: string;
   children: CompsItem[];
 }
+
 export interface CompQuery {
   service: Option;
   database: Option;
@@ -50,11 +53,13 @@ export interface Option {
   key: string;
   label: string;
 }
+
 export interface Duration {
   start: Date;
   end: Date;
   step: string;
 }
+
 export interface DurationTime {
   start: string;
   end: string;
diff --git a/src/utils/comparison.ts b/src/utils/comparison.ts
index 2ef47d4..14fe756 100644
--- a/src/utils/comparison.ts
+++ b/src/utils/comparison.ts
@@ -19,6 +19,7 @@
  * Shallow comparison of two objects.
  * @param objA Object A to be compared
  * @param objB Object B to be compared
+ * @return The same object return false, otherwise return true.
  */
 const compareObj = (objA: object, objB: object): boolean => {
   return JSON.stringify(Object.entries(objA).sort(), null, 0) !== JSON.stringify(Object.entries(objB).sort(), null, 0);
diff --git a/src/utils/comparison.ts b/src/utils/datetime.ts
similarity index 52%
copy from src/utils/comparison.ts
copy to src/utils/datetime.ts
index 2ef47d4..8cfdf45 100644
--- a/src/utils/comparison.ts
+++ b/src/utils/datetime.ts
@@ -15,13 +15,30 @@
  * limitations under the License.
  */
 
+import { Duration } from '@/types/global';
+
 /**
- * Shallow comparison of two objects.
- * @param objA Object A to be compared
- * @param objB Object B to be compared
+ * init or generate durationRow Obj and save localStorage.
  */
-const compareObj = (objA: object, objB: object): boolean => {
-  return JSON.stringify(Object.entries(objA).sort(), null, 0) !== JSON.stringify(Object.entries(objB).sort(), null, 0);
+const getDurationRow = (): Duration => {
+  const durationRowString = localStorage.getItem('durationRow');
+  let durationRow: Duration;
+  if (durationRowString && durationRowString !== '') {
+    durationRow = JSON.parse(durationRowString);
+    durationRow = {
+      start: new Date(durationRow.start),
+      end: new Date(durationRow.end),
+      step: durationRow.step,
+    };
+  } else {
+    durationRow = {
+      start: new Date(new Date().getTime() - 900000),
+      end: new Date(),
+      step: 'MINUTE',
+    };
+    localStorage.setItem('durationRow', JSON.stringify(durationRow, null, 0));
+  }
+  return durationRow;
 };
 
-export default compareObj;
+export default getDurationRow;
diff --git a/src/views/components/trace/trace-search.vue b/src/views/components/trace/trace-search.vue
index 5d4ae31..7b5d8eb 100644
--- a/src/views/components/trace/trace-search.vue
+++ b/src/views/components/trace/trace-search.vue
@@ -1,24 +1,24 @@
 /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
 
 <template>
   <div class="rk-trace-search">
     <div>
-      <a class="rk-trace-search-btn r" @click="status = !status">
+      <a class="rk-trace-clear-btn r" @click="status = !status">
         <span class="mr-5 vm">{{this.$t('more')}}</span>
         <svg class="icon trans vm" :style="`transform: rotate(${status?180:0}deg);`">
           <use xlink:href="#arrow-down"></use>
@@ -30,14 +30,21 @@
         </svg>
         <span class="vm">{{this.$t('search')}}</span>
       </a>
+      <a class="rk-trace-clear-btn bg-warning r mr-10" @click="clearSearch">
+        <svg class="icon mr-5 vm">
+          <use xlink:href="#clear"></use>
+        </svg>
+        <span class="vm">{{this.$t('clear')}}</span>
+      </a>
       <div class="flex-h">
-        <TraceSelect :hasSearch="true" :title="this.$t('service')" :value="service" @input="chooseService" :data="rocketTrace.services"/>
+        <TraceSelect :hasSearch="true" :title="this.$t('service')" :value="service" @input="chooseService"
+                     :data="rocketTrace.services"/>
         <TraceSelect :hasSearch="true" :title="this.$t('instance')" v-model="instance" :data="rocketTrace.instances"/>
-        <TraceSelect  :title="this.$t('status')" :value="traceState" @input="chooseStatus"
-        :data="[{label:'All', key: 'ALL'}, {label:'Success', key: 'SUCCESS'}, {label:'Error', key: 'ERROR'}]"/>
+        <TraceSelect :title="this.$t('status')" :value="traceState" @input="chooseStatus"
+                     :data="[{label:'All', key: 'ALL'}, {label:'Success', key: 'SUCCESS'}, {label:'Error', key: 'ERROR'}]"/>
         <div class="mr-10" style="padding: 3px 15px 0">
           <div class="sm grey">{{this.$t('endpointName')}}</div>
-          <input type="text"  v-model="endpointName" class="rk-trace-search-input">
+          <input type="text" v-model="endpointName" class="rk-trace-search-input">
         </div>
       </div>
     </div>
@@ -63,174 +70,252 @@
 </template>
 
 <script lang="ts">
-import { Vue, Component } from 'vue-property-decorator';
-import { Action, Getter, State } from 'vuex-class';
-import { Trace } from '@/types/trace';
-import { DurationTime, Option } from '@/types/global';
-import TraceSelect from './trace-select.vue';
-
-@Component({components: {TraceSelect}})
-export default class TraceTool extends Vue {
-  @State('rocketbot') private rocketbotGlobal: any;
-  @State('rocketTrace') private rocketTrace: any;
-  @Getter('durationTime') private durationTime: any;
-  @Getter('duration') private duration: any;
-  @Action('rocketTrace/GET_SERVICES') private GET_SERVICES: any;
-  @Action('rocketTrace/GET_INSTANCES') private GET_INSTANCES: any;
-  @Action('rocketTrace/GET_TRACELIST') private GET_TRACELIST: any;
-  @Action('rocketTrace/SET_TRACE_FORM') private SET_TRACE_FORM: any;
-
-  private time: Date[] = [new Date() , new Date()];
-  private status: boolean = true;
-  private maxTraceDuration: string = '';
-  private minTraceDuration: string = '';
-  private service: Option  = {label: 'All', key: ''};
-  private instance: Option  = {label: 'All', key: ''};
-  private endpointName: string = '';
-  private traceId: string = '';
-  private traceState: Option  = {label: 'All', key: 'ALL'};
-  get eventHub() {
-    return this.$store.getters.globalEventHub;
-  }
-  private dateFormate = (date: Date, step: string) => {
-    const year = date.getFullYear();
-    const monthTemp = date.getMonth() + 1;
-    let month: string = `${monthTemp}`;
-    if (monthTemp < 10) {
-      month = `0${monthTemp}`;
+  import { Duration, Option } from '@/types/global';
+  import { Component, Vue, Watch } from 'vue-property-decorator';
+  import { Action, Getter, Mutation, State } from 'vuex-class';
+  import TraceSelect from './trace-select.vue';
+
+  @Component({components: {TraceSelect}})
+  export default class TraceTool extends Vue {
+    @State('rocketbot') private rocketbotGlobal: any;
+    @State('rocketTrace') private rocketTrace: any;
+    @Getter('durationTime') private durationTime: any;
+    @Getter('duration') private duration: any;
+    @Action('RESET_DURATION') private RESET_DURATION: any;
+    @Action('rocketTrace/GET_SERVICES') private GET_SERVICES: any;
+    @Action('rocketTrace/GET_INSTANCES') private GET_INSTANCES: any;
+    @Action('rocketTrace/GET_TRACELIST') private GET_TRACELIST: any;
+    @Action('rocketTrace/SET_TRACE_FORM') private SET_TRACE_FORM: any;
+    @Mutation('rocketTrace/SET_TRACE_FORM_ITEM') private SET_TRACE_FORM_ITEM: any;
+
+    private time!: Date[];
+    private status: boolean = true;
+    private maxTraceDuration: string = localStorage.getItem('maxTraceDuration') || '';
+    private minTraceDuration: string = localStorage.getItem('minTraceDuration') || '';
+    private service: Option = {label: 'All', key: ''};
+    private instance: Option = {label: 'All', key: ''};
+    private endpointName: string = localStorage.getItem('endpointName') || '';
+    private traceId: string = localStorage.getItem('traceId') || '';
+    private traceState: Option = {label: 'All', key: 'ALL'};
+
+    get eventHub() {
+      return this.$store.getters.globalEventHub;
     }
-    if (step === 'MONTH') {
-      return `${year}-${month}`;
+
+    private dateFormat = (date: Date, step: string) => {
+      const year = date.getFullYear();
+      const monthTemp = date.getMonth() + 1;
+      let month: string = `${monthTemp}`;
+      if (monthTemp < 10) {
+        month = `0${monthTemp}`;
+      }
+      if (step === 'MONTH') {
+        return `${year}-${month}`;
+      }
+      const dayTemp = date.getDate();
+      let day: string = `${dayTemp}`;
+      if (dayTemp < 10) {
+        day = `0${dayTemp}`;
+      }
+      if (step === 'DAY') {
+        return `${year}-${month}-${day}`;
+      }
+      const hourTemp = date.getHours();
+      let hour: string = `${hourTemp}`;
+      if (hourTemp < 10) {
+        hour = `0${hourTemp}`;
+      }
+      if (step === 'HOUR') {
+        return `${year}-${month}-${day} ${hour}`;
+      }
+      const minuteTemp = date.getMinutes();
+      let minute: string = `${minuteTemp}`;
+      if (minuteTemp < 10) {
+        minute = `0${minuteTemp}`;
+      }
+      if (step === 'MINUTE') {
+        return `${year}-${month}-${day} ${hour}${minute}`;
+      }
     }
-    const dayTemp = date.getDate();
-    let day: string = `${dayTemp}`;
-    if (dayTemp < 10) { day = `0${dayTemp}`; }
-    if (step === 'DAY') { return `${year}-${month}-${day}`; }
-    const hourTemp = date.getHours();
-    let hour: string = `${hourTemp}`;
-    if (hourTemp < 10) { hour = `0${hourTemp}`; }
-    if (step === 'HOUR') { return `${year}-${month}-${day} ${hour}`; }
-    const minuteTemp = date.getMinutes();
-    let minute: string = `${minuteTemp}`;
-    if (minuteTemp < 10) { minute = `0${minuteTemp}`; }
-    if (step === 'MINUTE') { return `${year}-${month}-${day} ${hour}${minute}`; }
-  }
-  private globalTimeFormate = (time: Date[]): any => {
-    let step = 'MINUTE';
-    const unix = Math.round(time[1].getTime()) - Math.round(time[0].getTime());
-    if (unix <= 60 * 60 * 1000) {
-      step = 'MINUTE';
-    } else if (unix <= 24 * 60 * 60 * 1000) {
-      step = 'HOUR';
-    } else if (unix <= 30 * 24 * 60 * 60 * 1000) {
-      step = 'DAY';
-    } else {
-      step = 'MONTH';
+    private globalTimeFormat = (time: Date[]): any => {
+      let step = 'MINUTE';
+      const unix = Math.round(time[1].getTime()) - Math.round(time[0].getTime());
+      if (unix <= 60 * 60 * 1000) {
+        step = 'MINUTE';
+      } else if (unix <= 24 * 60 * 60 * 1000) {
+        step = 'HOUR';
+      } else if (unix <= 30 * 24 * 60 * 60 * 1000) {
+        step = 'DAY';
+      } else {
+        step = 'MONTH';
+      }
+      return {start: this.dateFormat(time[0], step), end: this.dateFormat(time[1], step), step};
     }
-    return { start: this.dateFormate(time[0], step), end: this.dateFormate(time[1], step), step };
-  }
-  private chooseService(i: any) {
-    if (this.service.key === i.key) {
-      return;
+
+    private chooseService(i: any) {
+      if (this.service.key === i.key) {
+        return;
+      }
+      this.instance = {label: 'All', key: ''};
+      this.service = i;
+      if (i.key === '') {
+        return;
+      }
+      this.GET_INSTANCES({duration: this.durationTime, serviceId: i.key});
     }
-    this.instance = {label: 'All', key: ''};
-    this.service = i;
-    if (i.key === '') {
-      return;
+
+    private chooseStatus(i: any) {
+      this.traceState = i;
     }
-    this.GET_INSTANCES({duration: this.durationTime, serviceId: i.key});
-  }
-  private chooseStatus(i: any) {
-    this.traceState = i;
-  }
-  private getTraceList() {
-    this.GET_SERVICES({duration: this.durationTime});
-    const temp: any = {
-        queryDuration: this.globalTimeFormate([
+
+    private getTraceList() {
+      this.GET_SERVICES({duration: this.durationTime});
+      const temp: any = {
+        queryDuration: this.globalTimeFormat([
           new Date(this.time[0].getTime() +
-          (parseInt(this.rocketbotGlobal.utc, 10) + new Date().getTimezoneOffset() / 60) * 3600000),
+            (parseInt(this.rocketbotGlobal.utc, 10) + new Date().getTimezoneOffset() / 60) * 3600000),
           new Date(this.time[1].getTime() +
-          (parseInt(this.rocketbotGlobal.utc, 10) + new Date().getTimezoneOffset() / 60) * 3600000),
+            (parseInt(this.rocketbotGlobal.utc, 10) + new Date().getTimezoneOffset() / 60) * 3600000),
         ]),
-        traceState:  this.traceState.key,
+        traceState: this.traceState.key,
         paging: {pageNum: 1, pageSize: 15, needTotal: true},
         queryOrder: this.rocketTrace.traceForm.queryOrder,
-    };
-    if (this.service.key) { temp.serviceId = this.service.key; }
-    if (this.instance.key) { temp.serviceInstanceId = this.instance.key; }
-    if (this.maxTraceDuration) { temp.maxTraceDuration = this.maxTraceDuration; }
-    if (this.minTraceDuration) { temp.minTraceDuration = this.minTraceDuration; }
-    if (this.endpointName) { temp.endpointName = this.endpointName; }
-    if (this.traceId) { temp.traceId = this.traceId; }
-    this.SET_TRACE_FORM(temp);
-    this.eventHub.$emit('SET_LOADING_TRUE', () => {
-      this.GET_TRACELIST().then(() => {
-        this.eventHub.$emit('SET_LOADING_FALSE');
+      };
+      if (this.service.key) {
+        temp.serviceId = this.service.key;
+      }
+      if (this.instance.key) {
+        temp.serviceInstanceId = this.instance.key;
+      }
+      if (this.maxTraceDuration) {
+        temp.maxTraceDuration = this.maxTraceDuration;
+        localStorage.setItem('maxTraceDuration', this.maxTraceDuration);
+      }
+      if (this.minTraceDuration) {
+        temp.minTraceDuration = this.minTraceDuration;
+        localStorage.setItem('minTraceDuration', this.minTraceDuration);
+      }
+      if (this.endpointName) {
+        temp.endpointName = this.endpointName;
+        localStorage.setItem('endpointName', this.endpointName);
+      }
+      if (this.traceId) {
+        temp.traceId = this.traceId;
+        localStorage.setItem('traceId', this.traceId);
+      }
+      this.SET_TRACE_FORM(temp);
+      this.eventHub.$emit('SET_LOADING_TRUE', () => {
+        this.GET_TRACELIST().then(() => {
+          this.eventHub.$emit('SET_LOADING_FALSE');
+        });
       });
-    });
-  }
-  private mounted() {
-    this.time = [this.rocketbotGlobal.durationRow.start, this.rocketbotGlobal.durationRow.end];
-    this.getTraceList();
+    }
+
+    private clearSearch() {
+      this.RESET_DURATION();
+      this.status = true;
+      this.maxTraceDuration = '';
+      localStorage.removeItem('maxTraceDuration');
+      this.minTraceDuration = '';
+      localStorage.removeItem('minTraceDuration');
+      this.service = {label: 'All', key: ''};
+      this.instance = {label: 'All', key: ''};
+      this.endpointName = '';
+      localStorage.removeItem('endpointName');
+      this.traceId = '';
+      localStorage.removeItem('traceId');
+      this.traceState = {label: 'All', key: 'ALL'};
+      this.SET_TRACE_FORM_ITEM({type: 'queryOrder', data: ''});
+      this.getTraceList();
+    }
+
+    @Watch('rocketbotGlobal.durationRow')
+    private durationRowWatch(value: Duration) {
+      this.time = [value.start, value.end];
+    }
+
+    private created() {
+      this.time = [this.rocketbotGlobal.durationRow.start, this.rocketbotGlobal.durationRow.end];
+    }
+
+    private mounted() {
+      this.getTraceList();
+    }
   }
-}
 </script>
 
 <style lang="scss">
-.rk-trace-search {
-  flex-shrink: 0;
-  background-color: #333840;
-  color: #eee;
-  width: 100%;
-  padding: 3px 15px 8px;
-}
-
-.rk-trace-search-input {
-  border-style: unset;
-  outline: 0;
-  padding: 2px 5px;
-  border-radius: 3px;
-}
-.rk-trace-search-range{
-  border-radius: 3px;
-  background-color: #fff;
-  padding: 1px;
-  border-radius: 3px;
-  input{
-    width: 38px;
+  .rk-trace-search {
+    flex-shrink: 0;
+    background-color: #333840;
+    color: #eee;
+    width: 100%;
+    padding: 3px 15px 8px;
+  }
+
+  .rk-trace-search-input {
     border-style: unset;
     outline: 0;
+    padding: 2px 5px;
+    border-radius: 3px;
+  }
+
+  .rk-trace-search-range {
+    border-radius: 3px;
+    background-color: #fff;
+    padding: 1px;
+    border-radius: 3px;
+
+    input {
+      width: 38px;
+      border-style: unset;
+      outline: 0;
+    }
   }
-}
-.rk-trace-search-btn{
-  padding: 3px 9px;
-  background-color: #484b55;
-  border-radius: 4px;
-  margin-top: 12px;
-  &.bg-blue{
-    background-color: #448dfe;
+
+  .rk-trace-search-btn {
+    padding: 3px 9px;
+    background-color: #484b55;
+    border-radius: 4px;
+    margin-top: 12px;
+
+    &.bg-blue {
+      background-color: #448dfe;
+    }
+  }
+
+  .rk-trace-clear-btn {
+    padding: 3px 9px;
+    background-color: #484b55;
+    border-radius: 4px;
+    margin-top: 12px;
+
+    &.bg-warning {
+      background-color: #FBB03B;
+    }
   }
-}
-.rk-trace-search-more{
-  background-color: #484b55;
-  padding: 4px 10px;
-  border-radius: 3px;
-  margin-top: 8px;
-  position: relative;
-  box-shadow: 0 1px 2px 0 rgba(0,0,0,.1);
-  &:after {
-    bottom: 100%;
-    right: 30px;
-    border: solid transparent;
-    content: " ";
-    height: 0;
-    width: 0;
-    position: absolute;
-    pointer-events: none;
-    border-color: rgba(0, 0,0, 0);
-    border-bottom-color: #484b55;
-    border-width: 8px;
-    margin-right: 0px;
+
+  .rk-trace-search-more {
+    background-color: #484b55;
+    padding: 4px 10px;
+    border-radius: 3px;
+    margin-top: 8px;
+    position: relative;
+    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .1);
+
+    &:after {
+      bottom: 100%;
+      right: 30px;
+      border: solid transparent;
+      content: " ";
+      height: 0;
+      width: 0;
+      position: absolute;
+      pointer-events: none;
+      border-color: rgba(0, 0, 0, 0);
+      border-bottom-color: #484b55;
+      border-width: 8px;
+      margin-right: 0px;
+    }
   }
-}
 </style>