Skip to content

Commit 6d54bb8

Browse files
committed
Clean code and convert into TSX
1 parent ea408f5 commit 6d54bb8

File tree

103 files changed

+1850
-2142
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1850
-2142
lines changed

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@
99
"Auths",
1010
"clipboardy",
1111
"countup",
12+
"daterange",
1213
"echarts",
1314
"filemanager",
1415
"Hengyang",
1516
"Kanban",
17+
"Popconfirm",
18+
"vueuse",
19+
"webtime",
1620
"zrender"
1721
],
1822
"cSpell.ignorePaths": [

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
},
5959
"dependencies": {
6060
"@element-plus/icons-vue": "^2.3.1",
61+
"@vueuse/core": "^10.7.2",
6162
"axios": "^1.6.5",
6263
"clipboardy": "^4.0.0",
6364
"countup.js": "^2.8.0",
@@ -71,4 +72,4 @@
7172
"engines": {
7273
"node": ">=18"
7374
}
74-
}
75+
}

src/app/components/analysis/components/filter.ts renamed to src/app/components/Analysis/components/AnalysisFilter.tsx

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/**
22
* Copyright (c) 2021 Hengyang Zhang
3-
*
3+
*
44
* This software is released under the MIT License.
55
* https://opensource.org/licenses/MIT
66
*/
77

8-
import type { Ref, PropType, VNode } from "vue"
8+
import type { Ref, PropType } from "vue"
99

