This commit is contained in:
kk
2026-07-08 18:00:33 +08:00
commit e66b4a3680
312 changed files with 54718 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
<template>
<div class="concat-panel">
<div class="concat-stage" :style="stageSize">
<div class="concat-top" :style="topStyle"></div>
<div class="concat-bottom" :style="bottomStyle"></div>
</div>
<track-slider
ref="slider"
hint="按住滑块,对齐上下图案"
:locked="locked"
@drag="handleDrag"
@release="handleRelease"
/>
</div>
</template>
<script>
import TrackSlider from './track-slider.vue';
export default {
name: 'concatPanel',
components: { TrackSlider },
props: {
data: {
type: Object,
required: true,
},
locked: {
type: Boolean,
default: false,
},
},
emits: ['confirm'],
data() {
return {
moveX: 0,
};
},
computed: {
// 舞台尺寸以服务端下发的逻辑尺寸为准,避免前后端各存一份常量产生偏差
stageSize() {
return { width: `${this.data.width}px`, height: `${this.data.height}px` };
},
topStyle() {
return {
height: `${this.data.sliceY}px`,
backgroundImage: `url(${this.data.image})`,
backgroundSize: `${this.data.width}px ${this.data.height}px`,
backgroundPosition: '0 0',
};
},
// 下条以背景横向循环平移实现推回复位,纵向偏移对准切缝以下的内容
bottomStyle() {
return {
height: `${this.data.height - this.data.sliceY}px`,
backgroundImage: `url(${this.data.image})`,
backgroundSize: `${this.data.width}px ${this.data.height}px`,
backgroundPosition: `${this.moveX}px -${this.data.sliceY}px`,
};
},
},
watch: {
// 更换题目后下条回到初始错位状态
data() {
this.moveX = 0;
this.$refs.slider?.reset();
},
},
methods: {
// 滑轨行程映射整幅画布宽度的循环位移
handleDrag(progress) {
this.moveX = Math.round(progress * this.data.width);
},
handleRelease() {
this.$emit('confirm', String(this.moveX));
},
},
};
</script>
<style scoped>
.concat-stage {
position: relative;
border-radius: 12px;
overflow: hidden;
user-select: none;
}
.concat-stage::after {
content: '';
position: absolute;
inset: 0;
border-radius: 12px;
box-shadow: inset 0 0 0 1px rgba(17, 24, 39, 0.08);
pointer-events: none;
}
.concat-top,
.concat-bottom {
width: 100%;
background-repeat: repeat-x;
}
</style>