Pārlūkot izejas kodu

feat(leave-source): 实现离店客源申请流程

- 新增 BaseDialog、PhoneEditDialog 和 SubMitSuccess 组件
- 更新 ContractMine 组件,添加联系电话输入和事件处理
- 修改 ContentCard 组件,支持不同类型的内容展示
- 优化 ContractCard 组件,集成新的联系电话事件
- 更新 ContentDialog 组件,集成新的对话框流程
- 完善 usePhoneCheck 钩子,支持手机号验证和提交逻辑

Signed-off-by: tangshizhe <48740614+tangshizhe@users.noreply.github.com>
tangshizhe 3 nedēļas atpakaļ
vecāks
revīzija
db2b1dad13

+ 52 - 0
plugins/leave-source/src/lib/pc/components/BaseDialog.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="base-dialog">
+    <AnimatedOverlay
+      :visible="visible"
+      @update:visible="updateVisible"
+      @close="close"
+    >
+      <div class="base-dialog-content" :style="{ width: props.width }">
+        <slot name="content" />
+      </div>
+    </AnimatedOverlay>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import AnimatedOverlay from '../../../components/dialog/AnimatedOverlay.vue'
+
+const props = defineProps({
+  width: {
+    type: String,
+    default: '316px'
+  }
+})
+
+const visible = ref(false)
+function updateVisible(f = false) {
+  visible.value = f
+}
+function close() {
+  visible.value = false
+}
+defineExpose({
+  updateVisible
+})
+</script>
+
+<style lang="scss" scoped>
+  .base-dialog {
+    &-content {
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      margin: 300px auto;
+      padding: 32px;
+      border-radius: 8px;
+      background: #fff;
+    }
+  }
+</style>

+ 15 - 3
plugins/leave-source/src/lib/pc/components/ContractMine.vue

@@ -5,9 +5,9 @@
     </div>
     <div class="contract-mine-content">
       <label for="phone" class="contract-mine-label">联系电话:</label>
-      <input id="phone" type="text" class="contract-mine-input">
+      <input id="phone" v-model="phone" type="text" class="contract-mine-input" placeholder="请输入联系电话">
     </div>
-    <button class="contract-mine-btn">
+    <button class="contract-mine-btn" @click="handle">
       与我联系
     </button>
   </div>
@@ -15,7 +15,19 @@
 
 <script>
 export default {
-  name: 'ContractMine'
+  name: 'ContractMine',
+  data() {
+    return {
+      phone: ''
+    }
+  },
+
+  methods: {
+    handle() {
+      console.log('phone', this.phone)
+      this.$emit('contactMeEvent', this.phone)
+    }
+  }
 }
 </script>
 

+ 94 - 0
plugins/leave-source/src/lib/pc/components/PhoneEditDialog.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="phone-edit-dialog">
+    <BaseDialog ref="baseDialogRef">
+      <template #content>
+        <header>修改联系电话</header>
+        <main>
+          <span>联系电话:</span>
+          <input v-model="phone" name="phone" class="phone-edit-ipt" type="text" placeholder="请输入联系电话">
+        </main>
+        <footer>
+          <button @click="handleConfirm">
+            确定
+          </button>
+          <button @click="handleCancel">
+            取消
+          </button>
+        </footer>
+      </template>
+    </BaseDialog>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import BaseDialog from './BaseDialog.vue'
+
+const phone = ref('')
+
+const baseDialogRef = ref(null)
+
+function updateVisible(f = false) {
+  baseDialogRef.value.updateVisible(f)
+}
+
+function handleConfirm() {
+  console.log('handleConfirm')
+}
+function handleCancel() {
+  console.log('handleCancel')
+}
+
+defineExpose({
+  updateVisible
+})
+</script>
+
+<style lang="scss" scoped>
+  .phone-edit-dialog {
+    header {
+      font-size: 18px;
+      line-height: 28px;
+      color: #1D1D1D;
+    }
+    main {
+      margin: 20px 0 32px;
+      font-size: 14px;
+      line-height: 22px;
+      color: #686868;
+      text-align: center;
+      .phone-edit-ipt {
+        margin-left: 8px;
+        padding: 4px 16px;
+        width: 138px;
+        height: 24px;
+        border: 1px solid #E0E0E0;
+        border-radius: 4px;
+        color: #1D1D1D;
+        font-size: 16px;
+        line-height: 24px;
+      }
+    }
+    footer {
+      display: flex;
+      justify-content: space-between;
+      width: 100%;
+      button {
+        width: 132px;
+        height: 36px;
+        border-radius: 6px;
+        background: #2ABED1;
+        color: #fff;
+        font-size: 16px;
+        line-height: 24px;
+        border: none;
+        cursor: pointer;
+        &:last-child {
+          background: #fff;
+          border: 1px solid #E0E0E0;
+          color: #1D1D1D;
+        }
+      }
+    }
+  }
+</style>

