refactor: 重构 render/components 目录下部分组件, 使用 Vue3 组合式 API 写法 (#115)

This commit is contained in:
alwayrun 2024-05-20 20:42:37 +08:00 committed by sudoooooo
parent eed15cd23c
commit 5e50a3a733
8 changed files with 153 additions and 178 deletions

View File

@ -2,33 +2,33 @@
<div class="mask" v-if="visible"> <div class="mask" v-if="visible">
<div class="box"> <div class="box">
<div class="title">{{ title }}</div> <div class="title">{{ title }}</div>
<div class="btn" @click="onConfirm">{{ btnText }}</div> <div class="btn" @click="handleConfirm">{{ btnText }}</div>
</div> </div>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
export default { interface Props {
name: 'AlertDialog', visible?: boolean
props: { btnText?: string
visible: { title?: string
type: Boolean, }
default: false
}, interface Emit {
btnText: { (ev: 'confirm'): void
type: String, (ev: 'close'): void
default: '我知道了' }
},
title: { const emit = defineEmits<Emit>()
type: String,
default: '' withDefaults(defineProps<Props>(), {
} visible: false,
}, btnText: '我知道了',
methods: { title: ''
onConfirm() { })
this.$emit('confirm')
this.$emit('close') const handleConfirm = () => {
} emit('confirm')
} emit('close')
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -3,44 +3,42 @@
<div class="box"> <div class="box">
<div class="title">{{ title }}</div> <div class="title">{{ title }}</div>
<div class="btn-box"> <div class="btn-box">
<div class="btn cancel" @click="onCancel">{{ cancelBtnText }}</div> <div class="btn cancel" @click="handleCancel">{{ cancelBtnText }}</div>
<div class="btn confirm" @click="onConfirm">{{ confirmBtnText }}</div> <div class="btn confirm" @click="handleConfirm">{{ confirmBtnText }}</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
export default { interface Props {
name: 'ConfirmDialog', visible?: boolean
props: { cancelBtnText?: string
visible: { confirmBtnText?: string
type: Boolean, title?: string
default: false }
},
cancelBtnText: { interface Emit {
type: String, (ev: 'confirm', callback: () => void): void
default: '取消' (ev: 'close'): void
}, }
confirmBtnText: {
type: String, const emit = defineEmits<Emit>()
default: '确定'
}, withDefaults(defineProps<Props>(), {
title: { visible: false,
type: String, cancelBtnText: '取消',
default: '' confirmBtnText: '确定',
} title: ''
}, })
methods: {
onCancel() { const handleConfirm = () => {
// this.$emit('cancel'); emit('confirm', () => {
this.$emit('close') emit('close')
}, })
onConfirm() { }
this.$emit('confirm', () => {
this.$emit('close') const handleCancel = () => {
}) emit('close')
}
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -5,13 +5,13 @@
class="banner-img" class="banner-img"
:src="bannerConf.bannerConfig.bgImage" :src="bannerConf.bannerConfig.bgImage"
:class="{ pointer: bannerConf.bannerConfig.bgImageAllowJump }" :class="{ pointer: bannerConf.bannerConfig.bgImageAllowJump }"
@click="onBannerClick" @click="handleBannerClick"
/> />
</div> </div>
<div class="banner" v-if="bannerConf.bannerConfig && bannerConf.bannerConfig.videoLink"> <div class="banner" v-if="bannerConf.bannerConfig && bannerConf.bannerConfig.videoLink">
<div class="video"> <div class="video">
<video <video
id="video" ref="videoRef"
controls controls
style="margin: 0 auto; width: 100%; display: block" style="margin: 0 auto; width: 100%; display: block"
preload="auto" preload="auto"
@ -21,49 +21,50 @@
</video> </video>
<div <div
class="video-modal" class="video-modal"
:style="`background-image:url(${bannerConf.bannerConfig.postImg})`" :style="{
backgroundImage:
bannerConf.bannerConfig.postImg && `url(${bannerConf.bannerConfig.postImg})`,
display: displayModel
}"
></div>
<div
class="iconfont icon-kaishi play-icon"
:style="{ display: displayModel }"
@click="handlePlay()"
></div> ></div>
<div class="iconfont icon-kaishi play-icon" @click="play()"></div>
</div> </div>
</div> </div>
<!-- <div
class="titlePanel"
v-if="bannerConf.titleConfig && bannerConf.titleConfig.mainTitle"
>
<div
class="mainTitle"
v-if="bannerConf.titleConfig.mainTitle"
v-safe-html="bannerConf.titleConfig.mainTitle"
></div>
</div> -->
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { computed, ref } from 'vue'
import { useStore } from 'vuex'
import { get as _get } from 'lodash-es' import { get as _get } from 'lodash-es'
import { formatLink } from '../utils/index.js' import { formatLink } from '../utils/index.js'
export default { const store = useStore()
name: 'HeaderSetter',
computed: { const bannerConf = computed<any>(() => _get(store, 'state.bannerConf', {}))
bannerConf() {
return _get(this.$store, 'state.bannerConf', {}) const handleBannerClick = () => {
} const allow = _get(bannerConf.value, 'bannerConfig.bgImageAllowJump', false)
}, const jumpLink = _get(bannerConf.value, 'bannerConfig.bgImageJumpLink', '')
methods: {
onBannerClick() { if (!allow || !jumpLink) {
const allow = _get(this.bannerConf, 'bannerConfig.bgImageAllowJump', false) return
const jumpLink = _get(this.bannerConf, 'bannerConfig.bgImageJumpLink', '') }
if (!allow || !jumpLink) {
return window.open(formatLink(jumpLink))
} }
window.open(formatLink(jumpLink))
}, const videoRef = ref<HTMLVideoElement | null>(null)
play() { const displayModel = ref('block')
const video = document.getElementById('video')
document.querySelector('.play-icon').style.display = 'none' const handlePlay = () => {
document.querySelector('.video-modal').style.display = 'none' if (bannerConf.value.bannerConfig && bannerConf.value.bannerConfig.videoLink) {
video.play() videoRef.value?.play()
} displayModel.value = 'none'
} }
} }
</script> </script>

View File

@ -5,21 +5,15 @@
</div> </div>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
export default { import { computed } from 'vue'
name: 'LogoIcon', import { useStore } from 'vuex'
computed: {
logoImage() { const store = useStore()
return this.$store.state?.bottomConf?.logoImage
}, const logoImage = computed(() => store.state?.bottomConf?.logoImage)
logoImageWidth() { const logoImageWidth = computed(() => store.state?.bottomConf?.logoImageWidth)
return this.$store.state?.bottomConf?.logoImageWidth const isMobile = computed(() => store.state?.isMobile)
},
isMobile() {
return this.$store.state?.isMobile
}
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.container { .container {

View File

@ -6,37 +6,24 @@
:render-data="item" :render-data="item"
:rules="rules" :rules="rules"
:formModel="formModel" :formModel="formModel"
@formChange="changeData" @formChange="handleChangeData"
/> />
</template> </template>
</div> </div>
</template> </template>
<script setup lang="ts">
import { computed } from 'vue'
import { useStore } from 'vuex'
<script>
import { mapActions } from 'vuex'
import MaterialGroup from './MaterialGroup.vue' import MaterialGroup from './MaterialGroup.vue'
export default {
name: 'MainRenderer', const store = useStore()
computed: {
questionData() { const renderData = computed(() => store.getters?.renderData)
return this.$store.state.questionData const rules = computed(() => store.state.rules)
}, const formModel = computed(() => store.getters.formModel)
renderData() {
return this.$store.getters.renderData const handleChangeData = (data: any) => {
}, store.dispatch('changeData', data)
rules() {
return this.$store.state.rules
},
formModel() {
return this.$store.getters.formModel
}
},
mounted() {},
components: { MaterialGroup },
methods: {
...mapActions(['changeData'])
}
} }
</script> </script>
<style scoped lang="scss"></style>

View File

@ -9,18 +9,13 @@
</div> </div>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { get as _get } from 'lodash-es' import { computed } from 'vue'
export default { import { useStore } from 'vuex'
name: 'MainTitle',
computed: {
bannerConf() {
return _get(this.$store, 'state.bannerConf', {})
}
}
}
</script>
const store = useStore()
const bannerConf = computed(() => store.state?.bannerConf || {})
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/render/styles/variable.scss'; @import '@/render/styles/variable.scss';
.question-header { .question-header {

View File

@ -1,45 +1,42 @@
<template> <template>
<div class="question-submit_wrapper"> <div class="question-submit_wrapper">
<button class="question-submit-btn" @click="submit"> <button class="question-submit-btn" @click="handleSubmit">
{{ submitConf.submitTitle }} {{ submitConf.submitTitle }}
</button> </button>
</div> </div>
</template> </template>
<script setup lang="ts">
import { computed } from 'vue'
import { useStore } from 'vuex'
<script> interface Props {
export default { validate: (fn: (valid: boolean) => void) => void
name: 'SubmitSetter', renderData?: Array<any>
props: { }
validate: Function,
renderData: Array interface Emit {
}, (ev: 'submit'): void
data() { }
return {}
}, const props = defineProps<Props>()
computed: { const emit = defineEmits<Emit>()
submitConf() {
return this.$store.state?.submitConf || {} const store = useStore()
},
skinConf() { const submitConf = computed(() => store.state?.submitConf || {})
return this.$store.state?.skinConf || {}
} const handleSubmit = (e: Event) => {
}, const validate = props.validate
methods: { if (e) {
submit(e) { e.preventDefault()
const validate = this.validate validate((valid) => {
if (e) { if (valid) {
e.preventDefault() emit('submit')
validate((valid) => {
if (valid) {
this.$emit('submit')
}
})
} }
} })
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '@/render/styles/variable.scss'; @import '@/render/styles/variable.scss';
.question-submit_wrapper { .question-submit_wrapper {

View File

@ -16,4 +16,7 @@
.icon-kaishi:before { .icon-kaishi:before {
content: '\e6ad'; content: '\e6ad';
border-radius: 50%;
background-color: white;
cursor: pointer;
} }