1010
import { ElOption, ElSelect, ElTag } from "element-plus"
11-
import { ref, h, defineComponent } from "vue"
11+
import { ref, defineComponent } from "vue"
1212
import statService, { HostSet } from "@service/stat-service"
1313
import siteService from "@service/site-service"
1414
import { t } from "@app/locale"
@@ -45,15 +45,15 @@ async function handleRemoteSearch(queryStr: string, trendDomainOptions: Ref<time
4545

4646
const HOST_PLACEHOLDER = t(msg => msg.analysis.common.hostPlaceholder)
4747

48-
function keyOfHostInfo(option: timer.site.SiteKey): string {
48+
function calcKey(option: timer.site.SiteKey): string {
4949
const { merged, virtual, host } = option
5050
let prefix = '_'
5151
merged && (prefix = 'm')
5252
virtual && (prefix = 'v')
5353
return `${prefix}${host || ''}`
5454
}
5555

56-
function hostInfoOfKey(key: string): timer.site.SiteKey {
56+
function calcSite(key: string): timer.site.SiteKey {
5757
if (!key?.length) return undefined
5858
const prefix = key.charAt(0)
5959
return { host: key.substring(1), merged: prefix === 'm', virtual: prefix === 'v' }
@@ -62,22 +62,18 @@ function hostInfoOfKey(key: string): timer.site.SiteKey {
6262
const MERGED_TAG_TXT = t(msg => msg.analysis.common.merged)
6363
const VIRTUAL_TAG_TXT = t(msg => msg.analysis.common.virtual)
6464

65-
const renderOptionTag = (tagLabel: string) => h('span',
66-
{ style: { float: "right", height: "34px" } },
67-
h(ElTag, { size: 'small' }, () => tagLabel)
68-
)
69-
70-
function renderHostLabel({ host, merged, virtual, alias }: timer.site.SiteInfo): VNode[] {
71-
const result = [
72-
h('span', {}, host)
73-
]
74-
alias && result.push(
75-
h(ElTag, { size: 'small', type: 'info' }, () => alias)
76-
)
77-
merged && result.push(renderOptionTag(MERGED_TAG_TXT))
78-
virtual && result.push(renderOptionTag(VIRTUAL_TAG_TXT))
79-
return result
80-
}
65+
const SiteOptionTag = defineComponent({
66+
props: {
67+
text: String,
68+
},
69+
setup: ({ text }) => {
70+
return () => (
71+
<span style={{ float: "right", height: "34px" }}>
72+
<ElTag size="small">{text}</ElTag>
73+
</span>
74+
)
75+
}
76+
})
8177

8278
const _default = defineComponent({
8379
props: {
@@ -91,48 +87,58 @@ const _default = defineComponent({
9187
setup(props, ctx) {
9288
const domainKey: Ref<string> = ref('')
9389
const trendSearching: Ref<boolean> = ref(false)
94-
const trendDomainOptions: Ref<timer.site.SiteKey[]> = ref([])
90+
const trendDomainOptions: Ref<timer.site.SiteInfo[]> = ref([])
9591
const defaultSite: timer.site.SiteKey = props.site
9692
const timeFormat: Ref<timer.app.TimeFormat> = ref(props.timeFormat)
93+
9794
if (defaultSite) {
98-
domainKey.value = keyOfHostInfo(defaultSite)
95+
domainKey.value = calcKey(defaultSite)
9996
trendDomainOptions.value.push(defaultSite)
10097
}
10198

102-
function handleSiteChange() {
103-
const siteInfo: timer.site.SiteInfo = hostInfoOfKey(domainKey.value)
99+
const handleSiteChange = () => {
100+
const siteInfo: timer.site.SiteInfo = calcSite(domainKey.value)
104101
ctx.emit('siteChange', siteInfo)
105102
}
106103

107-
return () => [
108-
h(ElSelect, {
109-
placeholder: HOST_PLACEHOLDER,
110-
class: 'filter-item',
111-
modelValue: domainKey.value,
112-
filterable: true,
113-
remote: true,
114-
loading: trendSearching.value,
115-
clearable: true,
116-
remoteMethod: (query: string) => handleRemoteSearch(query, trendDomainOptions, trendSearching),
117-
onChange: (key: string) => {
104+
return () => <>
105+
<ElSelect
106+
placeholder={HOST_PLACEHOLDER}
107+
class="filter-item"
108+
modelValue={domainKey.value}
109+
filterable
110+
remote
111+
loading={trendSearching.value}
112+
clearable
113+
remoteMethod={(query: string) => handleRemoteSearch(query, trendDomainOptions, trendSearching)}
114+
onChange={(key: string) => {
118115
domainKey.value = key
119116
handleSiteChange()
120-
},
121-
onClear: () => {
117+
}}
118+
onClear={() => {
122119
domainKey.value = undefined
123120
handleSiteChange()
124-
}
125-
}, () => (trendDomainOptions.value || [])?.map(
126-
siteInfo => h(ElOption, {
127-
value: keyOfHostInfo(siteInfo),
128-
label: labelOfHostInfo(siteInfo),
129-
}, () => renderHostLabel(siteInfo))
130-
)),
131-
h(TimeFormatFilterItem, {
132-
defaultValue: timeFormat.value,
133-
onSelect: (newVal: timer.app.TimeFormat) => ctx.emit('timeFormatChange', timeFormat.value = newVal)
134-
})
135-
]
121+
}}
122+
>
123+
{(trendDomainOptions.value || [])?.map(
124+
site => (
125+
<ElOption
126+
value={calcKey(site)}
127+
label={labelOfHostInfo(site)}
128+
>
129+
<span>{site.host}</span>
130+
{site.alias && <ElTag size="small" type="info">{site.alias}</ElTag>}
131+
{site.merged && <SiteOptionTag text={MERGED_TAG_TXT} />}
132+
{site.virtual && <SiteOptionTag text={VIRTUAL_TAG_TXT} />}
133+
</ElOption>
134+
)
135+
)}
136+
</ElSelect>
137+
<TimeFormatFilterItem
138+
defaultValue={timeFormat.value}
139+
onChange={val => ctx.emit("timeFormatChange", timeFormat.value = val)}
140+
/>
141+
</>
136142
}
137143
})
138144

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Copyright (c) 2023 Hengyang Zhang
3+
*
4+
* This software is released under the MIT License.
5+
* https://opensource.org/licenses/MIT
6+
*/
7+
8+
import { Ref, defineComponent } from "vue"
9+
import { computedAsync } from "@vueuse/core"
10+
import { labelOfHostInfo } from "../../util"
11+
import { t } from "@app/locale"
12+
import { useAnalysisSite } from "../../context"
13+
import siteService from "@service/site-service"
14+
15+
const EMPTY_DESC = t(msg => msg.analysis.common.emptyDesc)
16+
17+
function renderChildren(site: timer.site.SiteInfo) {
18+
if (!site) return <h1 class="site-alias">{EMPTY_DESC}</h1>
19+
20+
const { iconUrl, alias } = site
21+
const label = labelOfHostInfo(site)
22+
const title: string = alias ? alias : label
23+
const subtitle: string = alias ? label : undefined
24+
return <>
25+
{iconUrl && <img src={iconUrl} width={24} height={24} />}
26+
<h1 class="site-alias">{title}</h1>
27+
{subtitle && <p class="site-host">{subtitle}</p>}
28+
</>
29+
}
30+
31+
const computedSiteInfo = async (siteKey: timer.site.SiteKey): Promise<timer.site.SiteInfo> => {
32+
if (!siteKey) return undefined
33+
return await siteService.get(siteKey)
34+
}
35+
36+
const _default = defineComponent(() => {
37+
const site = useAnalysisSite()
38+
const siteInfo: Ref<timer.site.SiteInfo> = computedAsync(() => computedSiteInfo(site.value))
39+
return () => (
40+
<div class="site-container">
41+
{renderChildren(siteInfo.value)}
42+
</div>
43+
)
44+
})
45+
46+
export default _default
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Copyright (c) 2023 Hengyang Zhang
3+
*
4+
* This software is released under the MIT License.
5+
* https://opensource.org/licenses/MIT
6+
*/
7+
import type { Ref } from "vue"
8+
9+
import { computed, defineComponent } from "vue"
10+
import Site from "./Site"
11+
import { KanbanIndicatorCell, KanbanCard, KanbanIndicatorRow } from "@app/components/common/kanban"
12+
import "./summary.sass"
13+
import { ElCol } from "element-plus"
14+
import { t } from "@app/locale"
15+
import { cvt2LocaleTime, periodFormatter } from "@app/util/time"
16+
import { useAnalysisRows, useAnalysisSite, useAnalysisTimeFormat } from "../../context"
17+
18+
type Summary = {
19+
focus: number
20+
visit: number
21+
day: number
22+
firstDay?: string
23+
}
24+
25+
function computeSummary(site: timer.site.SiteKey, rows: timer.stat.Row[]): Summary {
26+
if (!site) return undefined
27+
28+
const summary: Summary = { focus: 0, visit: 0, day: 0 }
29+
summary.firstDay = rows?.[0]?.date
30+
rows?.forEach(({ focus, time: visit }) => {
31+
summary.focus += focus
32+
summary.visit += visit
33+
focus && (summary.day += 1)
34+
})
35+
return summary
36+
}
37+
38+
const DAYS_LABEL = t(msg => msg.analysis.summary.day)
39+
const FOCUS_LABEL = t(msg => msg.analysis.common.focusTotal)
40+
const VISIT_LABEL = t(msg => msg.analysis.common.visitTotal)
41+
42+
const _default = defineComponent(() => {
43+
const site = useAnalysisSite()
44+
const timeFormat = useAnalysisTimeFormat()
45+
const rows = useAnalysisRows()
46+
47+
const summary: Ref<Summary> = computed(() => computeSummary(site.value, rows.value))
48+
49+
return () => (
50+
<KanbanCard title={t(msg => msg.analysis.summary.title)}>
51+
<KanbanIndicatorRow>
52+
<ElCol span={6}>
53+
<Site />
54+
</ElCol>
55+
<ElCol span={6}>
56+
<KanbanIndicatorCell
57+
mainName={DAYS_LABEL}
58+
mainValue={summary.value?.day?.toString?.() || '-'}
59+
subTips={msg => msg.analysis.summary.firstDay}
60+
subValue={summary.value?.firstDay ? `@${cvt2LocaleTime(summary.value?.firstDay)}` : ''}
61+
/>
62+
</ElCol>
63+
<ElCol span={6}>
64+
<KanbanIndicatorCell
65+
mainName={FOCUS_LABEL}
66+
mainValue={summary.value?.focus === undefined ? '-' : periodFormatter(summary.value?.focus, timeFormat.value, false)}
67+
/>
68+
</ElCol>
69+
<ElCol span={6}>
70+
<KanbanIndicatorCell mainName={VISIT_LABEL} mainValue={summary.value?.visit?.toString?.() || '-'} />
71+
</ElCol>
72+
</KanbanIndicatorRow>
73+
</KanbanCard>
74+
)
75+
})
76+
77+
export default _default

src/app/components/analysis/components/summary/summary.sass renamed to src/app/components/Analysis/components/Summary/summary.sass

File renamed without changes.

src/app/components/analysis/components/trend/dimension/chart.ts renamed to src/app/components/Analysis/components/Trend/Dimension/Chart.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
*/
77

88
import type { PropType, Ref } from "vue"
9-
import type { DimensionEntry, ValueFormatter } from "@app/components/analysis/util"
9+
import type { DimensionEntry, ValueFormatter } from "@app/components/Analysis/util"
1010

11-
import { defineComponent, h, watch, onMounted, ref } from "vue"
11+
import { defineComponent, watch, onMounted, ref } from "vue"
1212
import ChartWrapper from "./wrapper"
1313

1414
const _default = defineComponent({
@@ -20,7 +20,12 @@ const _default = defineComponent({
2020
setup(props) {
2121
const elRef: Ref<HTMLDivElement> = ref()
2222
const wrapper: ChartWrapper = new ChartWrapper()
23-
const render = () => wrapper.render({ entries: props.data, title: props.title, valueFormatter: props.valueFormatter })
23+
24+
const render = () => wrapper.render({
25+
entries: props.data,
26+
title: props.title,
27+
valueFormatter: props.valueFormatter,
28+
})
2429

2530
watch(() => props.data, render)
2631
watch(() => props.valueFormatter, render)
@@ -30,7 +35,7 @@ const _default = defineComponent({
3035
render()
3136
})
3237

33-
return () => h('div', { class: 'analysis-trend-dimension-chart', ref: elRef })
38+
return () => <div class="analysis-trend-dimension-chart" ref={elRef} />
3439
}
3540
})
3641

0 commit comments

Comments
 (0)