Jelajahi Sumber

fix(reportProblems): 稳定上报提交流程并清理调试代码

增强问题上报的防重复提交、异常提示和手机号校验,解耦答复列表查询条件为当前登录用户,并移除无用调试/城运残留逻辑以降低维护成本。

Made-with: Cursor
haifeng.zhang 2 minggu lalu
induk
melakukan
edf7ebe90a
1 mengubah file dengan 87 tambahan dan 222 penghapusan
  1. 87 222
      src/subPages/pages/reportProblems/index.vue

+ 87 - 222
src/subPages/pages/reportProblems/index.vue

@@ -1,17 +1,13 @@
 <script lang="ts" setup>
-import { addQuestionReportData,REPORTDATA, getQuestionTypeList, pageQuestionReportData,getPerson } from '@/api/questionReqort'
-import { AddQuestionReportDataReq, PageQuestionReportDataReq, QuestionListRes, QuestionType, QuestionTypeListRes } from '@/api/questionReqort/types'
-import type { ApiResponse, PageResp } from '@/api/types'
+import { addQuestionReportData, getQuestionTypeList, pageQuestionReportData,getPerson } from '@/api/questionReqort'
+import { AddQuestionReportDataReq, PageQuestionReportDataReq, QuestionListRes, QuestionType } from '@/api/questionReqort/types'
 import { getCachedWecomVisitorProfile, getWecomInternalUser } from '@/api/wecom'
-import { computed, onMounted, ref, watch } from 'vue'
+import { onMounted, ref, watch } from 'vue'
 import GridAddress from '@/components/address/gridAddress/index.vue'
 import { showNotify } from 'vant'
-import dayjs from 'dayjs';
 import { onLoad } from '@dcloudio/uni-app'
-import useUserState from '@/store/userState'
 
 const active = ref(0)
