Skip to content

Commit 377bb78

Browse files
committed
v0.0.8 History trender
1 parent ea5536e commit 377bb78

File tree

18 files changed

+351
-61
lines changed

18 files changed

+351
-61
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@
2222
npm run build:prod
2323
```
2424

25+
## DEBUG
26+
27+
+ 在控制台下可以开启日志
28+
29+
```JavaScript
30+
window.timer.openLog()
31+
```
32+
33+
+ 关闭日志
34+
35+
```JavaScript
36+
window.timer.closeLog()
37+
```
38+
2539
## 下载地址
2640

2741
[Firefox](https://addons.mozilla.org/zh-CN/firefox/addon/make-zero/) [Chrome](https://chrome.google.com/webstore/detail/make-zero-%E6%96%87%E5%AD%97%E5%8A%A0%E5%AF%86%E5%99%A8/ihpcojcdiclghnggnlkcinbmfpomefcc?hl=zh-CN) [Edge](https://microsoftedge.microsoft.com/addons/detail/make-zero-decenc-your-/gkjmpdoddilgcfoeokeajfecogaaocol)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "timer",
3-
"version": "0.0.7",
3+
"version": "0.0.8",
44
"description": "Web timer",
55
"main": "index.js",
66
"scripts": {
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div class="filter-container">
44
<el-input class="filter-item"
55
v-model="host"
6-
:placeholder="$t('record.hostPlaceholder')"
6+
:placeholder="$t('report.hostPlaceholder')"
77
clearable
88
@keyup.enter.native="queryData">
99
</el-input>
@@ -13,17 +13,17 @@
1313
format="yyyy/MM/dd"
1414
range-separator="-"
1515
:picker-options="pickerOptions"
16-
:start-placeholder="$t('record.startDate')"
17-
:end-placeholder="$t('record.endDate')">
16+
:start-placeholder="$t('report.startDate')"
17+
:end-placeholder="$t('report.endDate')">
1818
</el-date-picker>
1919
</span>
20-
<a class="filter-name">{{ $t('record.mergeDate') }}</a>
20+
<a class="filter-name">{{ $t('report.mergeDate') }}</a>
2121
<el-switch class="filter-item"
2222
v-model="mergeDate" />
23-
<a class="filter-name">{{ $t('record.mergeDomain') }}</a>
23+
<a class="filter-name">{{ $t('report.mergeDomain') }}</a>
2424
<el-switch class="filter-item"
2525
v-model="mergeDomain" />
26-
<a class="filter-name">{{ $t('record.displayBySecond') }}</a>
26+
<a class="filter-name">{{ $t('report.displayBySecond') }}</a>
2727
<el-switch class="filter-item"
2828
v-model="displayBySecond" />
2929
<el-dropdown class="export-dropdown"
@@ -138,6 +138,7 @@ import whitelistService from '../../../service/whitelist-service'
138138
import { FAVICON } from '../../../util/constant'
139139
import { formatPeriodCommon, formatTime } from '../../../util/time'
140140
import { exportCsv, exportJson } from '../../../util/file'
141+
import { MILL_PER_DAY } from '../../../util/time'
141142
const ELEMENT_SORT_2_DB = {
142143
descending: QueryParam.DESC,
143144
ascending: QueryParam.ASC
@@ -147,13 +148,12 @@ export default {
147148
name: 'Dashboard',
148149
data () {
149150
const daysAgo = (start, end) => {
150-
const timePerDay = 3600 * 1000 * 24
151151
const current = new Date().getTime()
152-
return [current - start * timePerDay, current - end * timePerDay]
152+
return [current - start * MILL_PER_DAY, current - end * MILL_PER_DAY]
153153
}
154154
const datePickerShortcut = (msg, agoOfStart, agoOfEnd) => {
155155
return {
156-
text: this.$t(`record.${msg}`),
156+
text: this.$t(`report.${msg}`),
157157
onClick: picker => picker.$emit('pick', daysAgo(agoOfStart || 0, agoOfEnd || 0))
158158
}
159159
}
@@ -326,7 +326,7 @@ export default {
326326
}
327327
},
328328
exportFileName () {
329-
let baseName = this.$t('record.exportFileName')
329+
let baseName = this.$t('report.exportFileName')
330330
if (this.dateRange && this.dateRange.length === 2) {
331331
const start = this.dateRange[0]
332332
const end = this.dateRange[1]
@@ -336,9 +336,9 @@ export default {
336336
baseName += '_' + formatTime(start, '{y}{m}{d}') + '_' + formatTime(end, '{y}{m}{d}')
337337
}
338338
}
339-
this.mergeDate && (baseName += '_' + this.$t('record.mergeDate'))
340-
this.mergeDomain && (baseName += '_' + this.$t('record.mergeDomain'))
341-
this.displayBySecond && (baseName += '_' + this.$t('record.displayBySecond'))
339+
this.mergeDate && (baseName += '_' + this.$t('report.mergeDate'))
340+
this.mergeDomain && (baseName += '_' + this.$t('report.mergeDomain'))
341+
this.displayBySecond && (baseName += '_' + this.$t('report.displayBySecond'))
342342
return baseName
343343
}
344344
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<template>
2+
<el-card style="margin-top:25px;">
3+
<div style="width:100%;height:600px;"
4+
ref="chart" />
5+
</el-card>
6+
</template>
7+
<script>
8+
import { init } from 'echarts'
9+
import timerDatabase, { QueryParam, Row } from '../../../../database/timer-database'
10+
import { formatPeriodCommon, formatTime, MILL_PER_DAY } from '../../../../util/time'
11+
12+
// Get the timestamp of one timestamp of date
13+
const timestampOf = d => d.getTime ? d.getTime() : d
14+
15+
const mill2Second = mill => Math.floor((mill || 0) / 1000)
16+
17+
18+
export default {
19+
name: 'DomainTrender',
20+
props: {
21+
domain: {
22+
type: String
23+
},
24+
dateRange: {
25+
type: Array
26+
},
27+
field: {
28+
type: 'focus' | 'total' | 'time'
29+
}
30+
},
31+
data () {
32+
const formatTimeOfEchart = ({ seriesName, name, value }) => `${seriesName}<br/>${name}&ensp;-&ensp;${formatPeriodCommon(value * 1000)}`
33+
34+
return {
35+
rows: [],
36+
chart: undefined,
37+
option: {
38+
backgroundColor: 'rgba(0,0,0,0)',
39+
grid: { top: '100' },
40+
title: {
41+
text: this.$t('trender.history.title'),
42+
subtext: '',
43+
left: 'center',
44+
align: ''
45+
},
46+
tooltip: {
47+
trigger: 'item'
48+
},
49+
toolbox: {
50+
feature: {
51+
saveAsImage: {}
52+
}
53+
},
54+
xAxis: {
55+
type: 'category',
56+
data: []
57+
},
58+
yAxis: [
59+
{ name: this.$t('trender.history.timeUnit'), type: 'value' },
60+
{ name: this.$t('trender.history.numberUnit'), type: 'value' }
61+
],
62+
legend: {
63+
left: 'left',
64+
data: [this.$t('item.total'), this.$t('item.focus'), this.$t('item.time')]
65+
},
66+
series: [
67+
// run time
68+
{
69+
name: this.$t('item.total'),
70+
data: [],
71+
yAxisIndex: 0,
72+
type: 'line',
73+
smooth: true,
74+
tooltip: { formatter: formatTimeOfEchart }
75+
},
76+
{
77+
name: this.$t('item.focus'),
78+
data: [],
79+
yAxisIndex: 0,
80+
type: 'line',
81+
smooth: true,
82+
tooltip: { formatter: formatTimeOfEchart }
83+
},
84+
{
85+
name: this.$t('item.time'),
86+
data: [],
87+
yAxisIndex: 1,
88+
type: 'line',
89+
smooth: true,
90+
tooltip: {
91+
formatter: ({ seriesName, name, value }) => `${seriesName}<br/>${name}&emsp;-&emsp;${value}`
92+
}
93+
}
94+
]
95+
}
96+
}
97+
},
98+
mounted () {
99+
this.chart = init(this.$refs.chart)
100+
this.updateXAxis()
101+
this.renderChart()
102+
},
103+
methods: {
104+
queryData () {
105+
if (this.domain === '') {
106+
// Do nothing
107+
return
108+
}
109+
timerDatabase.select(rows => {
110+
const dateInfoMap = {}
111+
rows.forEach(row => dateInfoMap[row.date] = row)
112+
const allXAxis = this.getAxias('{y}{m}{d}')
113+
114+
const focusData = []
115+
const totalData = []
116+
const timeData = []
117+
118+
allXAxis.forEach(date => {
119+
const row = dateInfoMap[date] || new Row()
120+
focusData.push(mill2Second(row.focus))
121+
totalData.push(mill2Second(row.total))
122+
timeData.push(row.time || 0)
123+
})
124+
125+
this.option.title.subtext = this.domain
126+
this.option.series[0].data = totalData
127+
this.option.series[1].data = focusData
128+
this.option.series[2].data = timeData
129+
this.renderChart()
130+
}, this.queryParam)
131+
},
132+
renderChart () {
133+
this.chart && this.chart.setOption(this.option)
134+
},
135+
/**
136+
* Get the x-axis of date
137+
*/
138+
getAxias (format) {
139+
const xAxisData = []
140+
const startTime = timestampOf(this.dateRange[0])
141+
const endTime = timestampOf(this.dateRange[1])
142+
for (let time = startTime; time <= endTime; time += MILL_PER_DAY) {
143+
xAxisData.push(formatTime(time, format))
144+
}
145+
return xAxisData
146+
},
147+
/**
148+
* Update the x-axis
149+
*/
150+
updateXAxis () {
151+
if (!this.dateRange || this.dateRange.length !== 2) {
152+
this.option.xAxis.data = []
153+
}
154+
this.option.xAxis.data = this.getAxias('{m}/{d}')
155+
}
156+
},
157+
computed: {
158+
queryParam () {
159+
return {
160+
host: this.domain,
161+
fullHost: true,
162+
sort: 'date',
163+
sortOrder: QueryParam.ASC
164+
}
165+
}
166+
},
167+
watch: {
168+
domain () {
169+
this.queryData()
170+
},
171+
dateRange () {
172+
this.updateXAxis()
173+
this.queryData()
174+
}
175+
}
176+
}
177+
</script>

src/app/components/Trender/index.vue

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<template>
22
<div class="content-container">
33
<div class="filter-container">
4-
<el-select placeholder="ceshi"
4+
<el-select :placeholder="$t('trender.hostPlaceholder')"
5+
class="filter-item"
56
v-model="trenderDomain"
6-
multiple
7+
clearable
78
filterable
89
remote
910
:remote-method="queryDomainHandler"
@@ -13,18 +14,56 @@
1314
:label="option"
1415
:value="option" />
1516
</el-select>
17+
<span class="filter-item">
18+
<el-date-picker v-model="dateRange"
19+
type="daterange"
20+
format="yyyy/MM/dd"
21+
range-separator="-"
22+
:picker-options="pickerOptions"
23+
:start-placeholder="$t('trender.startDate')"
24+
:end-placeholder="$t('trender.endDate')"
25+
unlink-panels>
26+
</el-date-picker>
27+
</span>
28+
<domain-trender :date-range="dateRange"
29+
:domain="trenderDomain"
30+
:field="trenderField" />
1631
</div>
1732
</div>
1833
</template>
1934
<script>
2035
import timerService from '../../../service/timer-service'
36+
import DomainTrender from './components/DomainTrender'
37+
import { MILL_PER_DAY } from '../../../util/time'
2138
export default {
2239
name: 'Trender',
40+
components: { DomainTrender },
2341
data () {
42+
const daysAgo = (start, end) => {
43+
const current = new Date().getTime()
44+
return [current - start * MILL_PER_DAY, current - end * MILL_PER_DAY]
45+
}
46+
const datePickerShortcut = (msg, agoOfStart, agoOfEnd) => {
47+
return {
48+
text: this.$t(`trender.${msg}`),
49+
onClick: picker => picker.$emit('pick', daysAgo(agoOfStart || 0, (agoOfEnd || 0) + 1))
50+
}
51+
}
2452
return {
2553
trenderDomain: '',
2654
trenderSearching: false,
27-
trenderDomainOptions: []
55+
trenderDomainOptions: [],
56+
trenderField: 'focus',
57+
dateRange: daysAgo(15, 1),
58+
pickerOptions: {
59+
disabledDate: date => date.getTime() > new Date().getTime() - MILL_PER_DAY,
60+
shortcuts: [
61+
datePickerShortcut('latestWeek', 7),
62+
datePickerShortcut('latest15Days', 15),
63+
datePickerShortcut('latest30Days', 30),
64+
datePickerShortcut('latest90Days', 90)
65+
]
66+
}
2867
}
2968
},
3069
methods: {

src/app/element.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Vue from 'vue'
22
import {
33
Alert, Aside,
44
Button,
5-
Container,
5+
Card, Container,
66
DatePicker, Dropdown, DropdownMenu, DropdownItem,
77
Icon, Input,
88
Main, Menu, MenuItem, Message, MessageBox,
@@ -21,6 +21,8 @@ import 'element-ui/lib/theme-chalk/aside.css'
2121
Vue.use(Button)
2222
import 'element-ui/lib/theme-chalk/button.css'
2323

24+
Vue.use(Card)
25+
import 'element-ui/lib/theme-chalk/card.css'
2426
Vue.use(Container)
2527
import 'element-ui/lib/theme-chalk/container.css'
2628

0 commit comments

Comments
 (0)