+ 69 - 0
plugins/leave-source/src/lib/pc/components/SubMitSuccess.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="phone-edit-dialog">
+    <BaseDialog ref="baseDialogRef">
+      <template #content>
+        <header>提交成功</header>
+        <main>
+          我们的专属客服会在24小时内尽快与您联系,请注意电话接听。
+        </main>
+        <footer>
+          <button @click="handleConfirm">
+            我知道啦
+          </button>
+        </footer>
+      </template>
+    </BaseDialog>
+  </div>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import BaseDialog from './BaseDialog.vue'
+
+const baseDialogRef = ref(null)
+
+function updateVisible(f = false) {
+  baseDialogRef.value.updateVisible(f)
+}
+
+function handleConfirm() {
+  updateVisible(false)
+}
+
+defineExpose({
+  updateVisible
+})
+</script>
+
+<style lang="scss" scoped>
+  .phone-edit-dialog {
+    header {
+      font-size: 18px;
+      line-height: 28px;
+      color: #1D1D1D;
+    }
+    main {
+      margin: 20px 0 32px;
+      font-size: 14px;
+      line-height: 22px;
+      color: #686868;
+      text-align: center;
+    }
+    footer {
+      display: flex;
+      justify-content: center;
+      width: 100%;
+      button {
+        width: 132px;
+        height: 36px;
+        border-radius: 6px;
+        background: #2ABED1;
+        color: #fff;
+        font-size: 16px;
+        line-height: 24px;
+        border: none;
+        cursor: pointer;
+      }
+    }
+  }
+</style>

+ 37 - 22
plugins/leave-source/src/lib/pc/components/content-card.vue

@@ -1,13 +1,14 @@
 <template>
   <div class="content-card">
     <span class="j-icon icon-pc-close" />
-    <ContractCard v-if="type === '1'" />
-    <ContractCardQrcode v-if="type === '2'" class="qrcode-module" />
-    <LeaveCommon :class="{ 'samll-footer': type === '2' }" />
+    <ContractCard v-if="config.props.type === '1'" @contactMeEvent="contactMeEvent" />
+    <ContractCardQrcode v-else class="qrcode-module" />
+    <LeaveCommon :class="{ 'samll-footer': config.props.type === '2' }" />
   </div>
 </template>
 
 <script>
+import { usePhoneCheck } from '../../../utils/hooks'
 import ContractCard from './contract-card.vue'
 import ContractCardQrcode from './contract-card-qrcode.vue'
 import LeaveCommon from './footer'
