Implement #2961
This commit is contained in:
		
							parent
							
								
									172a0a85aa
								
							
						
					
					
						commit
						1af4f94338
					
				
					 2 changed files with 106 additions and 1 deletions
				
			
		|  | @ -4,7 +4,10 @@ | ||||||
| 		%fa:hashtag%<span>{{ tag }}</span> | 		%fa:hashtag%<span>{{ tag }}</span> | ||||||
| 	</span> | 	</span> | ||||||
| 
 | 
 | ||||||
| 	<x-hashtag-tl :tag-tl="tagTl"/> | 	<div class="xroyrflcmhhtmlwmyiwpfqiirqokfueb"> | ||||||
|  | 		<div ref="chart" class="chart"></div> | ||||||
|  | 		<x-hashtag-tl :tag-tl="tagTl" class="tl"/> | ||||||
|  | 	</div> | ||||||
| </x-column> | </x-column> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
|  | @ -12,6 +15,8 @@ | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import XColumn from './deck.column.vue'; | import XColumn from './deck.column.vue'; | ||||||
| import XHashtagTl from './deck.hashtag-tl.vue'; | import XHashtagTl from './deck.hashtag-tl.vue'; | ||||||
|  | import * as G2 from '@antv/g2'; | ||||||
|  | import * as tinycolor from 'tinycolor2'; | ||||||
| 
 | 
 | ||||||
| export default Vue.extend({ | export default Vue.extend({ | ||||||
| 	components: { | 	components: { | ||||||
|  | @ -32,6 +37,67 @@ export default Vue.extend({ | ||||||
| 				query: [[this.tag]] | 				query: [[this.tag]] | ||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	mounted() { | ||||||
|  | 		(this as any).api('charts/hashtag', { | ||||||
|  | 			tag: this.tag, | ||||||
|  | 			span: 'hour', | ||||||
|  | 			limit: 30 | ||||||
|  | 		}).then(stats => { | ||||||
|  | 			const data = []; | ||||||
|  | 
 | ||||||
|  | 			const now = new Date(); | ||||||
|  | 			const y = now.getFullYear(); | ||||||
|  | 			const m = now.getMonth(); | ||||||
|  | 			const d = now.getDate(); | ||||||
|  | 			const h = now.getHours(); | ||||||
|  | 
 | ||||||
|  | 			for (let i = 0; i < 30; i++) { | ||||||
|  | 				const x = new Date(y, m, d, h - i + 1); | ||||||
|  | 				data.push({ | ||||||
|  | 					x: x, | ||||||
|  | 					count: stats.count[i] | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			const chart = new G2.Chart({ | ||||||
|  | 				container: this.$refs.chart as HTMLDivElement, | ||||||
|  | 				forceFit: true, | ||||||
|  | 				height: 70, | ||||||
|  | 				padding: 8, | ||||||
|  | 				renderer: 'svg' | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			const text = tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--primary')); | ||||||
|  | 
 | ||||||
|  | 			chart.area().position('x*count').color(`l(100) 0:${text.clone().setAlpha(0.5).toRgbString()} 1:${text.clone().setAlpha(0.25).toRgbString()}`); | ||||||
|  | 			chart.line().position('x*count').color(`#${text.clone().toHex()}`).size(2); | ||||||
|  | 			chart.legend(false); | ||||||
|  | 			chart.axis('x', false); | ||||||
|  | 			chart.axis('count', false); | ||||||
|  | 			chart.tooltip(true, { | ||||||
|  | 				showTitle: false, | ||||||
|  | 				crosshairs: { | ||||||
|  | 					type: 'line' | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 			chart.source(data); | ||||||
|  | 			chart.render(); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | .xroyrflcmhhtmlwmyiwpfqiirqokfueb | ||||||
|  | 	background var(--deckColumnBg) | ||||||
|  | 
 | ||||||
|  | 	> .chart | ||||||
|  | 		margin 16px 0 | ||||||
|  | 		background var(--face) | ||||||
|  | 
 | ||||||
|  | 	> .tl | ||||||
|  | 		background var(--face) | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								src/server/api/endpoints/charts/hashtag.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/server/api/endpoints/charts/hashtag.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | ||||||
|  | import $ from 'cafy'; | ||||||
|  | import getParams from '../../get-params'; | ||||||
|  | import { hashtagStats } from '../../../../services/stats'; | ||||||
|  | 
 | ||||||
|  | export const meta = { | ||||||
|  | 	desc: { | ||||||
|  | 		'ja-JP': 'ハッシュタグごとの統計を取得します。' | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	params: { | ||||||
|  | 		span: $.str.or(['day', 'hour']).note({ | ||||||
|  | 			desc: { | ||||||
|  | 				'ja-JP': '集計のスパン (day または hour)' | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 
 | ||||||
|  | 		limit: $.num.optional.range(1, 100).note({ | ||||||
|  | 			default: 30, | ||||||
|  | 			desc: { | ||||||
|  | 				'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。' | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 
 | ||||||
|  | 		tag: $.str.note({ | ||||||
|  | 			desc: { | ||||||
|  | 				'ja-JP': '対象のハッシュタグ' | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export default (params: any) => new Promise(async (res, rej) => { | ||||||
|  | 	const [ps, psErr] = getParams(meta, params); | ||||||
|  | 	if (psErr) throw psErr; | ||||||
|  | 
 | ||||||
|  | 	const stats = await hashtagStats.getChart(ps.span as any, ps.limit, ps.tag); | ||||||
|  | 
 | ||||||
|  | 	res(stats); | ||||||
|  | }); | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue