Merge branch 'dev'

This commit is contained in:
zyronon 2024-04-23 17:36:18 +08:00
commit 5007e88093
27 changed files with 504 additions and 301 deletions

View File

@ -9,3 +9,4 @@
- 双指缩放 - 双指缩放
- AutoInput组件在真机上无法输入 - AutoInput组件在真机上无法输入
- 真机上100vh显示异常的问题

4
env.d.ts vendored
View File

@ -3,6 +3,10 @@
declare const LATEST_COMMIT_HASH: string declare const LATEST_COMMIT_HASH: string
declare global { declare global {
interface Window {
isMoved: boolean
}
interface Navigator { interface Navigator {
control: any control: any
webkitGetUserMedia: any webkitGetUserMedia: any

View File

@ -137,6 +137,9 @@
}, },
"interact_info": { "liked_count": "2147", "liked": false }, "interact_info": { "liked_count": "2147", "liked": false },
"cover": { "url_default": "daZ662BX0lVMTq0Y6hIwR.png" }, "cover": { "url_default": "daZ662BX0lVMTq0Y6hIwR.png" },
"image_list": [
{ "info_list": [{ "url": "daZ662BX0lVMTq0Y6hIwR.png" }] }
],
"type": "normal", "type": "normal",
"display_title": "无所谓了,互联网没有我在乎的人" "display_title": "无所谓了,互联网没有我在乎的人"
}, },
@ -176,7 +179,10 @@
"nickname": "芙•" "nickname": "芙•"
}, },
"interact_info": { "liked": false, "liked_count": "1966" }, "interact_info": { "liked": false, "liked_count": "1966" },
"cover": { "url_default": "4a4TtExpq7RXnKK3hylKU.png" } "cover": { "url_default": "4a4TtExpq7RXnKK3hylKU.png" },
"image_list": [
{ "info_list": [{ "url": "4a4TtExpq7RXnKK3hylKU.png" }] }
]
}, },
"track_id": "2d0udv0xvhqne0t0nmd83", "track_id": "2d0udv0xvhqne0t0nmd83",
"ignore": false, "ignore": false,
@ -233,6 +239,9 @@
}, },
"interact_info": { "liked": false, "liked_count": "1005" }, "interact_info": { "liked": false, "liked_count": "1005" },
"cover": { "url_default": "dg16eh25m2SSI9Hc1fJuE.png" }, "cover": { "url_default": "dg16eh25m2SSI9Hc1fJuE.png" },
"image_list": [
{ "info_list": [{ "url": "dg16eh25m2SSI9Hc1fJuE.png" }] }
],
"type": "normal", "type": "normal",
"display_title": "拍旗袍没人看 办公室随手拍就有流量是吧" "display_title": "拍旗袍没人看 办公室随手拍就有流量是吧"
}, },
@ -321,7 +330,10 @@
"nick_name": "林木婷子" "nick_name": "林木婷子"
}, },
"interact_info": { "liked": false, "liked_count": "2700" }, "interact_info": { "liked": false, "liked_count": "2700" },
"cover": { "url_default": "z-XSh-g9MhKpYrFDHcxQT.png" } "cover": { "url_default": "z-XSh-g9MhKpYrFDHcxQT.png" },
"image_list": [
{ "info_list": [{ "url": "z-XSh-g9MhKpYrFDHcxQT.png" }] }
]
}, },
"track_id": "2d0udv0xvhqne0t0nmd83" "track_id": "2d0udv0xvhqne0t0nmd83"
}, },
@ -629,7 +641,10 @@
"user_id": "5bf37f6651783a194c1e1da2" "user_id": "5bf37f6651783a194c1e1da2"
}, },
"interact_info": { "liked": false, "liked_count": "119" }, "interact_info": { "liked": false, "liked_count": "119" },
"cover": { "url_default": "UaxqkI4aZ5LDu7k8KLw48.png" } "cover": { "url_default": "UaxqkI4aZ5LDu7k8KLw48.png" },
"image_list": [
{ "info_list": [{ "url": "UaxqkI4aZ5LDu7k8KLw48.png" }] }
]
} }
}, },
{ {
@ -888,6 +903,7 @@
}, },
"interact_info": { "liked": false, "liked_count": "1786" }, "interact_info": { "liked": false, "liked_count": "1786" },
"cover": { "url_default": "n0SAcEY5gLucU7Ik7yP2P.png" }, "cover": { "url_default": "n0SAcEY5gLucU7Ik7yP2P.png" },
"image_list": [{ "info_list": [{ "url": "n0SAcEY5gLucU7Ik7yP2P.png" }] }],
"type": "normal" "type": "normal"
}, },
"track_id": "2d0udv0xvhqne0t0nmd83", "track_id": "2d0udv0xvhqne0t0nmd83",
@ -936,6 +952,9 @@
"model_type": "note", "model_type": "note",
"note_card": { "note_card": {
"cover": { "url_default": "Sf5mzf68e2GwZHZv7h1G2.png" }, "cover": { "url_default": "Sf5mzf68e2GwZHZv7h1G2.png" },
"image_list": [
{ "info_list": [{ "url": "Sf5mzf68e2GwZHZv7h1G2.png" }] }
],
"type": "normal", "type": "normal",
"display_title": "行吧,我重发 ", "display_title": "行吧,我重发 ",
"user": { "user": {

Binary file not shown.

View File

@ -6,16 +6,17 @@
</keep-alive> </keep-alive>
</transition> </transition>
</router-view> </router-view>
<BaseMask v-if="!isMobile" /> <BaseMask v-if="!isMobile" @click="isMobile = true" />
<div v-if="!isMobile" class="guide"> <div v-if="!isMobile" class="guide">
<Icon icon="mynaui:danger-triangle" /> <Icon class="danger" icon="mynaui:danger-triangle" />
<div class="txt"> <Icon class="close" icon="simple-line-icons:close" @click="isMobile = true" />
<h2>切换至手机模式才可正常使用</h2> <div class="txt">
<h3>1. F12 调出控制台</h3> <h2>切换至手机模式获取最佳体验</h2>
<h3>2. Ctrl+Shift+M或点击下面图标</h3> <h3>1. F12 调出控制台</h3>
</div> <h3>2. Ctrl+Shift+M或点击下面图标</h3>
<img src="@/assets/img/guide.png" alt="" />
</div> </div>
<img src="@/assets/img/guide.png" alt="" />
</div>
<Call /> <Call />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -92,6 +93,15 @@ onMounted(() => {
font-size: 14rem; font-size: 14rem;
} }
@media screen and (min-width: 500px) {
#app {
width: 500px !important;
position: relative;
left: 50%;
transform: translateX(-50%);
}
}
.guide { .guide {
color: white; color: white;
z-index: 999; z-index: 999;
@ -104,12 +114,21 @@ onMounted(() => {
overflow: hidden; overflow: hidden;
text-align: center; text-align: center;
svg { .danger {
margin-top: 10rem; margin-top: 10rem;
font-size: 40rem; font-size: 40rem;
color: red; color: red;
} }
.close {
cursor: pointer;
font-size: 18rem;
color: white;
position: absolute;
right: 15rem;
top: 15rem;
}
.txt { .txt {
text-align: left; text-align: left;
padding: 0 24rem; padding: 0 24rem;

View File

@ -128,6 +128,7 @@ export default {
} }
.add-ctn { .add-ctn {
cursor: pointer;
@height: 27rem; @height: 27rem;
@width: 36rem; @width: 36rem;
height: @height; height: @height;
@ -147,6 +148,8 @@ export default {
} }
span { span {
cursor: pointer;
font-weight: bold; font-weight: bold;
opacity: 0.7; opacity: 0.7;

View File

@ -87,11 +87,12 @@ function getMonth(time) {
<style scoped lang="less"> <style scoped lang="less">
.posters { .posters {
display: grid; display: grid;
grid-template-columns: 33.33vw 33.33vw 33.33vw; grid-template-columns: 33.33% 33.33% 33.33%;
} }
.poster-item { .poster-item {
height: calc(33.33vw * 1.2); height: 200rem;
max-height: calc(33.33vw * 1.2);
border: 0.5px solid black; border: 0.5px solid black;
overflow: hidden; overflow: hidden;
position: relative; position: relative;

View File

@ -123,6 +123,7 @@ export default {
@import '../assets/less/index'; @import '../assets/less/index';
.scroll-wrapper { .scroll-wrapper {
touch-action: pan-y;
overflow: auto; overflow: auto;
.scroll-content { .scroll-content {

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="UserPanel" @scroll="scroll" ref="page"> <div id="UserPanel" @scroll="scroll" @dragstart="(e) => Utils.$stopPropagation(e)" ref="page">
<div ref="float" class="float" :class="state.floatFixed ? 'fixed' : ''"> <div ref="float" class="float" :class="state.floatFixed ? 'fixed' : ''">
<div class="left"> <div class="left">
<Icon @click="emit('back')" class="icon" icon="eva:arrow-ios-back-fill" /> <Icon @click="emit('back')" class="icon" icon="eva:arrow-ios-back-fill" />
@ -405,6 +405,7 @@ function touchEnd() {
} }
#UserPanel { #UserPanel {
touch-action: pan-y;
position: fixed; position: fixed;
background: var(--color-user); background: var(--color-user);
height: 100%; height: 100%;
@ -500,7 +501,7 @@ function touchEnd() {
grid-template-columns: 33.33% 33.33% 33.33%; grid-template-columns: 33.33% 33.33% 33.33%;
.item { .item {
height: calc(33.33vw * 1.3); height: calc(33.33% * 1.3);
padding: 2rem; padding: 2rem;
overflow: hidden; overflow: hidden;
position: relative; position: relative;

View File

@ -28,8 +28,9 @@
</transition> </transition>
</template> </template>
<script> <script>
import Dom from '../../utils/dom' import Dom, { _css } from '../../utils/dom'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
import Utils from '@/utils'
export default { export default {
name: 'FromBottomDialog', name: 'FromBottomDialog',
@ -74,7 +75,7 @@ export default {
modelValue(newVal) { modelValue(newVal) {
let page = document.getElementById(this.pageId) let page = document.getElementById(this.pageId)
if (newVal) { if (newVal) {
this.pagePosition = this.$getCss2(page, 'position') this.pagePosition = _css(page, 'position')
page.style.position = 'absolute' page.style.position = 'absolute'
this.scroll = document.documentElement.scrollTop this.scroll = document.documentElement.scrollTop
document.body.style.position = 'fixed' document.body.style.position = 'fixed'
@ -113,28 +114,28 @@ export default {
created() {}, created() {},
methods: { methods: {
beforeEnter(el) { beforeEnter(el) {
this.$setCss(el, 'transition-duration', `250ms`) _css(el, 'transition-duration', `250ms`)
this.$setCss(el, 'transform', `translate3d(0,${this.height},0)`) _css(el, 'transform', `translate3d(0,${this.height},0)`)
}, },
enter(el, done) { enter(el, done) {
setTimeout(() => { setTimeout(() => {
this.$setCss(el, 'transform', `translate3d(0,0,0)`) _css(el, 'transform', `translate3d(0,0,0)`)
}, 0) }, 0)
setTimeout(() => { setTimeout(() => {
// this.$setCss(el, 'transition-duration', `0ms`) // _css(el, 'transition-duration', `0ms`)
this.$setCss(el, 'transform', `none`) _css(el, 'transform', `none`)
done() done()
}, 250) }, 250)
}, },
afterEnter() {}, afterEnter() {},
beforeLeave(el) { beforeLeave(el) {
this.$setCss(el, 'transition-duration', `250ms`) _css(el, 'transition-duration', `250ms`)
this.$setCss(el, 'transform', `translate3d(0,0,0)`) _css(el, 'transform', `translate3d(0,0,0)`)
}, },
leave(el, done) { leave(el, done) {
//ref //ref
let maxHeight = new Dom('.FromBottomDialog').css('max-height') let maxHeight = new Dom('.FromBottomDialog').css('max-height')
this.$setCss(el, 'transform', `translate3d(0,${maxHeight},0)`) _css(el, 'transform', `translate3d(0,${maxHeight},0)`)
setTimeout(done, 250) setTimeout(done, 250)
}, },
afterLeave() {}, afterLeave() {},
@ -147,7 +148,7 @@ export default {
if (this.$refs.dialog.scrollTop !== 0) return if (this.$refs.dialog.scrollTop !== 0) return
this.startLocationY = e.touches[0].pageY this.startLocationY = e.touches[0].pageY
this.startTime = Date.now() this.startTime = Date.now()
this.$setCss(this.$refs.dialog, 'transition-duration', `0ms`) _css(this.$refs.dialog, 'transition-duration', `0ms`)
}, },
move(e) { move(e) {
if (this.$refs.dialog.scrollTop !== 0) return if (this.$refs.dialog.scrollTop !== 0) return
@ -157,7 +158,7 @@ export default {
tag: this.tag, tag: this.tag,
e: this.moveYDistance e: this.moveYDistance
}) })
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,${this.moveYDistance}px,0)`) _css(this.$refs.dialog, 'transform', `translate3d(0,${this.moveYDistance}px,0)`)
} }
}, },
end() { end() {
@ -168,17 +169,17 @@ export default {
// //
if (this.$refs.dialog.scrollTop !== 0) return if (this.$refs.dialog.scrollTop !== 0) return
let clientHeight = this.$refs.dialog.clientHeight let clientHeight = this.$refs.dialog.clientHeight
this.$setCss(this.$refs.dialog, 'transition-duration', `250ms`) _css(this.$refs.dialog, 'transition-duration', `250ms`)
if (Math.abs(this.moveYDistance) > clientHeight / 2) { if (Math.abs(this.moveYDistance) > clientHeight / 2) {
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,${clientHeight}px,0)`) _css(this.$refs.dialog, 'transform', `translate3d(0,${clientHeight}px,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: true }) bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: true })
setTimeout(this.hide, 250) setTimeout(this.hide, 250)
} else { } else {
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,0,0)`) _css(this.$refs.dialog, 'transform', `translate3d(0,0,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: false }) bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: false })
setTimeout(() => { setTimeout(() => {
this.$setCss(this.$refs.dialog, 'transform', 'none') _css(this.$refs.dialog, 'transform', 'none')
// this.$setCss(this.$refs.dialog, 'transition-duration', `0ms`) // _css(this.$refs.dialog, 'transition-duration', `0ms`)
}, 250) }, 250)
} }
this.moveYDistance = 0 this.moveYDistance = 0

View File

@ -23,13 +23,13 @@
/> />
<template v-if="state.operationStatus === SlideAlbumOperationStatus.Normal"> <template v-if="state.operationStatus === SlideAlbumOperationStatus.Normal">
<ItemToolbar <!-- <ItemToolbar-->
class="mb3r" <!-- class="mb3r"-->
v-model:item="state.localItem" <!-- v-model:item="state.localItem"-->
:position="position" <!-- :position="position"-->
v-bind="$attrs" <!-- v-bind="$attrs"-->
/> <!-- />-->
<ItemDesc class="mb3r" v-model:item="state.localItem" :position="position" /> <!-- <ItemDesc class="mb3r" v-model:item="state.localItem" :position="position" />-->
</template> </template>
<!--不知为啥touch事件在下部20px的空间内不触发加上click事件不好了 --> <!--不知为啥touch事件在下部20px的空间内不触发加上click事件不好了 -->
<div <div
@ -106,15 +106,12 @@ import {
slideInit, slideInit,
slideReset, slideReset,
slideTouchEnd, slideTouchEnd,
slidePointerMove, slideTouchMove,
slidePointerDown slideTouchStart
} from '@/utils/slide' } from '@/utils/slide'
import { SlideAlbumOperationStatus, SlideItemPlayStatus, SlideType } from '../../utils/const_var' import { SlideAlbumOperationStatus, SlideItemPlayStatus, SlideType } from '../../utils/const_var'
import ItemToolbar from './ItemToolbar'
import ItemDesc from './ItemDesc'
import { cloneDeep } from '@/utils' import { cloneDeep } from '@/utils'
import bus, { EVENT_KEY } from '../../utils/bus' import bus, { EVENT_KEY } from '../../utils/bus'
import $ from 'jquery'
let out = new Float32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) let out = new Float32Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
let ov = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) let ov = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1])
@ -409,7 +406,7 @@ function touchStart(e) {
// Utils.$showNoticeDialog('start'+e.touches.length) // Utils.$showNoticeDialog('start'+e.touches.length)
console.log('start', e.touches.length) console.log('start', e.touches.length)
if (e.touches.length === 1) { if (e.touches.length === 1) {
slidePointerDown(e, wrapperEl.value, state) slideTouchStart(e, wrapperEl.value, state)
} else { } else {
if (state.operationStatus === SlideAlbumOperationStatus.Zooming) { if (state.operationStatus === SlideAlbumOperationStatus.Zooming) {
// state.start.center = Utils.getCenter(state.start.point1, state.start.point2) // state.start.center = Utils.getCenter(state.start.point1, state.start.point2)
@ -430,6 +427,9 @@ function touchStart(e) {
} }
function touchMove(e) { function touchMove(e) {
const s = true
if (s) return
// Utils.$showNoticeDialog('move'+e.touches.length) // Utils.$showNoticeDialog('move'+e.touches.length)
// console.log('move', e.touches.length, state.operationStatus) // console.log('move', e.touches.length, state.operationStatus)
let current1 = { x: e.touches[0].pageX, y: e.touches[0].pageY } let current1 = { x: e.touches[0].pageX, y: e.touches[0].pageY }
@ -452,7 +452,7 @@ function touchMove(e) {
} else { } else {
// console.log('m2') // console.log('m2')
state.isAutoPlay = false state.isAutoPlay = false
slidePointerMove( slideTouchMove(
e, e,
wrapperEl.value, wrapperEl.value,
state, state,
@ -481,10 +481,11 @@ function touchMove(e) {
if (rectMap.has(state.localIndex)) { if (rectMap.has(state.localIndex)) {
rect = rectMap.get(state.localIndex) rect = rectMap.get(state.localIndex)
} else { } else {
//TODO jquery
//getBoundingClientRect //getBoundingClientRect
let offset = $(state.itemRefs[state.localIndex]).offset() // let offset = $(state.itemRefs[state.localIndex]).offset()
rect = { x: offset.left, y: offset.top } // rect = { x: offset.left, y: offset.top }
rectMap.set(state.localIndex, rect) // rectMap.set(state.localIndex, rect)
} }
let current2 = { x: e.touches[1].pageX, y: e.touches[1].pageY } let current2 = { x: e.touches[1].pageX, y: e.touches[1].pageY }
@ -579,7 +580,7 @@ function touchEnd(e) {
startLoop() startLoop()
} }
) )
slideReset(wrapperEl.value, state) slideReset(e, wrapperEl.value, state)
} }
} }
} }

View File

@ -4,8 +4,8 @@ import GM from '../../utils'
import { import {
getSlideOffset, getSlideOffset,
slideInit, slideInit,
slidePointerDown, slideTouchStart,
slidePointerMove, slideTouchMove,
slideReset, slideReset,
slideTouchEnd slideTouchEnd
} from '@/utils/slide' } from '@/utils/slide'
@ -39,16 +39,20 @@ const props = defineProps({
const emit = defineEmits(['update:index']) const emit = defineEmits(['update:index'])
let ob = null let ob = null
//slide-listref
const wrapperEl = ref(null) const wrapperEl = ref(null)
const state = reactive({ const state = reactive({
judgeValue: 20, judgeValue: 20, //
type: SlideType.HORIZONTAL, type: SlideType.HORIZONTAL, //
name: props.name, name: props.name,
localIndex: props.index, localIndex: props.index, //
needCheck: true, needCheck: true, //uptrue
next: false, next: false, //
start: { x: 0, y: 0, time: 0 }, isDown: false, //move
move: { x: 0, y: 0 }, start: { x: 0, y: 0, time: 0 }, //
move: { x: 0, y: 0 }, //
//slide-list
wrapper: { wrapper: {
width: 0, width: 0,
height: 0, height: 0,
@ -99,17 +103,17 @@ onUnmounted(() => {
ob.disconnect() ob.disconnect()
}) })
function touchStart(e: TouchEvent) { function touchStart(e) {
slidePointerDown(e, wrapperEl.value, state) slideTouchStart(e, wrapperEl.value, state)
} }
function touchMove(e: TouchEvent) { function touchMove(e) {
slidePointerMove(e, wrapperEl.value, state) slideTouchMove(e, wrapperEl.value, state)
} }
function touchEnd(e: TouchEvent) { function touchEnd(e) {
slideTouchEnd(e, state) slideTouchEnd(e, state)
slideReset(wrapperEl.value, state, emit) slideReset(e, wrapperEl.value, state, emit)
} }
</script> </script>
@ -127,9 +131,9 @@ function touchEnd(e: TouchEvent) {
<div <div
class="slide-list" class="slide-list"
ref="wrapperEl" ref="wrapperEl"
@touchstart="touchStart" @pointerdown="touchStart"
@touchmove="touchMove" @pointermove="touchMove"
@touchend="touchEnd" @pointerup="touchEnd"
> >
<slot></slot> <slot></slot>
</div> </div>
@ -141,16 +145,16 @@ function touchEnd(e: TouchEvent) {
position: absolute; position: absolute;
bottom: 10rem; bottom: 10rem;
z-index: 2; z-index: 2;
left: 0; left: 50%;
transform: translateX(-50%);
display: flex; display: flex;
justify-content: center; justify-content: center;
width: 100%; gap: 7rem;
.bullet { .bullet {
@width: 5rem; @width: 5rem;
width: @width; width: @width;
height: @width; height: @width;
margin: 0 3rem;
border-radius: 50%; border-radius: 50%;
background: var(--second-btn-color); background: var(--second-btn-color);

View File

@ -6,8 +6,8 @@ import {
slideInit, slideInit,
slideReset, slideReset,
slideTouchEnd, slideTouchEnd,
slidePointerMove, slideTouchMove,
slidePointerDown slideTouchStart
} from '@/utils/slide' } from '@/utils/slide'
import { SlideType } from '@/utils/const_var' import { SlideType } from '@/utils/const_var'
@ -22,21 +22,34 @@ const props = defineProps({
changeActiveIndexUseAnim: { changeActiveIndexUseAnim: {
type: Boolean, type: Boolean,
default: true default: true
},
name: {
type: String,
default: () => 'SlideVertical'
} }
}) })
const emit = defineEmits(['update:index']) const emit = defineEmits(['update:index'])
//slide-listref
const wrapperEl = ref(null) const wrapperEl = ref(null)
const state = reactive({ const state = reactive({
judgeValue: 20, judgeValue: 20, //
type: SlideType.HORIZONTAL, type: SlideType.VERTICAL, //
name: 'SlideVertical', name: props.name,
localIndex: props.index, localIndex: props.index, //
needCheck: true, needCheck: true, //uptrue
next: false, next: false, //
start: { x: 0, y: 0, time: 0 }, isDown: false, //move
move: { x: 0, y: 0 }, start: { x: 0, y: 0, time: 0 }, //
wrapper: { width: 0, height: 0, childrenLength: 0 } move: { x: 0, y: 0 }, //
//slide-list
wrapper: {
width: 0,
height: 0,
//childrenLengthcanNext
childrenLength: 0
}
}) })
watch( watch(
@ -61,16 +74,16 @@ onMounted(() => {
}) })
function touchStart(e) { function touchStart(e) {
slidePointerDown(e, wrapperEl.value, state) slideTouchStart(e, wrapperEl.value, state)
} }
function touchMove(e) { function touchMove(e) {
slidePointerMove(e, wrapperEl.value, state) slideTouchMove(e, wrapperEl.value, state)
} }
function touchEnd(e) { function touchEnd(e) {
slideTouchEnd(e, state) slideTouchEnd(e, state)
slideReset(wrapperEl.value, state, emit) slideReset(e, wrapperEl.value, state, emit)
} }
</script> </script>
@ -79,9 +92,9 @@ function touchEnd(e) {
<div <div
class="slide-list flex-direction-column" class="slide-list flex-direction-column"
ref="wrapperEl" ref="wrapperEl"
@touchstart="touchStart" @pointerdown="touchStart"
@touchmove="touchMove" @pointermove="touchMove"
@touchend="touchEnd" @pointerup="touchEnd"
> >
<slot></slot> <slot></slot>
</div> </div>

View File

@ -1,4 +1,4 @@
<script setup lang="jsx"> <script setup lang="tsx">
import { createApp, onMounted, reactive, ref, render as vueRender, watch } from 'vue' import { createApp, onMounted, reactive, ref, render as vueRender, watch } from 'vue'
import GM from '../../utils' import GM from '../../utils'
import { import {
@ -6,15 +6,15 @@ import {
slideInit, slideInit,
slideReset, slideReset,
slideTouchEnd, slideTouchEnd,
slidePointerMove, slideTouchMove,
slidePointerDown slideTouchStart
} from '@/utils/slide' } from '@/utils/slide'
import { SlideType } from '@/utils/const_var' import { SlideType } from '@/utils/const_var'
import SlideItem from '@/components/slide/SlideItem.vue' import SlideItem from '@/components/slide/SlideItem.vue'
import bus, { EVENT_KEY } from '../../utils/bus' import bus, { EVENT_KEY } from '../../utils/bus'
import Loading from '@/components/Loading.vue' import Loading from '@/components/Loading.vue'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import $ from 'jquery' import { _css } from '@/utils/dom'
const props = defineProps({ const props = defineProps({
index: { index: {
@ -60,14 +60,15 @@ const emit = defineEmits(['update:index', 'loadMore', 'refresh'])
const appInsMap = new Map() const appInsMap = new Map()
const itemClassName = 'slide-item' const itemClassName = 'slide-item'
const wrapperEl = ref(null) const wrapperEl = ref<HTMLDivElement>(null)
const state = reactive({ const state = reactive({
judgeValue: 20, judgeValue: 20,
type: SlideType.VERTICAL, type: SlideType.VERTICAL_INFINITE,
name: props.name, name: props.name,
localIndex: props.index, localIndex: props.index,
needCheck: true, needCheck: true,
next: false, next: false,
isDown: false,
start: { x: 0, y: 0, time: 0 }, start: { x: 0, y: 0, time: 0 },
move: { x: 0, y: 0 }, move: { x: 0, y: 0 },
wrapper: { width: 0, height: 0, childrenLength: 0 } wrapper: { width: 0, height: 0, childrenLength: 0 }
@ -85,17 +86,17 @@ watch(
if (oldVal.length === 0) { if (oldVal.length === 0) {
insertContent() insertContent()
} else { } else {
let lastSlideItem = $(wrapperEl.value).find(`.${itemClassName}:last`) let lastSlideItem = wrapperEl.value.querySelector(`.${itemClassName}:last-child`)
let top = lastSlideItem.css('top') let top = _css(lastSlideItem, 'top')
let lastIndex = Number(lastSlideItem.attr('data-index')) + 1 let lastIndex = Number(lastSlideItem.getAttribute('data-index')) + 1
console.log('lastIndex', lastIndex) // console.log('lastIndex', lastIndex)
newVal.slice(lastIndex, lastIndex + 3).map((item, index) => { newVal.slice(lastIndex, lastIndex + 3).map((item, index) => {
let el = getInsEl(item, lastIndex + index) let el = getInsEl(item, lastIndex + index)
//top //top
//2022-3-27slide-itemtop //2022-3-27slide-itemtop
//top //top
// top // top
$(el).css('top', top) _css(el, 'top', top)
wrapperEl.value.appendChild(el) wrapperEl.value.appendChild(el)
state.wrapper.childrenLength++ state.wrapper.childrenLength++
}) })
@ -146,13 +147,13 @@ watch(
) )
onMounted(() => { onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.VERTICAL) slideInit(wrapperEl.value, state)
insertContent() insertContent()
}) })
function insertContent(list = props.list) { function insertContent(list = props.list) {
if (!list.length) return if (!list.length) return
$(wrapperEl.value).empty() wrapperEl.value.innerHTML = ''
let half = (props.virtualTotal - 1) / 2 let half = (props.virtualTotal - 1) / 2
let start = 0 let start = 0
if (state.localIndex >= half) { if (state.localIndex >= half) {
@ -170,18 +171,21 @@ function insertContent(list = props.list) {
let el = getInsEl(item, start + index, start + index === state.localIndex) let el = getInsEl(item, start + index, start + index === state.localIndex)
wrapperEl.value.appendChild(el) wrapperEl.value.appendChild(el)
}) })
GM.$setCss(wrapperEl.value, 'transform', `translate3d(0px,${getSlideOffset(state)}px, 0px)`) GM.$setCss(
wrapperEl.value,
'transform',
`translate3d(0px,${getSlideOffset(state, wrapperEl.value)}px, 0px)`
)
if (state.localIndex > 2 && list.length > 5) { if (state.localIndex > 2 && list.length > 5) {
$(wrapperEl.value) let list = wrapperEl.value.querySelectorAll(`.${itemClassName}`)
.find(`.${itemClassName}`) list.forEach((item) => {
.each(function () { if (list.length - state.localIndex > 2) {
if (list.length - state.localIndex > 2) { _css(item, 'top', (state.localIndex - 2) * state.wrapper.height)
$(this).css('top', (state.localIndex - 2) * state.wrapper.height) } else {
} else { _css(item, 'top', start * state.wrapper.height)
$(this).css('top', start * state.wrapper.height) }
} })
})
} }
state.wrapper.childrenLength = wrapperEl.value.children.length state.wrapper.childrenLength = wrapperEl.value.children.length
// console.log('list[state.localIndex]',list[state.localIndex]) // console.log('list[state.localIndex]',list[state.localIndex])
@ -189,10 +193,10 @@ function insertContent(list = props.list) {
} }
function dislike(item) { function dislike(item) {
let currentItem = $(wrapperEl.value).find(`.${itemClassName}[data-index=${state.localIndex}]`) // let currentItem = $(wrapperEl.value).find(`.${itemClassName}[data-index=${state.localIndex}]`)
let replaceItem = getInsEl(item, state.localIndex, true) // let replaceItem = getInsEl(item, state.localIndex, true)
$(replaceItem).css('top', currentItem.css('top')) // $(replaceItem).css('top', currentItem.css('top'))
currentItem.replaceWith(replaceItem) // currentItem.replaceWith(replaceItem)
} }
defineExpose({ dislike }) defineExpose({ dislike })
@ -226,12 +230,12 @@ function getInsEl(item, index, play = false) {
} }
function touchStart(e) { function touchStart(e) {
slidePointerDown(e, wrapperEl.value, state) slideTouchStart(e, wrapperEl.value, state)
} }
//TODO 2022-3-28: //TODO 2022-3-28:
function touchMove(e) { function touchMove(e) {
slidePointerMove(e, wrapperEl.value, state, canNext) slideTouchMove(e, wrapperEl.value, state, canNext)
} }
function touchEnd(e) { function touchEnd(e) {
@ -251,9 +255,9 @@ function touchEnd(e) {
emit('loadMore') emit('loadMore')
} }
let addItemIndex = state.localIndex + 2 let addItemIndex = state.localIndex + 2
let res = $(wrapperEl.value).find(`.${itemClassName}[data-index=${addItemIndex}]`) let res = wrapperEl.value.querySelector(`.${itemClassName}[data-index='${addItemIndex}']`)
if (state.wrapper.childrenLength < props.virtualTotal) { if (state.wrapper.childrenLength < props.virtualTotal) {
if (res.length === 0) { if (!res) {
wrapperEl.value.appendChild(getInsEl(props.list[addItemIndex], addItemIndex)) wrapperEl.value.appendChild(getInsEl(props.list[addItemIndex], addItemIndex))
} }
} }
@ -262,55 +266,56 @@ function touchEnd(e) {
state.localIndex >= (props.virtualTotal + 1) / 2 && state.localIndex >= (props.virtualTotal + 1) / 2 &&
state.localIndex <= props.list.length - 3 state.localIndex <= props.list.length - 3
) { ) {
if (res.length === 0) { if (!res) {
wrapperEl.value.appendChild(getInsEl(props.list[addItemIndex], addItemIndex)) wrapperEl.value.appendChild(getInsEl(props.list[addItemIndex], addItemIndex))
appInsMap let index = wrapperEl.value
.get($(wrapperEl.value).find(`.${itemClassName}:first`).data('index')) .querySelector(`.${itemClassName}:first-child`)
.unmount() .getAttribute('data-index')
// $(wrapperEl.value).find(".base-slide-item:first").remove() appInsMap.get(Number(index)).unmount()
$(wrapperEl.value) wrapperEl.value.querySelectorAll(`.${itemClassName}`).forEach((item) => {
.find(`.${itemClassName}`) _css(item, 'top', (state.localIndex - 2) * state.wrapper.height)
.each(function () { })
$(this).css('top', (state.localIndex - 2) * state.wrapper.height)
})
} }
} }
if (state.wrapper.childrenLength > props.virtualTotal) { if (state.wrapper.childrenLength > props.virtualTotal) {
$(wrapperEl.value) wrapperEl.value.querySelectorAll(`.${itemClassName}`).forEach((item) => {
.find(`.${itemClassName}`) let index = Number(item.getAttribute('data-index'))
.each(function () { if (index < state.localIndex - 2) {
let index = $(this).data('index') console.log(2, appInsMap.get(Number(index)))
if (index < state.localIndex - 2) { appInsMap.get(index).unmount()
appInsMap.get(index).unmount() }
} _css(item, 'top', (state.localIndex - 2) * state.wrapper.height)
$(this).css('top', (state.localIndex - 2) * state.wrapper.height) })
})
} }
} else { } else {
let addItemIndex = state.localIndex - 2 let addItemIndex = state.localIndex - 2
let res = $(wrapperEl.value).find(`.${itemClassName}[data-index=${addItemIndex}]`) let res = wrapperEl.value.querySelector(`.${itemClassName}[data-index='${addItemIndex}']`)
if (state.localIndex > 1 && state.localIndex <= props.list.length - 4) { if (state.localIndex > 1 && state.localIndex <= props.list.length - 4) {
if (res.length === 0) { if (!res) {
wrapperEl.value.prepend(getInsEl(props.list[addItemIndex], addItemIndex)) wrapperEl.value.prepend(getInsEl(props.list[addItemIndex], addItemIndex))
appInsMap.get($(wrapperEl.value).find(`.${itemClassName}:last`).data('index')).unmount() let index = wrapperEl.value
.querySelector(`.${itemClassName}:last-child`)
.getAttribute('data-index')
appInsMap.get(Number(index)).unmount()
// $(wrapperEl.value).find(".base-slide-item:last").remove() // $(wrapperEl.value).find(".base-slide-item:last").remove()
$(wrapperEl.value) wrapperEl.value.querySelectorAll(`.${itemClassName}`).forEach((item) => {
.find(`.${itemClassName}`) _css(item, 'top', (state.localIndex - 2) * state.wrapper.height)
.each(function () { })
$(this).css('top', (state.localIndex - 2) * state.wrapper.height)
})
} }
} }
if (state.wrapper.childrenLength > props.virtualTotal) { if (state.wrapper.childrenLength > props.virtualTotal) {
appInsMap.get($(wrapperEl.value).find(`.${itemClassName}:last`).data('index')).unmount() let index = wrapperEl.value
.querySelector(`.${itemClassName}:last-child`)
.getAttribute('data-index')
appInsMap.get(Number(index)).unmount()
} }
} }
state.wrapper.childrenLength = wrapperEl.value.children.length state.wrapper.childrenLength = wrapperEl.value.children.length
} }
}) })
slideReset(wrapperEl.value, state, emit) slideReset(e, wrapperEl.value, state, emit)
} }
function canNext(state, isNext) { function canNext(state, isNext) {
@ -328,9 +333,9 @@ function canNext(state, isNext) {
class="slide-list flex-direction-column" class="slide-list flex-direction-column"
ref="wrapperEl" ref="wrapperEl"
@click="null" @click="null"
@touchstart="touchStart" @pointerdown="touchStart"
@touchmove="touchMove" @pointermove="touchMove"
@touchend="touchEnd" @pointerup="touchEnd"
> >
<slot></slot> <slot></slot>
</div> </div>

View File

@ -8,6 +8,29 @@ import mixin from './utils/mixin'
import VueLazyload from '@jambonn/vue-lazyload' import VueLazyload from '@jambonn/vue-lazyload'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
window.isMoved = false
HTMLElement.prototype.addEventListener = new Proxy(HTMLElement.prototype.addEventListener, {
apply(target, ctx, args) {
const eventName = args[0]
const listener = args[1]
// console.log('e', eventName, '')
if (listener instanceof Function && eventName === 'click') {
args[1] = new Proxy(listener, {
apply(target, ctx, args) {
// console.log('点击', window.isMoved)
if (window.isMoved) return
try {
return target.apply(ctx, args)
} catch (e) {
console.error(`[proxyPlayerEvent][${eventName}]`, listener, e)
}
}
})
}
return target.apply(ctx, args)
}
})
const pinia = createPinia() const pinia = createPinia()
const emitter = mitt() const emitter = mitt()
const app = createApp(App) const app = createApp(App)

View File

@ -28,23 +28,71 @@ const t = [
type: 'imgs', type: 'imgs',
src: `https://imgapi.cn/bing.php`, src: `https://imgapi.cn/bing.php`,
author: { author: {
unique_id: 1 unique_id: 1,
} avatar_168x168: {
}, url_list: []
{ },
type: 'user', avatar_300x300: {
src: `https://imgapi.cn/bing.php`, url_list: []
author: { },
unique_id: 2 cover_url: [
} {
}, url_list: []
{ }
type: 'img', ],
src: `https://imgapi.cn/bing.php`, white_cover_url: [
author: { {
unique_id: 3 url_list: []
}
]
} }
} }
// {
// type: 'user',
// src: `https://imgapi.cn/bing.php`,
// author: {
// unique_id: 2,
// avatar_168x168: {
// url_list: []
// },
// avatar_300x300: {
// url_list: []
// },
// cover_url: [
// {
// url_list: []
// }
// ],
// white_cover_url: [
// {
// url_list: []
// }
// ]
// }
// },
// {
// type: 'img',
// src: `https://imgapi.cn/bing.php`,
// author: {
// unique_id: 3,
// avatar_168x168: {
// url_list: []
// },
// avatar_300x300: {
// url_list: []
// },
// cover_url: [
// {
// url_list: []
// }
// ],
// white_cover_url: [
// {
// url_list: []
// }
// ]
// }
// }
] ]
// allRecommendVideos.unshift(...t) // allRecommendVideos.unshift(...t)

View File

@ -346,6 +346,7 @@ function dislike() {
overflow: hidden; overflow: hidden;
.sidebar { .sidebar {
touch-action: pan-y;
width: 80vw; width: 80vw;
height: calc(var(--vh, 1vh) * 100); height: calc(var(--vh, 1vh) * 100);
overflow: auto; overflow: auto;
@ -449,7 +450,7 @@ function dislike() {
.first-horizontal-item { .first-horizontal-item {
//width: 90vw; //width: 90vw;
//height: 80vh; //height: 80vh;
width: 100vw; width: 100%;
height: calc(var(--vh, 1vh) * 100 - var(--footer-height)) !important; height: calc(var(--vh, 1vh) * 100 - var(--footer-height)) !important;
overflow: hidden; overflow: hidden;
border-radius: 10rem; border-radius: 10rem;

View File

@ -1,5 +1,5 @@
<template> <template>
<div id="Community"> <div id="Community" @dragstart="(e) => Utils.$stopPropagation(e)">
<ScrollList class="Scroll" v-if="state.show" :api="recommendedPost"> <ScrollList class="Scroll" v-if="state.show" :api="recommendedPost">
<template v-slot="{ list }"> <template v-slot="{ list }">
<div class="search" @click="nav('/home/search')"> <div class="search" @click="nav('/home/search')">
@ -47,7 +47,7 @@
<script setup> <script setup>
import { reactive, ref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import { $no, _checkImgUrl, cloneDeep } from '@/utils' import Utils, { $no, _checkImgUrl, cloneDeep } from '@/utils'
import { recommendedPost } from '@/api/user' import { recommendedPost } from '@/api/user'
import { useNav } from '@/utils/hooks/useNav' import { useNav } from '@/utils/hooks/useNav'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
@ -56,9 +56,7 @@ import ScrollList from '@/components/ScrollList.vue'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import AlbumDetail from '@/pages/other/AlbumDetail.vue' import AlbumDetail from '@/pages/other/AlbumDetail.vue'
import Mock from 'mockjs' import Mock from 'mockjs'
import $ from 'jquery' import { _css } from '@/utils/dom'
//@click="nav('album-detail',{},item)"
const nav = useNav() const nav = useNav()
const baseStore = useBaseStore() const baseStore = useBaseStore()
@ -98,32 +96,32 @@ watch(
) )
function close() { function close() {
let s = $('.shadow ') let s = document.querySelector('.shadow ')
let domRect = rect.value let domRect = rect.value
let t = '.3' let t = '.3'
s.css('transition', `all ${t}s`) _css(s, 'transition', `all ${t}s`)
s.css('top', domRect.top) _css(s, 'top', domRect.top)
s.css('left', domRect.left) _css(s, 'left', domRect.left)
s.css('width', domRect.width) _css(s, 'width', domRect.width)
s.css('height', domRect.height) _css(s, 'height', domRect.height)
let a = $('.goods-detail') let a = document.querySelector('.goods-detail')
a.css('transition', `all ${t}s`) _css(a, 'transition', `all ${t}s`)
a.css('opacity', '0') _css(a, 'opacity', '0')
a.css('width', '100vw') _css(a, 'width', '100vw')
a.css('height', '100vh') _css(a, 'height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`) _css(a, 'transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`) _css(a, 'transform-origin', `0 0`)
let d = $('.shadow .wrap') let d = document.querySelector('.shadow .wrap')
d.css('transition', `all ${t}s`) _css(d, 'transition', `all ${t}s`)
d.css('opacity', '1') _css(d, 'opacity', '1')
// state.d = false // state.d = false
setTimeout(() => { setTimeout(() => {
s.css('z-index', '-100') _css(s, 'z-index', '-100')
s.css('transition', 'all 0s') _css(s, 'transition', 'all 0s')
s.css('top', '-200vh') _css(s, 'top', '-200vh')
}, 300) }, 300)
} }
@ -144,52 +142,54 @@ function showDetail(e, item) {
// console.log(state.current) // console.log(state.current)
state.d = true state.d = true
let domRect = e.currentTarget.getBoundingClientRect()
// console.log('e', domRect)
let s = $('.shadow ')
s.css('z-index', '1') let domRect = e.currentTarget.getBoundingClientRect()
s.css('transition', '0s') // // console.log('e', domRect)
s.css('top', domRect.top)
s.css('left', domRect.left) let s = document.querySelector('.shadow')
s.css('width', domRect.width)
s.css('height', domRect.height) _css(s, 'z-index', '1')
_css(s, 'transition', '0s')
_css(s, 'top', domRect.top)
_css(s, 'left', domRect.left)
_css(s, 'width', domRect.width)
_css(s, 'height', domRect.height)
let t = '.3' let t = '.3'
let d = $('.shadow .wrap') let d = document.querySelector('.shadow .wrap')
d.empty() d.innerHTML = ''
d.show() d.append(e.currentTarget.cloneNode(true))
d.append($(e.currentTarget).clone()) _css(d, 'display', 'block')
d.css('transition', `all ${t}s`) _css(d, 'transition', `all ${t}s`)
d.css('opacity', '1') _css(d, 'opacity', '1')
let sw = domRect.width / baseStore.bodyWidth let sw = domRect.width / baseStore.bodyWidth
let sh = domRect.height / baseStore.bodyHeight let sh = domRect.height / baseStore.bodyHeight
domRect.sw = sw domRect.sw = sw
domRect.sh = sh domRect.sh = sh
let a = $('.goods-detail') let a = document.querySelector('.goods-detail')
a.css('opacity', '0') _css(a, 'opacity', '0')
a.css('width', '100vw') _css(a, 'width', '100vw')
a.css('height', '100vh') _css(a, 'height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`) _css(a, 'transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`) _css(a, 'transform-origin', `0 0`)
rect.value = domRect rect.value = domRect
setTimeout(() => { setTimeout(() => {
s.css('transition', `all ${t}s`) _css(s, 'transition', `all ${t}s`)
s.css('top', 0) _css(s, 'top', 0)
s.css('left', 0) _css(s, 'left', 0)
s.css('width', '100vw') _css(s, 'width', '100vw')
s.css('height', '100vh') _css(s, 'height', '100vh')
d.css('opacity', '0') _css(d, 'opacity', '0')
d.css('z-index', '-1') _css(d, 'z-index', '-1')
a.css('transition', `all ${t}s`) _css(a, 'transition', `all ${t}s`)
a.css('opacity', '1') _css(a, 'opacity', '1')
a.css('transform', `scale(1,1)`) _css(a, 'transform', `scale(1,1)`)
a.css('transform-origin', `0 0`) _css(a, 'transform-origin', `0 0`)
}) })
} }
</script> </script>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { reactive, ref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import { _checkImgUrl, _duration, _formatNumber } from '@/utils' import Utils, { _checkImgUrl, _duration, _formatNumber } from '@/utils'
import { recommendedVideo } from '@/api/videos' import { recommendedVideo } from '@/api/videos'
import ScrollList from '@/components/ScrollList.vue' import ScrollList from '@/components/ScrollList.vue'
import { useNav } from '@/utils/hooks/useNav' import { useNav } from '@/utils/hooks/useNav'
@ -78,7 +78,7 @@ const nav = useNav()
</script> </script>
<template> <template>
<div class="long-video"> <div class="long-video" @dragstart="(e) => Utils.$stopPropagation(e)">
<ScrollList class="Scroll" v-if="state.show" :api="recommendedVideo"> <ScrollList class="Scroll" v-if="state.show" :api="recommendedVideo">
<template v-slot="{ list }"> <template v-slot="{ list }">
<div class="list"> <div class="list">

View File

@ -112,7 +112,7 @@
grid-template-columns: 33.33% 33.33% 33.33%; grid-template-columns: 33.33% 33.33% 33.33%;
.item { .item {
height: calc(33.33vw * 1.3); height: calc(33.33% * 1.3);
padding: 2rem; padding: 2rem;
overflow: hidden; overflow: hidden;
position: relative; position: relative;

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="Me"> <div class="Me">
<SlideRowList name="baseSlide" style="width: 100vw" v-model:active-index="baseActiveIndex"> <SlideRowList name="baseSlide" style="width: 100%" v-model:active-index="baseActiveIndex">
<SlideItem> <SlideItem>
<div ref="float" class="float" :class="floatFixed ? 'fixed' : ''"> <div ref="float" class="float" :class="floatFixed ? 'fixed' : ''">
<div <div

View File

@ -191,7 +191,6 @@ import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } fro
import Loading from '@/components/Loading.vue' import Loading from '@/components/Loading.vue'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import { _checkImgUrl, _no, _sleep } from '@/utils' import { _checkImgUrl, _no, _sleep } from '@/utils'
import $ from 'jquery'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useNav } from '@/utils/hooks/useNav' import { useNav } from '@/utils/hooks/useNav'
@ -238,6 +237,7 @@ const mitt = inject('mitt')
const router = useRouter() const router = useRouter()
const nav = useNav() const nav = useNav()
const store = useBaseStore() const store = useBaseStore()
const msgWrapper = ref<HTMLDivElement>()
const data = reactive({ const data = reactive({
previewImg: new URL('../../../assets/img/poster/3.jpg', import.meta.url).href, previewImg: new URL('../../../assets/img/poster/3.jpg', import.meta.url).href,
videoCall: [], videoCall: [],
@ -488,12 +488,16 @@ const data = reactive({
}) })
onMounted(() => { onMounted(() => {
$('img').on('load', scrollBottom) msgWrapper.value
.querySelectorAll('img')
.forEach((item) => item.addEventListener('load', scrollBottom))
scrollBottom() scrollBottom()
}) })
onUnmounted(() => { onUnmounted(() => {
$('img').off('load', scrollBottom) msgWrapper.value
.querySelectorAll('img')
.forEach((item) => item.removeEventListener('load', scrollBottom))
}) })
const isExpand = computed(() => { const isExpand = computed(() => {
@ -505,8 +509,6 @@ function handleClick() {
data.showOption = false data.showOption = false
} }
const msgWrapper = ref()
function scrollBottom() { function scrollBottom() {
nextTick(() => { nextTick(() => {
let wrapper = msgWrapper.value let wrapper = msgWrapper.value

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="goods-detail"> <div class="goods-detail" @dragstart="(e) => Utils.$stopPropagation(e)">
<header> <header>
<Icon @click="close" icon="material-symbols-light:arrow-back-ios-new" /> <Icon @click="close" icon="material-symbols-light:arrow-back-ios-new" />
<div class="option" @click="nav('/home/search')"> <div class="option" @click="nav('/home/search')">
@ -99,7 +99,7 @@ import SlideItem from '@/components/slide/SlideItem.vue'
import { reactive, ref } from 'vue' import { reactive, ref } from 'vue'
import { useNav } from '@/utils/hooks/useNav' import { useNav } from '@/utils/hooks/useNav'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { _checkImgUrl } from '@/utils' import Utils, { _checkImgUrl } from '@/utils'
const nav = useNav() const nav = useNav()
@ -181,7 +181,6 @@ function close() {
height: 100%; height: 100%;
width: 100%; width: 100%;
object-fit: cover; object-fit: cover;
touch-action: none;
} }
.indicator-bar { .indicator-bar {

View File

@ -81,8 +81,6 @@ export default class Dom {
//情况一:获取样式 //情况一:获取样式
if (typeof args[0] === 'string') { if (typeof args[0] === 'string') {
return window.getComputedStyle(this.els[this.els.length - 1], null)[args[0]] return window.getComputedStyle(this.els[this.els.length - 1], null)[args[0]]
// return globalMethods.$getCss2
// return this.els[0].style[args[0]]
} else { } else {
//情况三:设置多个样式 //情况三:设置多个样式
Object.keys(args[0]).map((key) => { Object.keys(args[0]).map((key) => {
@ -142,3 +140,48 @@ export default class Dom {
return parseInt(val) return parseInt(val)
} }
} }
export function _css(el, key, value?) {
const reg = /^\d+(px|pt|em|rem|vw|vh|%|rpx)$/i
if (value === undefined) {
let val = null
if ('getComputedStyle' in window) {
val = window.getComputedStyle(el, null)[key]
} else {
val = el.currentStyle[key]
}
return reg.test(val) ? parseFloat(val) : val
// return parseFloat(val)
} else {
if (
[
'top',
'left',
'bottom',
'right',
'width',
'height',
'font-size',
'margin',
'padding'
].includes(key)
) {
if (!reg.test(value)) {
value += 'px'
}
}
// console.log(value)
if (key === 'transform') {
//直接设置不生效
el.style.webkitTransform =
el.style.MsTransform =
el.style.msTransform =
el.style.MozTransform =
el.style.OTransform =
el.style.transform =
value
} else {
el.style[key] = value
}
}
}

View File

@ -204,26 +204,6 @@ const Utils = {
// return reg.test(val) ? parseFloat(val) : val // return reg.test(val) ? parseFloat(val) : val
return parseFloat(val) return parseFloat(val)
}, },
$getCss2(curEle, attr) {
let val = null,
reg = null
if ('getComputedStyle' in window) {
val = window.getComputedStyle(curEle, null)[attr]
} else {
//ie6~8不支持上面属性
//不兼容
if (attr === 'opacity') {
val = curEle.currentStyle['filter'] //'alpha(opacity=12,345)'
reg = /^alphaopacity=(\d+(?:\.\d+)?)opacity=(\d+(?:\.\d+)?)$/i
val = reg.test(val) ? reg.exec(val)[1] / 100 : 1
} else {
val = curEle.currentStyle[attr]
}
}
// reg = /^(-?\d+(\.\d)?)(px|pt|em|rem)?$/i
// return reg.test(val) ? parseFloat(val) : val
return val
},
$setCss(el, key, value) { $setCss(el, key, value) {
// console.log(value) // console.log(value)
if (key === 'transform') { if (key === 'transform') {

View File

@ -3,6 +3,22 @@ import Utils from '@/utils/index'
import GM from '@/utils/index' import GM from '@/utils/index'
import { SlideType } from '@/utils/const_var' import { SlideType } from '@/utils/const_var'
import { nextTick } from 'vue' import { nextTick } from 'vue'
import { _css } from '@/utils/dom'
function checkEvent(e) {
const isMobile = /Mobi|Android|iPhone/i.test(navigator.userAgent)
if (!isMobile || (isMobile && e instanceof PointerEvent)) {
e.touches = [
{
clientX: e.clientX,
clientY: e.clientY,
pageX: e.pageX,
pageY: e.pageY
}
]
}
return true
}
//初始化信息获取slide dom的长宽、子元素数量用于move事件判断能否滑动 //初始化信息获取slide dom的长宽、子元素数量用于move事件判断能否滑动
export function slideInit(el, state) { export function slideInit(el, state) {
@ -13,26 +29,17 @@ export function slideInit(el, state) {
}) })
//获取偏移量 //获取偏移量
let t = getSlideOffset(state, el) const t = getSlideOffset(state, el)
let dx1 = 0, let dx1 = 0,
dx2 = 0 dx2 = 0
if (state.type === SlideType.HORIZONTAL) dx1 = t if (state.type === SlideType.HORIZONTAL) dx1 = t
else dx2 = t else dx2 = t
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`) _css(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
}
export function slidePointerDown(e, el, state) {
Utils.$setCss(el, 'transition-duration', `0ms`)
//记录起点坐标用于move事件计算移动距离
state.start.x = e.touches[0].pageX
state.start.y = e.touches[0].pageY
//记录按下时间用于up事件判断滑动时间
state.start.time = Date.now()
} }
/** /**
* * SlideHorizontal组件就只处理左右滑动事件SlideVertical只处理上下滑动事件
* @param state * * @param state
* @returns {boolean} * @returns {boolean}
*/ */
export function canSlide(state) { export function canSlide(state) {
@ -41,7 +48,7 @@ export function canSlide(state) {
//判断move x和y的距离是否大于判断值因为距离太小无法判断滑动方向 //判断move x和y的距离是否大于判断值因为距离太小无法判断滑动方向
if (Math.abs(state.move.x) > state.judgeValue || Math.abs(state.move.y) > state.judgeValue) { if (Math.abs(state.move.x) > state.judgeValue || Math.abs(state.move.y) > state.judgeValue) {
//放大再相除根据长宽比判断方向angle大于1就是左右滑动小于是上下滑动 //放大再相除根据长宽比判断方向angle大于1就是左右滑动小于是上下滑动
let angle = (Math.abs(state.move.x) * 10) / (Math.abs(state.move.y) * 10) const angle = (Math.abs(state.move.x) * 10) / (Math.abs(state.move.y) * 10)
//根据当前slide的类型判断能否滑动并记录下来后续不再判断直接返回记录值 //根据当前slide的类型判断能否滑动并记录下来后续不再判断直接返回记录值
state.next = state.type === SlideType.HORIZONTAL ? angle > 1 : angle <= 1 state.next = state.type === SlideType.HORIZONTAL ? angle > 1 : angle <= 1
// console.log('angle', angle, state.next) // console.log('angle', angle, state.next)
@ -66,6 +73,24 @@ function canNext(state, isNext) {
) )
} }
/**
*
* @param e
* @param el
* @param state
*/
export function slideTouchStart(e, el, state) {
// console.log('e', e, state.name)
if (!checkEvent(e)) return
_css(el, 'transition-duration', `0ms`)
//记录起点坐标用于move事件计算移动距离
state.start.x = e.touches[0].pageX
state.start.y = e.touches[0].pageY
//记录按下时间用于up事件判断滑动时间
state.start.time = Date.now()
state.isDown = true
}
/** /**
* move事件 * move事件
* @param e * @param e
@ -75,7 +100,7 @@ function canNext(state, isNext) {
* @param notNextCb * @param notNextCb
* @param slideOtherDirectionCb * @param slideOtherDirectionCb
*/ */
export function slidePointerMove( export function slideTouchMove(
e, e,
el, el,
state, state,
@ -83,16 +108,20 @@ export function slidePointerMove(
notNextCb = null, notNextCb = null,
slideOtherDirectionCb = null slideOtherDirectionCb = null
) { ) {
if (!checkEvent(e)) return
if (!state.isDown) return
// console.log('move', state.name)
//计算移动距离 //计算移动距离
state.move.x = e.touches[0].pageX - state.start.x state.move.x = e.touches[0].pageX - state.start.x
state.move.y = e.touches[0].pageY - state.start.y state.move.y = e.touches[0].pageY - state.start.y
// console.log('move', state.name) // console.log('move', state.name)
//检测能否滑动 //检测能否滑动
let canSlideRes = canSlide(state) const canSlideRes = canSlide(state)
//是否是往下(右)滑动 //是否在往到头或尾滑动
let isNext = state.type === SlideType.HORIZONTAL ? state.move.x < 0 : state.move.y < 0 const isNext = state.type === SlideType.HORIZONTAL ? state.move.x < 0 : state.move.y < 0
//特别处理竖直的slide组件在第一页往下滑动时向外发送事件 //特别处理竖直的slide组件在第一页往下滑动时向外发送事件
//用于首页顶部导航栏的刷新动画 //用于首页顶部导航栏的刷新动画
@ -107,13 +136,14 @@ export function slidePointerMove(
//无限滑动组件要特别判断所以需要传canNextCb //无限滑动组件要特别判断所以需要传canNextCb
if (!canNextCb) canNextCb = canNext if (!canNextCb) canNextCb = canNext
if (canNextCb(state, isNext)) { if (canNextCb(state, isNext)) {
window.isMoved = true
//能滑动,那就把事件捕获,不能给父组件处理 //能滑动,那就把事件捕获,不能给父组件处理
Utils.$stopPropagation(e) Utils.$stopPropagation(e)
if (state.type === SlideType.HORIZONTAL) { if (state.type === SlideType.HORIZONTAL) {
bus.emit(state.name + '-moveX', state.move.x) bus.emit(state.name + '-moveX', state.move.x)
} }
//获取偏移量 //获取偏移量
let t = getSlideOffset(state, el) + (isNext ? state.judgeValue : -state.judgeValue) const t = getSlideOffset(state, el) + (isNext ? state.judgeValue : -state.judgeValue)
let dx1 = 0, let dx1 = 0,
dx2 = 0 dx2 = 0
//偏移量加当前手指移动的距离就是slide要偏移的值 //偏移量加当前手指移动的距离就是slide要偏移的值
@ -122,8 +152,8 @@ export function slidePointerMove(
} else { } else {
dx2 = t + state.move.y dx2 = t + state.move.y
} }
Utils.$setCss(el, 'transition-duration', `0ms`) _css(el, 'transition-duration', `0ms`)
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`) _css(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
} else { } else {
//SlideAlbum.vue组件在用用于捕获事件阻止事件传递给父slide //SlideAlbum.vue组件在用用于捕获事件阻止事件传递给父slide
notNextCb?.() notNextCb?.()
@ -143,25 +173,28 @@ export function slidePointerMove(
* @returns {*} * @returns {*}
*/ */
export function slideTouchEnd(e, state, canNextCb = null, nextCb = null, notNextCb = null) { export function slideTouchEnd(e, state, canNextCb = null, nextCb = null, notNextCb = null) {
let isHorizontal = state.type === SlideType.HORIZONTAL if (!checkEvent(e)) return
let isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0 if (!state.isDown) return
const isHorizontal = state.type === SlideType.HORIZONTAL
const isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0
if (state.next) { if (state.next) {
//同move事件 //同move事件
if (!canNextCb) canNextCb = canNext if (!canNextCb) canNextCb = canNext
if (canNextCb(state, isNext)) { if (canNextCb(state, isNext)) {
//能滑动,那就把事件捕获,不能给父组件处理 //能滑动,那就把事件捕获,不能给父组件处理
Utils.$stopPropagation(e) // Utils.$stopPropagation(e)
//结合时间、距离来判断是否成功滑动 //结合时间、距离来判断是否成功滑动
let endTime = Date.now() const endTime = Date.now()
let gapTime = endTime - state.start.time let gapTime = endTime - state.start.time
let distance = isHorizontal ? state.move.x : state.move.y const distance = isHorizontal ? state.move.x : state.move.y
let judgeValue = isHorizontal ? state.wrapper.width : state.wrapper.height const judgeValue = isHorizontal ? state.wrapper.width : state.wrapper.height
//1、距离太短直接不通过 //1、距离太短直接不通过
if (Math.abs(distance) < 20) gapTime = 1000 if (Math.abs(distance) < 20) gapTime = 1000
//2、距离太长直接通过 //2、距离太长直接通过
if (Math.abs(distance) > judgeValue / 3) gapTime = 100 if (Math.abs(distance) > judgeValue / 3) gapTime = 100
//3、若不在上面那个情况,那么只需要判断时间即可 //3、若不在上述两种情况,那么只需要判断时间即可
if (gapTime < 150) { if (gapTime < 150) {
if (isNext) { if (isNext) {
state.localIndex++ state.localIndex++
@ -184,9 +217,11 @@ export function slideTouchEnd(e, state, canNextCb = null, nextCb = null, notNext
* @param state * @param state
* @param emit * @param emit
*/ */
export function slideReset(el, state, emit = null) { export function slideReset(e, el, state, emit = null) {
Utils.$setCss(el, 'transition-duration', `300ms`) if (!checkEvent(e)) return
let t = getSlideOffset(state, el)
_css(el, 'transition-duration', `300ms`)
const t = getSlideOffset(state, el)
let dx1 = 0 let dx1 = 0
let dx2 = 0 let dx2 = 0
if (state.type === SlideType.HORIZONTAL) { if (state.type === SlideType.HORIZONTAL) {
@ -196,16 +231,21 @@ export function slideReset(el, state, emit = null) {
bus.emit(state.name + '-end') bus.emit(state.name + '-end')
dx2 = t dx2 = t
} }
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`) _css(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
state.start.x = state.start.y = state.start.time = state.move.x = state.move.y = 0 state.start.x = state.start.y = state.start.time = state.move.x = state.move.y = 0
state.next = false state.next = false
state.needCheck = true state.needCheck = true
state.isDown = false
// e.target.style.pointerEvents = null
setTimeout(() => {
window.isMoved = false
}, 200)
emit?.('update:index', state.localIndex) emit?.('update:index', state.localIndex)
} }
//根据当前index获取slide偏移距离 //根据当前index获取slide偏移距离
//如果每个页面的宽度是相同均为100%只需要当前index * wrapper的宽度即可 -state.localIndex * state.wrapper.width //如果每个页面的宽度是相同均为100%只需要当前index * wrapper的宽度即可 -state.localIndex * state.wrapper.width
export function getSlideOffset(state, el) { export function getSlideOffset(state: any, el: HTMLDivElement) {
//横竖判断逻辑基本同理 //横竖判断逻辑基本同理
if (state.type === SlideType.HORIZONTAL) { if (state.type === SlideType.HORIZONTAL) {
let widths = [] let widths = []
@ -222,7 +262,10 @@ export function getSlideOffset(state, el) {
return 0 return 0
// return -state.localIndex * state.wrapper.width // return -state.localIndex * state.wrapper.width
} else { } else {
//VERTICAL_INFINITE 列表只需要计算index * 高就行
if (state.type === SlideType.VERTICAL_INFINITE) { if (state.type === SlideType.VERTICAL_INFINITE) {
return -state.localIndex * state.wrapper.height
} else {
//同上 //同上
let heights = [] let heights = []
Array.from(el.children).map((v) => { Array.from(el.children).map((v) => {
@ -231,9 +274,6 @@ export function getSlideOffset(state, el) {
heights = heights.slice(0, state.localIndex) heights = heights.slice(0, state.localIndex)
if (heights.length) return -heights.reduce((a, b) => a + b) if (heights.length) return -heights.reduce((a, b) => a + b)
return 0 return 0
} else {
//VERTICAL_INFINITE 列表只需要计算index * 高就行
return -state.localIndex * state.wrapper.height
} }
} }
} }

View File

@ -63,12 +63,6 @@ export default defineConfig(async () => {
name: 'mockjs', name: 'mockjs',
var: 'Mock', var: 'Mock',
path: 'https://lib.baomitu.com/Mock.js/1.0.1-beta3/mock-min.js' path: 'https://lib.baomitu.com/Mock.js/1.0.1-beta3/mock-min.js'
},
{
name: 'jquery',
var: '$',
path: 'https://lib.baomitu.com/jquery/3.6.0/jquery.min.js'
} }
] ]
}) })