|
@@ -0,0 +1,209 @@
|
|
|
+<template>
|
|
|
+ <my-dialog
|
|
|
+ :visible="visible"
|
|
|
+ header=""
|
|
|
+ :width="(width || 0) + 68"
|
|
|
+ attach="body"
|
|
|
+ :closeOnOverlayClick="false"
|
|
|
+ :footer="false"
|
|
|
+ @close="onClose"
|
|
|
+ >
|
|
|
+ <div class="table-loop" ref="tableLoop">
|
|
|
+ <div class="thead" ref="thead" :style="{ width: width + 'px' }">
|
|
|
+ <div class="td index">排名</div>
|
|
|
+ <div
|
|
|
+ class="td"
|
|
|
+ v-for="(item, index) in columns"
|
|
|
+ :key="index"
|
|
|
+ :style="createStyle(item.style)"
|
|
|
+ >
|
|
|
+ {{ item.label }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <swiper
|
|
|
+ v-if="hasData"
|
|
|
+ :key="swiperKey"
|
|
|
+ :style="{ height: 36 * rowNum + 'px', width: width + 'px' }"
|
|
|
+ :modules="modules"
|
|
|
+ direction="vertical"
|
|
|
+ :slides-per-view="rowNum"
|
|
|
+ :space-between="0"
|
|
|
+ :mousewheel="true"
|
|
|
+ :autoplay="{ delay: 1500 }"
|
|
|
+ >
|
|
|
+ <swiper-slide
|
|
|
+ class="slide"
|
|
|
+ v-for="(item, index) in data || []"
|
|
|
+ :key="index"
|
|
|
+ @click="rowClick(item)"
|
|
|
+ >
|
|
|
+ <div class="td index">
|
|
|
+ <div class="cell" v-if="index == 0"
|
|
|
+ ><img class="index" src="../../../assets/imgs/No1.png"
|
|
|
+ /></div>
|
|
|
+ <div class="cell" v-else-if="index == 1"
|
|
|
+ ><img class="index" src="../../../assets/imgs/No2.png"
|
|
|
+ /></div>
|
|
|
+ <div class="cell" v-else-if="index == 2"
|
|
|
+ ><img class="index" src="../../../assets/imgs/No3.png"
|
|
|
+ /></div>
|
|
|
+ <div class="cell" v-else>{{ index + 1 }}</div>
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="td"
|
|
|
+ v-for="(v, i) in columns"
|
|
|
+ :key="i"
|
|
|
+ :style="createStyle(v.style)"
|
|
|
+ >
|
|
|
+ <div class="cell">
|
|
|
+ <t-tooltip
|
|
|
+ v-if="v.prop !== 'rate'"
|
|
|
+ placement="top"
|
|
|
+ :content="item[v.prop] + ''"
|
|
|
+ >
|
|
|
+ <span>{{ item[v.prop] }}</span>
|
|
|
+ </t-tooltip>
|
|
|
+ <div class="process-box" v-else>
|
|
|
+ <div class="process" :style="{ width: item.rate }"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </swiper-slide>
|
|
|
+ </swiper>
|
|
|
+ <div v-else class="none-data">暂无数据</div>
|
|
|
+ </div>
|
|
|
+ </my-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup name="BigTableLoopDialog">
|
|
|
+import { ref, onMounted, computed, watch } from 'vue';
|
|
|
+import { Navigation, Mousewheel, Autoplay } from 'swiper';
|
|
|
+import { Swiper, SwiperSlide } from 'vue-awesome-swiper';
|
|
|
+import 'swiper/css';
|
|
|
+import 'swiper/css/autoplay';
|
|
|
+const visible = ref(false);
|
|
|
+const emits = defineEmits(['rowClick', 'close']);
|
|
|
+const props = defineProps({
|
|
|
+ data: Object,
|
|
|
+ columns: Array,
|
|
|
+ width: Number,
|
|
|
+});
|
|
|
+const modules = ref([Navigation, Mousewheel, Autoplay]);
|
|
|
+const swiperKey = ref(Date.now() + '');
|
|
|
+const tableLoop = ref();
|
|
|
+const tbodyHeight = ref(1);
|
|
|
+const rowNum = computed(() => {
|
|
|
+ return parseInt(tbodyHeight.value / 36);
|
|
|
+});
|
|
|
+const swiperWidth = ref(0);
|
|
|
+const thead = ref();
|
|
|
+const onClose = () => {
|
|
|
+ emits('close');
|
|
|
+};
|
|
|
+onMounted(() => {
|
|
|
+ visible.value = true;
|
|
|
+ setTimeout(() => {
|
|
|
+ let w = 0;
|
|
|
+ for (let i = 0; i < thead.value.children.length; i++) {
|
|
|
+ let node = thead.value.children[i];
|
|
|
+ w += node.offsetWidth;
|
|
|
+ }
|
|
|
+ swiperWidth.value = w;
|
|
|
+ }, 0);
|
|
|
+});
|
|
|
+const hasData = computed(() => {
|
|
|
+ return !!props.data?.length;
|
|
|
+});
|
|
|
+watch(hasData, () => {
|
|
|
+ swiperKey.value = Date.now() + '';
|
|
|
+});
|
|
|
+onMounted(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ tbodyHeight.value = tableLoop.value.offsetHeight - 46;
|
|
|
+ setTimeout(() => {
|
|
|
+ swiperKey.value = Date.now() + '';
|
|
|
+ });
|
|
|
+ }, 0);
|
|
|
+});
|
|
|
+
|
|
|
+const rowClick = (item) => {
|
|
|
+ console.log('item:', item);
|
|
|
+ emits('rowClick', item);
|
|
|
+};
|
|
|
+const createStyle = (styleObj) => {
|
|
|
+ let w = parseFloat(styleObj.width) * 2;
|
|
|
+ return { ...styleObj, width: w + 'px' };
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped>
|
|
|
+.table-loop {
|
|
|
+ height: 400px;
|
|
|
+ overflow: auto;
|
|
|
+ .none-data {
|
|
|
+ height: calc(100% - 36px);
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: #ccc;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ .thead {
|
|
|
+ height: 36px;
|
|
|
+ font-size: 12px;
|
|
|
+ .td {
|
|
|
+ text-align: center;
|
|
|
+ line-height: 36px;
|
|
|
+ color: #8c8c8c !important;
|
|
|
+ background-color: #f7f7f7;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .slide {
|
|
|
+ cursor: pointer;
|
|
|
+ &:hover {
|
|
|
+ background-color: #f7f7f7;
|
|
|
+ }
|
|
|
+ .td {
|
|
|
+ color: #262626;
|
|
|
+ .cell {
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ img.index {
|
|
|
+ height: 14px;
|
|
|
+ }
|
|
|
+ > span {
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .thead,
|
|
|
+ .slide {
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ .td {
|
|
|
+ display: inline-block;
|
|
|
+
|
|
|
+ height: 100%;
|
|
|
+ &.index {
|
|
|
+ width: 34px;
|
|
|
+ }
|
|
|
+ .process-box {
|
|
|
+ background-color: #d9d9d9;
|
|
|
+ height: 6px;
|
|
|
+ border-radius: 3px;
|
|
|
+ width: 90%;
|
|
|
+ overflow: hidden;
|
|
|
+ .process {
|
|
|
+ background-color: #4080ff;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|