-const userState = useUserState()
 
 interface ReportFormData extends AddQuestionReportDataReq {
   location?: string
@@ -48,7 +44,8 @@ const createInitialFormData = (): ReportFormData => ({
 
 const formData = ref<ReportFormData>(createInitialFormData())
 const range = ref<{ text: string; value: string }[]>([])
-const rangePerson = ref([]) as any
+const submitting = ref(false)
+const mobileRegex = /^1[3-9]\d{9}$/
 
 const rules = ref({
   questionType: [{ required: true, message: '请选择类型' }],
@@ -67,12 +64,14 @@ const handleAddressFinish = async(value: AddressSelection) => {
   formData.value.chargerCode = ''
   formData.value.addrName = value.selectedOptions[value.tabIndex]?.areaName || ''
   addressList.value = value
-  const { data } = await getPerson({parentCode:value.value})
-  personData.value = (data || []) as GridPerson[]
-  rangePerson.value = personData.value.map((item) => ({
-    text: item.areaName,
-    value: item.areaName,
-  }))
+  try {
+    const { data } = await getPerson({parentCode:value.value})
+    personData.value = (data || []) as GridPerson[]
+  } catch (e) {
+    personData.value = []
+    showNotify('获取网格员失败,请稍后重试')
+    console.error('获取网格员失败:', e)
+  }
 }
 
 /* 获取群主手机号 */
@@ -84,6 +83,7 @@ onLoad((option) => {
 })
 const ownerPhone = ref('')
 const visitorPhone = ref('')
+const listContactPerson = ref('')
 
 const fillVisitorName = () => {
   const profile = getCachedWecomVisitorProfile()
@@ -91,6 +91,7 @@ const fillVisitorName = () => {
 
   visitorPhone.value = profile.mobile || ''
   formData.value.contactPerson = profile.name
+  listContactPerson.value = profile.name
 }
 
 const fillVisitorPhone = () => {
@@ -115,6 +116,7 @@ const getOwnerPhone = async () => {
 }
 
 const submit = async () => {
+  if (submitting.value) return
   console.log(`output->formData.value`,formData.value)
   if (!formData.value.questionType) {
     showNotify('请选择问题类型')
@@ -132,80 +134,55 @@ const submit = async () => {
     showNotify('请输入联系人电话')
     return
   }
+  if (!mobileRegex.test(formData.value.contactPhone)) {
+    showNotify('请输入正确的手机号')
+    return
+  }
   if (!addressList.value || addressList.value.selectedOptions.length === 0) {
     showNotify('请选择所在地')
     return
   }
-  formData.value.chargerCode = personData.value.find(
-    item => item.areaName === formData.value.chargerName
-  )?.areaCode || '' // 添加兜底处理
-  formData.value.contactPersonPhone = formData.value.contactPhone || ''
-  console.log('formData.value',formData.value)
-  
-  /* 获取群主手机号(不阻塞流程,报错也继续执行) */
+  submitting.value = true
   try {
-    await getOwnerPhone();
-  } catch (e) {
-    console.error('获取群主手机号失败:', e);
-  }
-  const { data } = await addQuestionReportData({
-    ...formData.value,
-    ...(ownerPhone.value ? { ownerPhone: ownerPhone.value } : {}),
-    // personList:formData.value.person1+','+formData.value.person2,
-    streetCode: addressList.value.selectedOptions[1] ? addressList.value.selectedOptions[1].areaCode : '',
-    streetName: addressList.value.selectedOptions[1] ? addressList.value.selectedOptions[1].areaName : '',
-    communityCode: addressList.value.selectedOptions[2] ? addressList.value.selectedOptions[2].areaCode : '',
-    communityName: addressList.value.selectedOptions[2] ? addressList.value.selectedOptions[2].areaName : '',
-    grid: addressList.value.selectedOptions[3] ? addressList.value.selectedOptions[3].areaCode : '',
-    gridName: addressList.value.selectedOptions[3] ? addressList.value.selectedOptions[3].areaName : '',
-  })
-  if (data) {
-    uni.showToast({
-      title: '上报成功',
-      icon: 'success',
-      duration: 1000,
-    })
-    formData.value = createInitialFormData()
-    visitorPhone.value = ''
-    addressList.value = null
-    data.districtCode = '330205'
-    data.districtName = '江北区'
-    // reportCY(data)
-  }
-
-}
-
-// 上报到城运
-const reportCY = async (params:any) => {
-  const { data } = await REPORTDATA({
-    data:{
-      otherTaskNum:params.uuid.replace(/-/g,''),
-      // eventTitle:params.questionTitle,
-      eventDesc:params.questionContent,
-      eventTypeCode:'109000',
-      eventTypeName:'民事纠纷',
-      subTypeCode:'109002',
-      subTypeName:'邻里纠纷',
-      reportTime: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'),
-      reporter:params.contactPerson,
-      address:params.districtName+params.streetName+params.communityName,
-      
-      districtCode:'330205',
-      districtName:'江北区',
-      gridCode:params.grid,
-      gridName:params.gridName,
-      communityCode:params.communityCode,
-      communityName:params.communityName,
-      streetCode:params.streetCode,
-      streetName:params.streetName,
-    },
-    dataId:params.uuid.replace(/-/g,''),
-    dataType:'main',
-    timestamp:new Date().getTime(),
-  })
-  console.log(data)
-  if (data.code== '200'){
+    formData.value.chargerCode = personData.value.find(
+      item => item.areaName === formData.value.chargerName
+    )?.areaCode || '' // 添加兜底处理
+    formData.value.contactPersonPhone = formData.value.contactPhone || ''
+    console.log('formData.value',formData.value)
+
+    /* 获取群主手机号(不阻塞流程,报错也继续执行) */
+    try {
+      await getOwnerPhone();
+    } catch (e) {
+      console.error('获取群主手机号失败:', e);
+    }
 
+    const { data } = await addQuestionReportData({
+      ...formData.value,
+      ...(ownerPhone.value ? { ownerPhone: ownerPhone.value } : {}),
+      // personList:formData.value.person1+','+formData.value.person2,
+      streetCode: addressList.value.selectedOptions[1] ? addressList.value.selectedOptions[1].areaCode : '',
+      streetName: addressList.value.selectedOptions[1] ? addressList.value.selectedOptions[1].areaName : '',
+      communityCode: addressList.value.selectedOptions[2] ? addressList.value.selectedOptions[2].areaCode : '',
+      communityName: addressList.value.selectedOptions[2] ? addressList.value.selectedOptions[2].areaName : '',
+      grid: addressList.value.selectedOptions[3] ? addressList.value.selectedOptions[3].areaCode : '',
+      gridName: addressList.value.selectedOptions[3] ? addressList.value.selectedOptions[3].areaName : '',
+    })
+    if (data) {
+      uni.showToast({
+        title: '上报成功',
+        icon: 'success',
+        duration: 1000,
+      })
+      formData.value = createInitialFormData()
+      visitorPhone.value = ''
+      addressList.value = null
+    }
+  } catch (e) {
+    showNotify('提交失败,请稍后重试')
+    console.error('提交失败:', e)
+  } finally {
+    submitting.value = false
   }
 }
 
@@ -228,36 +205,6 @@ const listLoadVersion = ref(0)
 /** 合并并发 init,避免 watch 与重复进入导致多次 reset/请求交错 */
 let listInitPromise: Promise<void> | null = null
 
-/** 列表接口调试:最近一次请求参数与完整响应 */
-const showListRawJsonPopup = ref(false)
-const showApiFullUrlPopup = ref(false)
-const listLastReqParams = ref<PageQuestionReportDataReq | null>(null)
-const listLastApiResponse = ref<ApiResponse<PageResp<QuestionListRes>> | null>(null)
-
-const listReqParamsJson = computed(() => {
-  if (!listLastReqParams.value) return '{}'
-  return JSON.stringify(listLastReqParams.value, null, 2)
-})
-
-const listApiRawJson = computed(() => {
-  if (!listLastApiResponse.value) return '{}'
-  return JSON.stringify(listLastApiResponse.value, null, 2)
-})
-
-const httpsOrigin = computed(() => {
-  if (typeof window === 'undefined') return ''
-  const host = window.location.host || ''
-  return host ? `https://${host}` : ''
-})
-
-const listApiFullUrl = computed(() => `${httpsOrigin.value}/api/questionReport/pageQuestionReportData`)
-const detailApiFullUrl = computed(() => `${httpsOrigin.value}/api/questionReport/detailsQuestionReportData/{id}`)
-const currentPageUrl = computed(() => {
-  if (typeof window === 'undefined') return ''
-  return window.location.href || ''
-})
-const detailPageUrl = computed(() => `${httpsOrigin.value}/subPages/pages/reportProblems/detail?id={id}`)
-
 const resetQuestionList = () => {
   list.value = []
   pageInfo.value.pageNumber = 1
@@ -269,6 +216,11 @@ const resetQuestionList = () => {
 
 const questList = async () => {
   if (listRequesting.value || finished.value) return
+  if (!listContactPerson.value) {
+    finished.value = true
+    showNotify('未获取到当前登录用户信息,无法查询问题答复')
+    return
+  }
 
   const requestVersion = listLoadVersion.value
   listRequesting.value = true
@@ -278,13 +230,11 @@ const questList = async () => {
     const reqParams: PageQuestionReportDataReq = {
       pageNumber: currentPage,
       pageSize: pageInfo.value.pageSize,
-      contactPerson: formData.value.contactPerson || '',
+      contactPerson: listContactPerson.value,
     }
     const res = await pageQuestionReportData(reqParams)
     if (requestVersion !== listLoadVersion.value) return
 
-    listLastReqParams.value = reqParams
-    listLastApiResponse.value = res
     const records = res.data.records || []
 
     list.value = currentPage === 1 ? records : list.value.concat(records)
@@ -316,7 +266,7 @@ const handleGoDetail = (item: QuestionListRes) => {
 }
 
 const areaShow = ref(false)
-const hanleSelectArea = () => {
+const handleSelectArea = () => {
   areaShow.value = true
 }
 
@@ -329,7 +279,6 @@ const changeQuestionType = (e: any) => {
   formData.value.contactPersonPhone = contactPersonPhone
   addressList.value = null
   personData.value = []
-  rangePerson.value = []
   areaShow.value = false
 }
 
@@ -337,20 +286,26 @@ onMounted(async () => {
   fillVisitorName()
 
   // 问题类型下拉
-  const { data } = await getQuestionTypeList({
-    page: 1,
-    limit: 9999,
-    category: QuestionType.QUESTION,
-  })
-  if (data.records) {
-    range.value = data.records.map((item) => {
-      return {
-        text: item.typeName,
-        value: item.typeName,
-      }
+  try {
+    const { data } = await getQuestionTypeList({
+      page: 1,
+      limit: 9999,
+      category: QuestionType.QUESTION,
     })
-  } else {
+    if (data.records) {
+      range.value = data.records.map((item) => {
+        return {
+          text: item.typeName,
+          value: item.typeName,
+        }
+      })
+    } else {
+      range.value = []
+    }
+  } catch (e) {
     range.value = []
+    showNotify('获取问题类型失败,请稍后重试')
+    console.error('获取问题类型失败:', e)
   }
 })
 
@@ -386,17 +341,13 @@ watch(active, async (value) => {
           </uni-forms-item>
           <!-- 问题所在地 -->
           <uni-forms-item label="所在地" required name="addrName">
-            <uni-easyinput v-model="formData.addrName" placeholder="请选择所在地" @focus="hanleSelectArea"></uni-easyinput>
+            <uni-easyinput v-model="formData.addrName" placeholder="请选择所在地" @focus="handleSelectArea"></uni-easyinput>
             <GridAddress v-model="areaShow" @finish="handleAddressFinish"></GridAddress>
           </uni-forms-item>
           <!-- 详细地址-->
           <uni-forms-item label="详细位置" name="addrDetailName">
             <uni-easyinput v-model="formData.addrDetailName" placeholder="请输入"></uni-easyinput>
           </uni-forms-item>
-          <!-- 负责人下拉 -->
-          <!-- <uni-forms-item label="负责人" required name="person">
-            <uni-data-select v-model="formData.chargerName" :localdata="rangePerson"></uni-data-select>
-          </uni-forms-item> -->
           <!-- 联系人姓名 -->
           <uni-forms-item label="您的姓名" required name="contactPerson">
             <uni-easyinput v-model="formData.contactPerson" placeholder="请输入"></uni-easyinput>
@@ -408,15 +359,11 @@ watch(active, async (value) => {
             </view>
           </uni-forms-item>
         </uni-forms>
-        <van-button class="w-full mb-3" type="primary" @click="submit">提交</van-button>
+        <van-button class="w-full mb-3" type="primary" :loading="submitting" :disabled="submitting" @click="submit">提交</van-button>
       </view>
     </van-tab>
     <van-tab title="问题答复">
       <view class="tab-container">
-        <view class="mb-[8px]">
-          <van-button size="small" plain type="primary" @click="showListRawJsonPopup = true">查看接口原始JSON</van-button>
-          <van-button class="ml-[8px]" size="small" plain type="primary" @click="showApiFullUrlPopup = true">查看完整访问地址</van-button>
-        </view>
         <van-list
           v-model:loading="loading"
           :finished="finished"
@@ -443,52 +390,6 @@ watch(active, async (value) => {
             </view>
           </view>
         </van-list>
-        <van-popup
-          v-model:show="showListRawJsonPopup"
-          round
-          position="bottom"
-          :style="{ height: '75%' }"
-        >
-          <view class="json-popup">
-            <view class="json-title">请求参数</view>
-            <scroll-view scroll-y class="json-scroll json-scroll--small">
-              <text class="json-text">{{ listReqParamsJson }}</text>
-            </scroll-view>
-            <view class="json-title">列表接口完整JSON</view>
-            <scroll-view scroll-y class="json-scroll">
-              <text class="json-text">{{ listApiRawJson }}</text>
-            </scroll-view>
-          </view>
-        </van-popup>
-        <van-popup
-          v-model:show="showApiFullUrlPopup"
-          round
-          position="bottom"
-          :style="{ height: '55%' }"
-        >
-          <view class="json-popup">
-            <view class="json-title">当前HTTPS域名</view>
-            <scroll-view scroll-y class="json-scroll json-scroll--small">
-              <text class="json-text">{{ httpsOrigin || '当前环境未获取到浏览器域名' }}</text>
-            </scroll-view>
-            <view class="json-title">问题答复列表接口</view>
-            <scroll-view scroll-y class="json-scroll json-scroll--small">
-              <text class="json-text">{{ listApiFullUrl }}</text>
-            </scroll-view>
-            <view class="json-title">详情接口</view>
-            <scroll-view scroll-y class="json-scroll">
-              <text class="json-text">{{ detailApiFullUrl }}</text>
-            </scroll-view>
-            <view class="json-title">当前页面访问地址</view>
-            <scroll-view scroll-y class="json-scroll json-scroll--small">
-              <text class="json-text">{{ currentPageUrl || '当前环境未获取到页面地址' }}</text>
-            </scroll-view>
-            <view class="json-title">详情页访问地址</view>
-            <scroll-view scroll-y class="json-scroll">
-              <text class="json-text">{{ detailPageUrl }}</text>
-            </scroll-view>
-          </view>
-        </van-popup>
       </view>
     </van-tab>
   </van-tabs>
@@ -507,9 +408,6 @@ watch(active, async (value) => {
   box-sizing: border-box;
   display: flex;
   flex-direction: column;
-  > uni-view:first-child {
-    flex: 1;
-  }
 }
 
 .contact-phone-field {
@@ -546,6 +444,7 @@ watch(active, async (value) => {
       display: -webkit-box; /* 将对象作为弹性伸缩盒子模型显示 */
       -webkit-box-orient: vertical; /* 设置或检索伸缩盒对象的子元素的排列方式 */
       -webkit-line-clamp: 3; /* 限制在一个块元素显示的文本的行数 */
+      line-clamp: 3;
       overflow: hidden; /* 隐藏溢出的内容 */
     }
     .type {
@@ -554,38 +453,4 @@ watch(active, async (value) => {
   }
 }
 
-.json-popup {
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-  padding: 12px;
-}
-
-.json-title {
-  font-size: 16px;
-  font-weight: 500;
-  margin-bottom: 10px;
-}
-
-.json-scroll {
-  flex: 1;
-  overflow: hidden;
-  background: #f7f8fa;
-  border-radius: 8px;
-  padding: 12px;
-}
-
-.json-scroll--small {
-  flex: 0 0 auto;
-  max-height: 120px;
-  margin-bottom: 10px;
-}
-
-.json-text {
-  white-space: pre-wrap;
-  word-break: break-all;
-  font-size: 13px;
-  line-height: 20px;
-}
-
 </style>