chore(client): tweak ui
This commit is contained in:
		
							parent
							
								
									ec41aefeea
								
							
						
					
					
						commit
						9c6a220810
					
				
					 4 changed files with 46 additions and 28 deletions
				
			
		|  | @ -6,7 +6,7 @@ | ||||||
| 			<div class="track"> | 			<div class="track"> | ||||||
| 				<div class="highlight" :style="{ width: (steppedRawValue * 100) + '%' }"></div> | 				<div class="highlight" :style="{ width: (steppedRawValue * 100) + '%' }"></div> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div v-if="steps" class="ticks"> | 			<div v-if="steps && showTicks" class="ticks"> | ||||||
| 				<div v-for="i in (steps + 1)" class="tick" :style="{ left: (((i - 1) / steps) * 100) + '%' }"></div> | 				<div v-for="i in (steps + 1)" class="tick" :style="{ left: (((i - 1) / steps) * 100) + '%' }"></div> | ||||||
| 			</div> | 			</div> | ||||||
| 			<div ref="thumbEl" v-tooltip="textConverter(finalValue)" class="thumb" :style="{ left: thumbPosition + 'px' }" @mousedown="onMousedown" @touchstart="onMousedown"></div> | 			<div ref="thumbEl" v-tooltip="textConverter(finalValue)" class="thumb" :style="{ left: thumbPosition + 'px' }" @mousedown="onMousedown" @touchstart="onMousedown"></div> | ||||||
|  | @ -27,6 +27,7 @@ const props = withDefaults(defineProps<{ | ||||||
| 	max: number; | 	max: number; | ||||||
| 	step?: number; | 	step?: number; | ||||||
| 	textConverter?: (value: number) => string, | 	textConverter?: (value: number) => string, | ||||||
|  | 	showTicks?: boolean; | ||||||
| }>(), { | }>(), { | ||||||
| 	step: 1, | 	step: 1, | ||||||
| 	textConverter: (v) => v.toString(), | 	textConverter: (v) => v.toString(), | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { h, onMounted, onUnmounted, ref } from 'vue'; | import { h, onMounted, onUnmounted, ref, watch } from 'vue'; | ||||||
| 
 | 
 | ||||||
| export default { | export default { | ||||||
| 	name: 'MarqueeText', | 	name: 'MarqueeText', | ||||||
|  | @ -32,6 +32,8 @@ export default { | ||||||
| 			contentEl.value.style.animationDuration = `${duration}s`; | 			contentEl.value.style.animationDuration = `${duration}s`; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		watch(() => props.duration, calc); | ||||||
|  | 
 | ||||||
| 		onMounted(() => { | 		onMounted(() => { | ||||||
| 			calc(); | 			calc(); | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|  | @ -4,6 +4,8 @@ export function useInterval(fn: () => void, interval: number, options: { | ||||||
| 	immediate: boolean; | 	immediate: boolean; | ||||||
| 	afterMounted: boolean; | 	afterMounted: boolean; | ||||||
| }): void { | }): void { | ||||||
|  | 	if (Number.isNaN(interval)) return; | ||||||
|  | 
 | ||||||
| 	let intervalId: number | null = null; | 	let intervalId: number | null = null; | ||||||
| 
 | 
 | ||||||
| 	if (options.afterMounted) { | 	if (options.afterMounted) { | ||||||
|  |  | ||||||
|  | @ -6,11 +6,13 @@ | ||||||
| 	<div class="ekmkgxbk"> | 	<div class="ekmkgxbk"> | ||||||
| 		<MkLoading v-if="fetching"/> | 		<MkLoading v-if="fetching"/> | ||||||
| 		<div v-else class="feed"> | 		<div v-else class="feed"> | ||||||
| 			<MarqueeText :key="key" :duration="widgetProps.speed" :reverse="widgetProps.reverse"> | 			<transition name="change" mode="default"> | ||||||
| 				<span v-for="item in items" class="item"> | 				<MarqueeText :key="key" :duration="widgetProps.duration" :reverse="widgetProps.reverse"> | ||||||
| 					<a class="link" :href="item.link" rel="nofollow noopener" target="_blank" :title="item.title">{{ item.title }}</a><span class="divider"></span> | 					<span v-for="item in items" class="item"> | ||||||
| 				</span> | 						<a class="link" :href="item.link" rel="nofollow noopener" target="_blank" :title="item.title">{{ item.title }}</a><span class="divider"></span> | ||||||
| 			</MarqueeText> | 					</span> | ||||||
|  | 				</MarqueeText> | ||||||
|  | 			</transition> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| </MkContainer> | </MkContainer> | ||||||
|  | @ -32,6 +34,21 @@ const widgetPropsDef = { | ||||||
| 		type: 'string' as const, | 		type: 'string' as const, | ||||||
| 		default: 'http://feeds.afpbb.com/rss/afpbb/afpbbnews', | 		default: 'http://feeds.afpbb.com/rss/afpbb/afpbbnews', | ||||||
| 	}, | 	}, | ||||||
|  | 	refreshIntervalSec: { | ||||||
|  | 		type: 'number' as const, | ||||||
|  | 		default: 60, | ||||||
|  | 	}, | ||||||
|  | 	duration: { | ||||||
|  | 		type: 'range' as const, | ||||||
|  | 		default: 70, | ||||||
|  | 		step: 1, | ||||||
|  | 		min: 5, | ||||||
|  | 		max: 200, | ||||||
|  | 	}, | ||||||
|  | 	reverse: { | ||||||
|  | 		type: 'boolean' as const, | ||||||
|  | 		default: false, | ||||||
|  | 	}, | ||||||
| 	showHeader: { | 	showHeader: { | ||||||
| 		type: 'boolean' as const, | 		type: 'boolean' as const, | ||||||
| 		default: false, | 		default: false, | ||||||
|  | @ -40,25 +57,6 @@ const widgetPropsDef = { | ||||||
| 		type: 'boolean' as const, | 		type: 'boolean' as const, | ||||||
| 		default: false, | 		default: false, | ||||||
| 	}, | 	}, | ||||||
| 	speed: { |  | ||||||
| 		type: 'radio' as const, |  | ||||||
| 		default: 70, |  | ||||||
| 		options: [{ |  | ||||||
| 			value: 170, label: 'very slow', |  | ||||||
| 		}, { |  | ||||||
| 			value: 100, label: 'slow', |  | ||||||
| 		}, { |  | ||||||
| 			value: 70, label: 'medium', |  | ||||||
| 		}, { |  | ||||||
| 			value: 40, label: 'fast', |  | ||||||
| 		}, { |  | ||||||
| 			value: 20, label: 'very fast', |  | ||||||
| 		}], |  | ||||||
| 	}, |  | ||||||
| 	reverse: { |  | ||||||
| 		type: 'boolean' as const, |  | ||||||
| 		default: false, |  | ||||||
| 	}, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| type WidgetProps = GetFormResultType<typeof widgetPropsDef>; | type WidgetProps = GetFormResultType<typeof widgetPropsDef>; | ||||||
|  | @ -91,7 +89,7 @@ const tick = () => { | ||||||
| 
 | 
 | ||||||
| watch(() => widgetProps.url, tick); | watch(() => widgetProps.url, tick); | ||||||
| 
 | 
 | ||||||
| useInterval(tick, 60000, { | useInterval(tick, Math.max(10000, widgetProps.refreshIntervalSec * 1000), { | ||||||
| 	immediate: true, | 	immediate: true, | ||||||
| 	afterMounted: true, | 	afterMounted: true, | ||||||
| }); | }); | ||||||
|  | @ -104,17 +102,32 @@ defineExpose<WidgetComponentExpose>({ | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
|  | .change-enter-active, .change-leave-active { | ||||||
|  | 	position: absolute; | ||||||
|  | 	top: 0; | ||||||
|  |   transition: all 1s ease; | ||||||
|  | } | ||||||
|  | .change-enter-from { | ||||||
|  |   opacity: 0; | ||||||
|  | 	transform: translateY(-100%); | ||||||
|  | } | ||||||
|  | .change-leave-to { | ||||||
|  |   opacity: 0; | ||||||
|  | 	transform: translateY(100%); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .ekmkgxbk { | .ekmkgxbk { | ||||||
| 	> .feed { | 	> .feed { | ||||||
| 		padding: 0; | 		padding: 0; | ||||||
| 		font-size: 0.9em; | 		font-size: 0.9em; | ||||||
|  | 		line-height: 42px; | ||||||
|  | 		height: 42px; | ||||||
| 
 | 
 | ||||||
| 		::v-deep(.item) { | 		::v-deep(.item) { | ||||||
| 			display: inline-flex; | 			display: inline-flex; | ||||||
| 			align-items: center; | 			align-items: center; | ||||||
| 			vertical-align: bottom; | 			vertical-align: bottom; | ||||||
| 			color: var(--fg); | 			color: var(--fg); | ||||||
| 			margin: 12px 0; |  | ||||||
| 
 | 
 | ||||||
| 			> .divider { | 			> .divider { | ||||||
| 				display: inline-block; | 				display: inline-block; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue