Procházet zdrojové kódy

优化排序组件效果

shmily1213 před 4 týdny
rodič
revize
f40a114ed0

+ 1 - 1
src/components/ie-safe-toolbar/ie-safe-toolbar.vue

@@ -25,7 +25,7 @@ const props = defineProps({
   },
   bgColor: {
     type: String,
-    default: '#FFFFFF'
+    default: 'transparent'
   }
 });
 const minHeight = computed(() => {

+ 21 - 24
src/pagesMain/pages/me/components/me-menu.vue

@@ -64,26 +64,26 @@ type MenuItem = {
 };
 
 const menus = computed(() => [
-    {
-        name: '测评报告',
-        icon: '/static/personal/test_report.png',
-        pagePath: routes.testCenterList,
-    },
-    {
-        name: '我的收藏',
-        icon: '/static/personal/my_collected.png',
-        pagePath: routes.pageCollect,
-    },
-    {
-        name: '我的志愿表',
-        icon: '/static/personal/my_simulated.png',
-        pagePath: userStore.isVHS ? routes.VHSList : routes.voluntaryList,
-    },
-    {
-        name: '绑定会员卡',
-        icon: '/static/personal/bind_card.png',
-        pagePath: routes.pageCardVerify,
-    }
+  {
+    name: '测评报告',
+    icon: '/static/personal/test_report.png',
+    pagePath: routes.testCenterList,
+  },
+  {
+    name: '我的收藏',
+    icon: '/static/personal/my_collected.png',
+    pagePath: routes.pageCollect,
+  },
+  {
+    name: '我的志愿表',
+    icon: '/static/personal/my_simulated.png',
+    pagePath: userStore.isVHS ? routes.VHSList : routes.voluntaryList,
+  },
+  {
+    name: '绑定会员卡',
+    icon: '/static/personal/bind_card.png',
+    pagePath: routes.pageCardVerify,
+  }
 ]);
 const cellStyle = {
   padding: '30rpx 30rpx'
@@ -114,10 +114,7 @@ const handleQuestion = async () => {
   });
 }
 const handleLogout = async () => {
-  const confirm = await userStore.askLogout();
-  if (confirm) {
-
-  }
+  await userStore.askLogout();
 }
 const handlePhone = async () => {
   userStore.callContactPhone();

+ 1 - 1
src/pagesOther/components/ie-condition-dropdown/ie-condition-dropdown-popup.vue

@@ -59,7 +59,7 @@ const relTop = computed(() => baseBottom.value - baseTop.value - 1)
 // #endif
 // #ifdef MP-WEIXIN
 // TODO:小程序兼容性问题
-const refTop = ref(0)
+const relTop = uni.getSystemInfoSync().statusBarHeight
 // #endif
 
 const handleReset = () => {

+ 3 - 0
src/pagesOther/pages/university/index/components/plus/college-conditions-location.vue

@@ -103,6 +103,9 @@ const initValue = () => {
     } else {
       currentIndex.value = 0;
     }
+  } else {
+    selected.value = [];
+    currentIndex.value = 0;
   }
 }
 

+ 2 - 2
src/pagesOther/pages/vhs/index/components/course-selector.vue

@@ -3,8 +3,8 @@
         <view class="pl-20">
             专业类别
         </view>
-        <view class="py-15 flex gap-20">
-            <uv-tags size="large" type="primary" shape="circle" icon="lock" plain plain-fill
+        <view class="py-15 flex gap-20 text-[15px]">
+            <uv-tags size="medium" type="primary" shape="circle" icon="lock" plain plain-fill
                      :text="currentUser.examMajorName"/>
         </view>
     </view>

+ 3 - 3
src/pagesOther/pages/vhs/index/components/score-form.vue

@@ -5,13 +5,13 @@
         <course-selector/>
         <uv-line margin="15px 0 0 0"/>
         <uv-input v-model="model.score" :disabled="isScoreLocked" placeholder="请输入您的分数"
-                  v-bind="inputCommon">
+                  v-bind="inputCommon" placeholderClass="text-[15px]" font-size="15px">
             <template #prefix>您的分数:</template>
         </uv-input>
-        <uv-input v-if="false" v-model="model.rank.lowestRank" disabled v-bind="inputCommon">
+        <uv-input v-if="false" v-model="model.rank.lowestRank" disabled v-bind="inputCommon" placeholderClass="text-[15px]" font-size="15px">
             <template #prefix>匹配位次:</template>
         </uv-input>
-        <uv-input v-model="model.seatInput" placeholder="输入成绩单位次" v-bind="inputCommon">
+        <uv-input v-model="model.seatInput" placeholder="输入成绩单位次" v-bind="inputCommon" placeholderClass="text-[15px]" font-size="15px">
             <template #prefix>填写位次:</template>
         </uv-input>
         <view class="font-[PingFang] text-content text-2xs mt-20">

+ 5 - 1
src/pagesOther/pages/vhs/index/components/vhs-majors-draggable-list.vue

@@ -36,7 +36,7 @@ const emits = defineEmits<{
   (e: "change", majors: VHS.VoluntaryMajor[]): void;
 }>();
 const touchHandle = ref(false)
-
+const dragRef = ref();
 const handleDragStart = () => {
   touchHandle.value = true;
   // refresherEnabled.value = false;
@@ -56,5 +56,9 @@ const handleDelete = (major: VHS.VoluntaryMajor) => {
 const toFixedLen = (i: number, len: number = 1) => {
   return String(i + 1).padStart(len, "0");
 }
+const refresh = () => {
+  dragRef.value?.refresh();
+}
+defineExpose({ refresh });
 </script>
 <style lang="scss" scoped></style>

+ 9 - 1
src/pagesOther/pages/vhs/index/components/voluntary-cart-popup.vue

@@ -62,7 +62,7 @@
                             <uv-button type="primary" size="mini" plain shape="circle" icon="trash"
                                        icon-color="primary" @click="handleRemoveAll(college)"/>
                         </view>
-                        <vhs-majors-draggable-list :majors="getSelectedSortedMajors(college)"
+                        <vhs-majors-draggable-list ref="draggableListRef" :majors="getSelectedSortedMajors(college)"
                                                    @delete="handleMajorDelete($event, college)"
                                                    @change="handleDragComplete($event, college)" />
                     </view>
@@ -198,9 +198,17 @@ const handleSave = async () => {
     await save(isMock.value)
 }
 
+const draggableListRef = ref();
 const open = () => {
     localPageNum.value = 1
     popup.value.open()
+    setTimeout(() => {
+      nextTick(() => {
+        draggableListRef.value?.forEach(item => {
+          item?.refresh();
+        });
+      });
+    }, 300)
 }
 
 const close = () => {

+ 7 - 5
src/pagesOther/pages/voluntary/index/index.vue

@@ -93,11 +93,13 @@ const handleSubmit = async () => {
     }
     if (!target.value.universityId || !target.value.majorId) return uni.$ie.showToast('请选择院校专业')
     if (!rules.value.length) return uni.$ie.showToast('由于官方未公布历年录取分数或计划变更,暂时无法计算录取概率')
-    await form.value?.validate()
-    // make request
-    const {data: result} = await postRenderRules(target.value, model.value)
-    const bigData: VoluntaryDto = {target: target.value, rules: rules.value, model: model.value, result}
-    transferTo(routes.voluntaryResult, {bigData})
+    try {
+      await form.value?.validate()
+      // make request
+      const { data: result } = await postRenderRules(target.value, model.value)
+      const bigData: VoluntaryDto = { target: target.value, rules: rules.value, model: model.value, result }
+      transferTo(routes.voluntaryResult, { bigData })
+    } catch (error) { }
 }
 
 provide(VOLUNTARY_TARGET, target)

+ 3 - 3
src/pagesSystem/pages/bind-teacher-profile/bind-teacher-profile.vue

@@ -4,7 +4,7 @@
     <uv-form labelPosition="left" :model="examTypeForm" labelWidth="70px" ref="formRef">
       <content-card title="个人信息">
         <uv-form-item label="姓名" prop="name" borderBottom required>
-          <uv-input v-model="form.nickName" border="none" placeholder="请输入姓名" placeholderClass="text-30"
+          <uv-input v-model="form.nickName" border="none" placeholder="请输入姓名" placeholderClass="text-[15px]"
             font-size="15px" :custom-style="customStyle">
           </uv-input>
         </uv-form-item>
@@ -81,13 +81,13 @@
 
       <content-card v-if="showSchoolInfo" title="学校信息">
         <uv-form-item label="学校名称" prop="form.campusName" borderBottom>
-          <uv-input v-model="form.campusName" border="none" placeholder="" placeholderClass="text-30" font-size="15px"
+          <uv-input v-model="form.campusName" border="none" placeholder="" placeholderClass="text-[15px]" font-size="15px"
             :custom-style="customStyle" readonly>
           </uv-input>
           <ie-image slot="right" src="/static/image/icon-lock.png" custom-class="w-24 h-30" mode="aspectFill" />
         </uv-form-item>
         <uv-form-item label="所在班级" prop="form.campusClassName">
-          <uv-input v-model="form.campusClassName" border="none" placeholder="" placeholderClass="text-30"
+          <uv-input v-model="form.campusClassName" border="none" placeholder="" placeholderClass="text-[15px]"
             font-size="15px" :custom-style="customStyle" readonly>
           </uv-input>
           <ie-image slot="right" src="/static/image/icon-lock.png" custom-class="w-24 h-30" mode="aspectFill" />

+ 46 - 8
src/uni_modules/lime-drag/components/l-drag/l-drag.vue

@@ -19,7 +19,7 @@
 				:y="item.y"
 				:friction="friction"
 				:damping="damping"
-				:animation="animation"
+				:animation="getItemAnimation(oindex)"
 				:disabled="isDisabled || props.disabled"
 				@touchstart="touchStart" 
 				@change="touchMove" 
@@ -84,7 +84,10 @@
 				/** 旧视图下标 */
 				oldindex: -1,
 				/** 上次原始下标 */
-				lastindex: -1
+				lastindex: -1,
+				/** 当前拖拽坐标(用于小程序 touchend 防回闪) */
+				x: 0,
+				y: 0
 			})
 			
 			const ghostEl = reactive({
@@ -222,13 +225,15 @@
 				active.value = oindex 
 				// 选中项的当前下标
 				dragEl.index = dragEl.oldindex = target.index
+				dragEl.x = target.x || 0
+				dragEl.y = target.y || 0
 				ghostEl.x = target.x||0
 				ghostEl.y = target.y||0
 				dragEl.content = ghostEl.content = target.content
 			}
 			
 			const touchEnd = (e: any) => {
-				setTimeout(() => {
+				const finalize = () => {
 					if(e.target.dataset.remove || active.value==-1) return
 					setDisabled(e, true)
 					isDrag.value = false
@@ -246,8 +251,20 @@
 							isEmit && emitting()
 						})
 					})
-				},80)
-				
+				}
+				// 小程序下 movable-view 在 touchend 会先回到绑定的 x/y,
+				// 先把当前拖拽坐标写回,避免“先回原位”的闪现,同时保留动画
+				// #ifdef MP-WEIXIN
+				const last = cloneList.value[active.value]
+				if (last) {
+					last.x = dragEl.x
+					last.y = dragEl.y
+				}
+				finalize()
+				// #endif
+				// #ifndef MP-WEIXIN
+				setTimeout(finalize, 80)
+				// #endif
 			}
 			const emitting = () => {
 				const clone = [...cloneList.value].sort((a, b) => a.index - b.index)//.map(item => ref(item.content))
@@ -264,6 +281,16 @@
 				// #endif
 				if(oindex != active.value) return
 				const {x, y} = e.detail
+				// 小程序下同步更新绑定坐标,避免 touchend 回弹闪现
+				// #ifdef MP-WEIXIN
+				const activeItem = cloneList.value[active.value]
+				if (activeItem) {
+					activeItem.x = x
+					activeItem.y = y
+				}
+				// #endif
+				dragEl.x = x
+				dragEl.y = y
 				const centerX = x + girdWidth.value / 2
 				const centerY = y + gridHeight.value / 2
 				for (let i = 0; i < cloneList.value.length; i++) {
@@ -303,7 +330,9 @@
 				// 距离
 				let distance = start - toIndex
 				// 找到区间所有的项
-				while(distance) {
+				let steps = 0
+				const stepLimit = isDrag.value ? 1 : Number.POSITIVE_INFINITY
+				while(distance && steps < stepLimit) {
 					distance += speed
 					// 目标
 					const target = isDrag.value ? (dragEl.index += speed)  : (start += speed) 
@@ -321,7 +350,7 @@
 					targetEl.oldindex = targetEl.index
 					targetEl.index = lastIndex
 					activeEl.oldindex = activeEl.index //oIndex
-					activeEl.index = toIndex
+					activeEl.index = target
 					// 到达终点,如果是拖拽则不处理
 					if(!distance && !isDrag.value) {
 						const rect = gridRects[toIndex]
@@ -333,6 +362,7 @@
 							emitting()
 						}
 					}
+					steps++
 				}
 			}
 			/**
@@ -461,6 +491,12 @@
 			onUnmounted(clear)
 			watch(() => props.list, init)
 			
+			const getItemAnimation = (oindex: number) => {
+				// 拖拽中的项不做动画,避免小程序抖动
+				if (isDrag.value && oindex === active.value) return false
+				return animation.value
+			}
+			
 			// #ifdef VUE3
 			expose({
 				remove,
@@ -469,7 +505,8 @@
 				push,
 				unshift,
 				shift,
-				pop
+				pop,
+				refresh: getRect
 			})
 			// #endif
 			return {
@@ -489,6 +526,7 @@
 				
 				active,
 				animation,
+				getItemAnimation,
 				
 				afterEl,
 				ghostEl,

+ 10 - 9
src/utils/uni-tool.ts

@@ -100,15 +100,14 @@ const tool: IeTool = {
   loading: false,
   loadingStartTime: 0,
   minLoadingTime: 500, // 最小显示时间,单位毫秒
-  showToast(title: string = '') {
+  async showToast(title: string = '') {
     // 先立即隐藏,避免上一个 toast存在导致下次的 toast 很快关闭
     uni.hideToast();
-    setTimeout(() => {
-      uni.showToast({
-        title,
-        icon: 'none'
-      });
-    }, 50);
+    await sleep(100);
+    uni.showToast({
+      title,
+      icon: 'none'
+    });
   },
   showSuccess(title: string = '') {
     uni.showToast({
@@ -175,7 +174,7 @@ const tool: IeTool = {
         success: (res) => {
           /* 这里不要动,就是这样的。形成await showConfirm的效果 2026.1.13 */
           /* 如果有必须接收true/false的写法,请使用showModal */
-          if(res.confirm)(resolve(true))
+          if (res.confirm) (resolve(true))
           else reject(false)
         },
         fail: reject
@@ -225,5 +224,7 @@ const tool: IeTool = {
     // #endif
   }
 };
-
+const sleep = (ms: number) => {
+  return new Promise(resolve => setTimeout(resolve, ms));
+}
 export default tool;