@@ -17,33 +18,47 @@ export default {
   components: {
     ContractCard,
     ContractCardQrcode,
-    LeaveCommon
+    LeaveCommon,
   },
   props: {
-    type: {
-      type: String,
-      default: '2'
+    config: {
+      type: Object,
+      default: () => ({})
     },
-    source: {
-      type: String,
-      default: ''
-    },
-    sourceDesc: {
-      type: String,
-      default: ''
-    },
-    popupTitle: {
-      type: String,
-      default: '联系专属客服,申请免费体验'
-    }
+    // type: {
+    //   type: String,
+    //   default: '2'
+    // },
+    // source: {
+    //   type: String,
+    //   default: ''
+    // },
+    // sourceDesc: {
+    //   type: String,
+    //   default: ''
+    // },
+    // popupTitle: {
+    //   type: String,
+    //   default: '联系专属客服,申请免费体验'
+    // }
   },
 
   data() {
-    return {}
+    return {
+      confirmPhoneDialog: {}
+    }
+  },
+  mounted() {
+    this.confirmPhoneDialog = usePhoneCheck(this.config)
   },
   methods: {
-    // 手动触发绑定弹框
-    handle() {}
+    contactMeEvent(phone) {
+      console.log(this.config, 'config')
+      const newConfig = this.config
+      newConfig.configInfo.phone = phone
+      const { contactMe } = usePhoneCheck(newConfig)
+      contactMe()
+    }
   }
 }
 </script>

+ 5 - 2
plugins/leave-source/src/lib/pc/components/contract-card.vue

@@ -6,8 +6,8 @@
     </div>
     <div class="contract-card-content">
       <CallPhone class="call-phone" @handle="handle" />
-      <QrCode @handle="handle" />
-      <ContractMine class="contract-mine" @handle="handle" />
+      <QrCode type="1" @handle="handle" />
+      <ContractMine class="contract-mine" @contactMeEvent="contactMeEvent" />
     </div>
   </div>
 </template>
@@ -27,6 +27,9 @@ export default {
   methods: {
     handle() {
       this.$emit('handle')
+    },
+    contactMeEvent(phone) {
+      this.$emit('contactMeEvent', phone)
     }
   }
 }

+ 33 - 3
plugins/leave-source/src/lib/pc/content-dialog.vue

@@ -1,6 +1,9 @@
 <script setup>
 import AnimatedOverlay from '../../components/dialog/AnimatedOverlay.vue'
 import ContentCard from './components/content-card.vue'
+import PhoneConfirmDialog from './components/PhoneConfirmDialog.vue'
+import PhoneEditDialog from './components/PhoneEditDialog.vue'
+import SubMitSuccess from './components/SubMitSuccess.vue'
 import { usePreLeaveInfo } from '@/utils/hooks'
 
 const props = defineProps({
@@ -19,7 +22,7 @@ const props = defineProps({
   },
   type: {
     type: String,
-    default: '2'
+    default: '1'
   }
 })
 
@@ -30,7 +33,23 @@ const {
   configInfo,
 } = usePreLeaveInfo({ props })
 
-console.log(configInfo)
+const {
+  confirmPhoneDialog,
+  confirmContentText,
+  changePhoneDialog,
+  successCheckDialog,
+  dialogEvents,
+  checkPhonePass,
+} = usePhoneCheck({
+  configInfo,
+  props,
+  popupVisible: visible,
+})
+
+const config = {
+  configInfo,
+  props,
+}
 
 defineExpose({
   updateVisible
@@ -51,7 +70,18 @@ export default {
     @update:visible="updateVisible"
     @close="close"
   >
-    <ContentCard />
+    <ContentCard :config="config" />
+    <!-- 确认手机弹窗 -->
+    <PhoneConfirmDialog
+      :confirm-phone-dialog="confirmPhoneDialog"
+      :confirm-content-text="confirmContentText"
+    />
+    <!-- 修改手机号弹窗 -->
+    <PhoneEditDialog />
+    <!-- 提交成功弹窗 -->
+    <SubMitSuccess
+      :success-check-dialog="successCheckDialog"
+    />
   </AnimatedOverlay>
 </template>
 

+ 1 - 1
plugins/leave-source/src/utils/hooks.js

@@ -106,7 +106,7 @@ export function usePhoneCheck(options = {}) {
   const phone = ref(configInfo.phone)
   const source = computed(() => props.source)
 
-  const isLoginPhone = computed(() => configInfo.isCurrentPhone)
+  const isLoginPhone = computed(() => configInfo.isCurrentPhone || false)
 
   watch(() => configInfo.phone, (val) => {
     phone.value = val