From 7b0c1c43c95e93ae13dc936962b47b5ce67ff103 Mon Sep 17 00:00:00 2001
From: alwayrun <minge23@live.cn>
Date: Mon, 20 May 2024 20:42:37 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20render/compone?=
 =?UTF-8?q?nts=20=E7=9B=AE=E5=BD=95=E4=B8=8B=E9=83=A8=E5=88=86=E7=BB=84?=
 =?UTF-8?q?=E4=BB=B6,=20=E4=BD=BF=E7=94=A8=20Vue3=20=E7=BB=84=E5=90=88?=
 =?UTF-8?q?=E5=BC=8F=20API=20=E5=86=99=E6=B3=95=20(#115)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 web/src/render/components/AlertDialog.vue   | 48 ++++++-------
 web/src/render/components/ConfirmDialog.vue | 66 +++++++++---------
 web/src/render/components/HeaderSetter.vue  | 75 +++++++++++----------
 web/src/render/components/LogoIcon.vue      | 24 +++----
 web/src/render/components/MainRenderer.vue  | 39 ++++-------
 web/src/render/components/MainTitle.vue     | 17 ++---
 web/src/render/components/SubmitSetter.vue  | 59 ++++++++--------
 web/src/render/styles/icon.scss             |  3 +
 8 files changed, 153 insertions(+), 178 deletions(-)

diff --git a/web/src/render/components/AlertDialog.vue b/web/src/render/components/AlertDialog.vue
index 61e4bf15..7fa04e6e 100644
--- a/web/src/render/components/AlertDialog.vue
+++ b/web/src/render/components/AlertDialog.vue
@@ -2,33 +2,33 @@
   <div class="mask" v-if="visible">
     <div class="box">
       <div class="title">{{ title }}</div>
-      <div class="btn" @click="onConfirm">{{ btnText }}</div>
+      <div class="btn" @click="handleConfirm">{{ btnText }}</div>
     </div>
   </div>
 </template>
-<script>
-export default {
-  name: 'AlertDialog',
-  props: {
-    visible: {
-      type: Boolean,
-      default: false
-    },
-    btnText: {
-      type: String,
-      default: '我知道了'
-    },
-    title: {
-      type: String,
-      default: ''
-    }
-  },
-  methods: {
-    onConfirm() {
-      this.$emit('confirm')
-      this.$emit('close')
-    }
-  }
+<script setup lang="ts">
+interface Props {
+  visible?: boolean
+  btnText?: string
+  title?: string
+}
+
+interface Emit {
+  (ev: 'confirm'): void
+  (ev: 'close'): void
+}
+
+const emit = defineEmits<Emit>()
+
+withDefaults(defineProps<Props>(), {
+  visible: false,
+  btnText: '我知道了',
+  title: ''
+})
+
+const handleConfirm = () => {
+  emit('confirm')
+  emit('close')
 }
 </script>
 <style lang="scss" scoped>
diff --git a/web/src/render/components/ConfirmDialog.vue b/web/src/render/components/ConfirmDialog.vue
index ca14ceae..82c0e40c 100644
--- a/web/src/render/components/ConfirmDialog.vue
+++ b/web/src/render/components/ConfirmDialog.vue
@@ -3,44 +3,42 @@
     <div class="box">
       <div class="title">{{ title }}</div>
       <div class="btn-box">
-        <div class="btn cancel" @click="onCancel">{{ cancelBtnText }}</div>
-        <div class="btn confirm" @click="onConfirm">{{ confirmBtnText }}</div>
+        <div class="btn cancel" @click="handleCancel">{{ cancelBtnText }}</div>
+        <div class="btn confirm" @click="handleConfirm">{{ confirmBtnText }}</div>
       </div>
     </div>
   </div>
 </template>
-<script>
-export default {
-  name: 'ConfirmDialog',
-  props: {
-    visible: {
-      type: Boolean,
-      default: false
-    },
-    cancelBtnText: {
-      type: String,
-      default: '取消'
-    },
-    confirmBtnText: {
-      type: String,
-      default: '确定'
-    },
-    title: {
-      type: String,
-      default: ''
-    }
-  },
-  methods: {
-    onCancel() {
-      // this.$emit('cancel');
-      this.$emit('close')
-    },
-    onConfirm() {
-      this.$emit('confirm', () => {
-        this.$emit('close')
-      })
-    }
-  }
+<script setup lang="ts">
+interface Props {
+  visible?: boolean
+  cancelBtnText?: string
+  confirmBtnText?: string
+  title?: string
+}
+
+interface Emit {
+  (ev: 'confirm', callback: () => void): void
+  (ev: 'close'): void
+}
+
+const emit = defineEmits<Emit>()
+
+withDefaults(defineProps<Props>(), {
+  visible: false,
+  cancelBtnText: '取消',
+  confirmBtnText: '确定',
+  title: ''
+})
+
+const handleConfirm = () => {
+  emit('confirm', () => {
+    emit('close')
+  })
+}
+
+const handleCancel = () => {
+  emit('close')
 }
 </script>
 <style lang="scss" scoped>
diff --git a/web/src/render/components/HeaderSetter.vue b/web/src/render/components/HeaderSetter.vue
index b73eb844..7e4d508f 100755
--- a/web/src/render/components/HeaderSetter.vue
+++ b/web/src/render/components/HeaderSetter.vue
@@ -5,13 +5,13 @@
         class="banner-img"
         :src="bannerConf.bannerConfig.bgImage"
         :class="{ pointer: bannerConf.bannerConfig.bgImageAllowJump }"
-        @click="onBannerClick"
+        @click="handleBannerClick"
       />
     </div>
     <div class="banner" v-if="bannerConf.bannerConfig && bannerConf.bannerConfig.videoLink">
       <div class="video">
         <video
-          id="video"
+          ref="videoRef"
           controls
           style="margin: 0 auto; width: 100%; display: block"
           preload="auto"
@@ -21,49 +21,50 @@
         </video>
         <div
           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 class="iconfont icon-kaishi play-icon" @click="play()"></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>
 </template>
-<script>
+<script setup lang="ts">
+import { computed, ref } from 'vue'
+import { useStore } from 'vuex'
 import { get as _get } from 'lodash-es'
+
 import { formatLink } from '../utils/index.js'
 
-export default {
-  name: 'HeaderSetter',
-  computed: {
-    bannerConf() {
-      return _get(this.$store, 'state.bannerConf', {})
-    }
-  },
-  methods: {
-    onBannerClick() {
-      const allow = _get(this.bannerConf, 'bannerConfig.bgImageAllowJump', false)
-      const jumpLink = _get(this.bannerConf, 'bannerConfig.bgImageJumpLink', '')
-      if (!allow || !jumpLink) {
-        return
-      }
-      window.open(formatLink(jumpLink))
-    },
-    play() {
-      const video = document.getElementById('video')
-      document.querySelector('.play-icon').style.display = 'none'
-      document.querySelector('.video-modal').style.display = 'none'
-      video.play()
-    }
+const store = useStore()
+
+const bannerConf = computed<any>(() => _get(store, 'state.bannerConf', {}))
+
+const handleBannerClick = () => {
+  const allow = _get(bannerConf.value, 'bannerConfig.bgImageAllowJump', false)
+  const jumpLink = _get(bannerConf.value, 'bannerConfig.bgImageJumpLink', '')
+
+  if (!allow || !jumpLink) {
+    return
+  }
+
+  window.open(formatLink(jumpLink))
+}
+
+const videoRef = ref<HTMLVideoElement | null>(null)
+const displayModel = ref('block')
+
+const handlePlay = () => {
+  if (bannerConf.value.bannerConfig && bannerConf.value.bannerConfig.videoLink) {
+    videoRef.value?.play()
+    displayModel.value = 'none'
   }
 }
 </script>
diff --git a/web/src/render/components/LogoIcon.vue b/web/src/render/components/LogoIcon.vue
index 39ef1678..d266cda0 100644
--- a/web/src/render/components/LogoIcon.vue
+++ b/web/src/render/components/LogoIcon.vue
@@ -5,21 +5,15 @@
     </div>
   </div>
 </template>
-<script>
-export default {
-  name: 'LogoIcon',
-  computed: {
-    logoImage() {
-      return this.$store.state?.bottomConf?.logoImage
-    },
-    logoImageWidth() {
-      return this.$store.state?.bottomConf?.logoImageWidth
-    },
-    isMobile() {
-      return this.$store.state?.isMobile
-    }
-  }
-}
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useStore } from 'vuex'
+
+const store = useStore()
+
+const logoImage = computed(() => store.state?.bottomConf?.logoImage)
+const logoImageWidth = computed(() => store.state?.bottomConf?.logoImageWidth)
+const isMobile = computed(() => store.state?.isMobile)
 </script>
 <style lang="scss" scoped>
 .container {
diff --git a/web/src/render/components/MainRenderer.vue b/web/src/render/components/MainRenderer.vue
index 38895a07..da70b993 100644
--- a/web/src/render/components/MainRenderer.vue
+++ b/web/src/render/components/MainRenderer.vue
@@ -6,37 +6,24 @@
         :render-data="item"
         :rules="rules"
         :formModel="formModel"
-        @formChange="changeData"
+        @formChange="handleChangeData"
       />
     </template>
   </div>
 </template>
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useStore } from 'vuex'
 
-<script>
-import { mapActions } from 'vuex'
 import MaterialGroup from './MaterialGroup.vue'
-export default {
-  name: 'MainRenderer',
-  computed: {
-    questionData() {
-      return this.$store.state.questionData
-    },
-    renderData() {
-      return this.$store.getters.renderData
-    },
-    rules() {
-      return this.$store.state.rules
-    },
-    formModel() {
-      return this.$store.getters.formModel
-    }
-  },
-  mounted() {},
-  components: { MaterialGroup },
-  methods: {
-    ...mapActions(['changeData'])
-  }
+
+const store = useStore()
+
+const renderData = computed(() => store.getters?.renderData)
+const rules = computed(() => store.state.rules)
+const formModel = computed(() => store.getters.formModel)
+
+const handleChangeData = (data: any) => {
+  store.dispatch('changeData', data)
 }
 </script>
-
-<style scoped lang="scss"></style>
diff --git a/web/src/render/components/MainTitle.vue b/web/src/render/components/MainTitle.vue
index 23ee3c13..7fa6099d 100644
--- a/web/src/render/components/MainTitle.vue
+++ b/web/src/render/components/MainTitle.vue
@@ -9,18 +9,13 @@
     </div>
   </div>
 </template>
-<script>
-import { get as _get } from 'lodash-es'
-export default {
-  name: 'MainTitle',
-  computed: {
-    bannerConf() {
-      return _get(this.$store, 'state.bannerConf', {})
-    }
-  }
-}
-</script>
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useStore } from 'vuex'
 
+const store = useStore()
+const bannerConf = computed(() => store.state?.bannerConf || {})
+</script>
 <style lang="scss" scoped>
 @import '@/render/styles/variable.scss';
 .question-header {
diff --git a/web/src/render/components/SubmitSetter.vue b/web/src/render/components/SubmitSetter.vue
index e3ac7806..fc0546ff 100644
--- a/web/src/render/components/SubmitSetter.vue
+++ b/web/src/render/components/SubmitSetter.vue
@@ -1,45 +1,42 @@
 <template>
   <div class="question-submit_wrapper">
-    <button class="question-submit-btn" @click="submit">
+    <button class="question-submit-btn" @click="handleSubmit">
       {{ submitConf.submitTitle }}
     </button>
   </div>
 </template>
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useStore } from 'vuex'
 
-<script>
-export default {
-  name: 'SubmitSetter',
-  props: {
-    validate: Function,
-    renderData: Array
-  },
-  data() {
-    return {}
-  },
-  computed: {
-    submitConf() {
-      return this.$store.state?.submitConf || {}
-    },
-    skinConf() {
-      return this.$store.state?.skinConf || {}
-    }
-  },
-  methods: {
-    submit(e) {
-      const validate = this.validate
-      if (e) {
-        e.preventDefault()
-        validate((valid) => {
-          if (valid) {
-            this.$emit('submit')
-          }
-        })
+interface Props {
+  validate: (fn: (valid: boolean) => void) => void
+  renderData?: Array<any>
+}
+
+interface Emit {
+  (ev: 'submit'): void
+}
+
+const props = defineProps<Props>()
+const emit = defineEmits<Emit>()
+
+const store = useStore()
+
+const submitConf = computed(() => store.state?.submitConf || {})
+
+const handleSubmit = (e: Event) => {
+  const validate = props.validate
+  if (e) {
+    e.preventDefault()
+    validate((valid) => {
+      if (valid) {
+        emit('submit')
       }
-    }
+    })
   }
 }
 </script>
-
 <style lang="scss" scoped>
 @import '@/render/styles/variable.scss';
 .question-submit_wrapper {
diff --git a/web/src/render/styles/icon.scss b/web/src/render/styles/icon.scss
index 6a01c53e..3b2f4edc 100644
--- a/web/src/render/styles/icon.scss
+++ b/web/src/render/styles/icon.scss
@@ -16,4 +16,7 @@
 
 .icon-kaishi:before {
   content: '\e6ad';
+  border-radius: 50%;
+  background-color: white;
+  cursor: pointer;
 }