From 8e9c8f51dda9a0745aecedc54a5701b32d14a9e2 Mon Sep 17 00:00:00 2001
From: chaorenluo <1243357953@qq.com>
Date: Tue, 5 Nov 2024 13:55:11 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=87=E7=94=A8=E7=AC=AC=E4=B8=80=E7=89=88pi?=
=?UTF-8?q?cker?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/package.json | 1 +
.../pages/edit/components/Picker/event.ts | 24 +
.../pages/edit/components/Picker/index.vue | 614 +++++-------------
.../pages/edit/components/Picker/list.ts | 145 +++++
.../edit/components/Picker/pickerHeader.vue | 83 ---
.../edit/components/Picker/pickerList.vue | 250 -------
.../pages/edit/components/Picker/utils.ts | 29 -
.../MultilevelModule/BaseMultilevel/index.vue | 11 +-
web/src/render/main.js | 1 +
9 files changed, 353 insertions(+), 805 deletions(-)
create mode 100644 web/src/management/pages/edit/components/Picker/event.ts
create mode 100644 web/src/management/pages/edit/components/Picker/list.ts
delete mode 100644 web/src/management/pages/edit/components/Picker/pickerHeader.vue
delete mode 100644 web/src/management/pages/edit/components/Picker/pickerList.vue
delete mode 100644 web/src/management/pages/edit/components/Picker/utils.ts
diff --git a/web/package.json b/web/package.json
index f9060096..9022a32d 100644
--- a/web/package.json
+++ b/web/package.json
@@ -22,6 +22,7 @@
"axios": "^1.4.0",
"clipboard": "^2.0.11",
"crypto-js": "^4.2.0",
+ "default-passive-events": "^2.0.0",
"echarts": "^5.5.0",
"element-plus": "^2.8.3",
"lodash-es": "^4.17.21",
diff --git a/web/src/management/pages/edit/components/Picker/event.ts b/web/src/management/pages/edit/components/Picker/event.ts
new file mode 100644
index 00000000..b9a041a5
--- /dev/null
+++ b/web/src/management/pages/edit/components/Picker/event.ts
@@ -0,0 +1,24 @@
+
+interface IEvent {
+ handleConfirm: () => void,
+ handleCancel: () => void
+}
+
+const useEvent = ({ emit, ctx }: any): IEvent => {
+ const handleConfirm = () => {
+ emit('confirm', ctx.list[ctx.index])
+ emit('update:modelValue', false)
+ }
+
+ const handleCancel = () => {
+ emit('update:modelValue', false)
+ emit('cancel', false)
+ }
+
+ return {
+ handleConfirm,
+ handleCancel
+ }
+}
+
+export default useEvent
diff --git a/web/src/management/pages/edit/components/Picker/index.vue b/web/src/management/pages/edit/components/Picker/index.vue
index 2c69dab2..9766eefa 100644
--- a/web/src/management/pages/edit/components/Picker/index.vue
+++ b/web/src/management/pages/edit/components/Picker/index.vue
@@ -1,468 +1,206 @@
-
-
-
-
-
+
\ No newline at end of file
+
+.x-picker__content-item {
+ height: 40px;
+ line-height: 40px;
+ transition: color .5s;
+ text-align: center
+}
+
+.slide-picker-enter-active,
+.slide-picker-leave-active {
+ transition: all .5s;
+}
+
+.slide-picker-enter-from,
+.slide-picker-leave-to {
+ transform: translateY(100%);
+}
+
+
diff --git a/web/src/management/pages/edit/components/Picker/list.ts b/web/src/management/pages/edit/components/Picker/list.ts
new file mode 100644
index 00000000..0d7b0289
--- /dev/null
+++ b/web/src/management/pages/edit/components/Picker/list.ts
@@ -0,0 +1,145 @@
+import { ref, computed } from 'vue'
+import type { Ref } from 'vue'
+
+interface IList {
+ box: Ref,
+ list: Ref>,
+ getOffsetY: any,
+ getStyle: any,
+ handleMove: (e: TouchEvent) => void,
+ handleStart: (e: TouchEvent) => void,
+ handleEnd: (e: TouchEvent) => void,
+ goItem: (idx: number) => void,
+ resetData: () => void,
+ index: Ref,
+ isTouch:boolean
+}
+
+const useList = (props: any): IList => {
+ const colors = ['gray', '#ccc', '#ddd', '#eee']
+ const scales = [.96, .9, .88, .84]
+ const isTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0
+ let startY: number, activeIndex = 0, isDragging = false
+ const box = ref()
+ const offY = ref()
+ const index = ref(0)
+ const list = ref(props.list)
+ const getStyle = (idx: number) => {
+ let color = '#000', scale = 1
+ const len = colors.length - 1
+ if (idx > activeIndex) {
+ const _idx = idx - activeIndex > len ? len : idx - activeIndex - 1
+ color = colors[_idx]
+ scale = scales[_idx]
+ } else if (idx < activeIndex) {
+ const _idx = activeIndex - idx > len ? len : activeIndex - idx - 1
+ color = colors[_idx]
+ scale = scales[_idx]
+ }
+ return { color, transform: `scale(${scale})` }
+ }
+
+ // 节流
+ const throttle = function (callback: any, delay = 20) {
+ let timer: any = null
+ return function (args: any) {
+ if (timer) {
+ return
+ }
+ timer = setTimeout(() => {
+ callback(args)
+ timer = null
+ }, delay)
+ }
+ }
+
+ // 移动的实现
+ const move = throttle((e: any) => {
+ const clientY = e.touches ? e.touches[0].clientY : e.clientY;
+ offY.value = clientY - startY
+ if (offY.value > 40) {
+ offY.value = 40
+ } else if (offY.value < -box.value.offsetHeight - 40) {
+ offY.value = -box.value.offsetHeight - 40
+ }
+ // 计算当前位置的就近下标
+ index.value = Math.abs(Math.ceil(offY.value / 40))
+ // 判断顶部和底部的一个界限,然后做一个位置的重置
+ if (index.value <= 0 || offY.value > 0) {
+ index.value = 0
+ } else if (index.value > list.value.length - 1 || offY.value < -box.value.offsetHeight - 18) {
+ index.value = list.value.length - 1
+ }
+ activeIndex = index.value
+ })
+
+ const goItem = (idx: number) => {
+ index.value = idx;
+ activeIndex = idx;
+ }
+
+ const resetData = () => {
+ startY = 0;
+ activeIndex = 0
+ index.value = 0
+ box.value = null;
+ offY.value = null;
+ }
+
+ const handleStart = (e: MouseEvent | TouchEvent) => {
+ isDragging = true
+ const transform = box.value.style.transform
+ transform.match(/,(.*)px/)
+ const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY
+ startY = clientY - Number(RegExp.$1)
+
+ document.addEventListener('mousemove', handleMove)
+ document.addEventListener('mouseup', handleEnd)
+
+ }
+
+ const handleMove = (e: MouseEvent | TouchEvent) => {
+ if (isDragging) {
+ move(e)
+ }
+ }
+
+ const handleEnd = () => {
+ // 重置当前位置,加setTimeout避免出现Bug
+ isDragging = false
+ setTimeout(() => {
+ offY.value = -index.value * 40 - 18
+ }, 100)
+ document.removeEventListener('mousemove', handleMove)
+ document.removeEventListener('mouseup', handleEnd)
+ }
+
+ const getOffsetY = computed(() => {
+ if (typeof offY.value === 'number') {
+ return {
+ transform: `translate(-50%, ${offY.value}px)`
+ }
+ } else {
+ return {
+ transform: 'translate(-50%, -18px)'
+ }
+ }
+ })
+
+ return {
+ box,
+ list,
+ getOffsetY,
+ getStyle,
+ handleMove,
+ handleStart,
+ handleEnd,
+ goItem,
+ resetData,
+ index,
+ isTouch
+ }
+}
+
+export default useList
+
diff --git a/web/src/management/pages/edit/components/Picker/pickerHeader.vue b/web/src/management/pages/edit/components/Picker/pickerHeader.vue
deleted file mode 100644
index ad4ca08e..00000000
--- a/web/src/management/pages/edit/components/Picker/pickerHeader.vue
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/web/src/management/pages/edit/components/Picker/pickerList.vue b/web/src/management/pages/edit/components/Picker/pickerList.vue
deleted file mode 100644
index da66289b..00000000
--- a/web/src/management/pages/edit/components/Picker/pickerList.vue
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/web/src/management/pages/edit/components/Picker/utils.ts b/web/src/management/pages/edit/components/Picker/utils.ts
deleted file mode 100644
index 5502f1b3..00000000
--- a/web/src/management/pages/edit/components/Picker/utils.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-export const DEFTAULT_ITEM_HEIGHT = 44
-
-// 兼容pc 移动端
-export const HAS_TOUCH = 'ontouchstart' in window
-export const START_EVENT = HAS_TOUCH ? 'touchstart' : 'mousedown'
-export const MOVE_EVENT = HAS_TOUCH ? 'touchmove' : 'mousemove'
-export const END_EVENT = HAS_TOUCH ? 'touchend' : 'mouseup'
-
-export const getClient = (e:any) => {
- const clientX = HAS_TOUCH ? e.changedTouches[0].clientX : e.clientX
- const clientY = HAS_TOUCH ? e.changedTouches[0].clientY : e.clientY
- return {
- x: clientX,
- y: clientY
- }
-}
-
-export const isPC = () => {
- const userAgentInfo = navigator.userAgent
- const Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod']
- let flag = true
- for (let v = 0; v < Agents.length; v++) {
- if (userAgentInfo.indexOf(Agents[v]) > 0) {
- flag = false
- break
- }
- }
- return flag
-}
\ No newline at end of file
diff --git a/web/src/materials/questions/widgets/MultilevelModule/BaseMultilevel/index.vue b/web/src/materials/questions/widgets/MultilevelModule/BaseMultilevel/index.vue
index 0522cce4..68db39f4 100644
--- a/web/src/materials/questions/widgets/MultilevelModule/BaseMultilevel/index.vue
+++ b/web/src/materials/questions/widgets/MultilevelModule/BaseMultilevel/index.vue
@@ -23,8 +23,8 @@
-
+
@@ -105,8 +105,8 @@ const handleChange = async(val,i) => {
}
const onConfirm = (val) => {
- valList.value[pickIndex.value] = val[0];
- handleChange(val[0], pickIndex.value);
+ valList.value[pickIndex.value] = val;
+ handleChange(val, pickIndex.value);
pickIndex.value=-1
}
const onCancel = () => {
@@ -115,12 +115,13 @@ const onCancel = () => {
const showPickPop = (list, index) => {
pickPop.value = true;
- listPop.value = [list];
+ listPop.value = list;
pickIndex.value = index
}
const updateEquipment = () => {
isMobile.value = isInMobile()
+ pickPop.value = false
}
onMounted(() => {
diff --git a/web/src/render/main.js b/web/src/render/main.js
index ca68f229..e097d4ca 100644
--- a/web/src/render/main.js
+++ b/web/src/render/main.js
@@ -3,6 +3,7 @@ import App from './App.vue'
import EventBus from './utils/eventbus'
import router from './router'
import { createPinia } from 'pinia'
+import 'default-passive-events'
const app = createApp(App)
const pinia = createPinia()