row模式在移动端切换为card模式显示

This commit is contained in:
hi2hi 2024-12-18 04:04:23 +00:00
parent 836fddf860
commit d10386e6e9
7 changed files with 193 additions and 102 deletions

View File

@ -3,7 +3,7 @@ window.$$nazhuaConfig = {
// freeAmount: '白嫖', // 免费服务的费用名称 // freeAmount: '白嫖', // 免费服务的费用名称
// infinityCycle: '长期有效', // 无限周期名称 // infinityCycle: '长期有效', // 无限周期名称
// buyBtnText: '购买', // 购买按钮文案 // buyBtnText: '购买', // 购买按钮文案
// listServerItemType: 'row', // 服务器列表项类型 card/row row列表模式目前为体验版不兼容移动端 // listServerItemType: 'row', // 服务器列表项类型 card/row row列表模式移动端自动切换至card
// listServerStatusType: 'progress', // 服务器状态类型--列表 // listServerStatusType: 'progress', // 服务器状态类型--列表
// listServerRealTimeShowLoad: false, // 列表显示服务器实时负载 // listServerRealTimeShowLoad: false, // 列表显示服务器实时负载
// detailServerStatusType: 'progress', // 服务器状态类型--详情页 // detailServerStatusType: 'progress', // 服务器状态类型--详情页

View File

@ -21,6 +21,7 @@ const defaultState = () => ({
serverTime: 0, serverTime: 0,
serverGroup: [], serverGroup: [],
serverList: [], serverList: [],
serverListColumnWidths: {},
serverCount: { serverCount: {
total: 0, total: 0,
online: 0, online: 0,
@ -92,6 +93,9 @@ const store = createStore({
SET_SETTING(state, setting) { SET_SETTING(state, setting) {
state.setting = setting; state.setting = setting;
}, },
SET_SERVER_LIST_COLUMN_WIDTHS(state, widths) {
state.serverListColumnWidths = widths;
},
}, },
actions: { actions: {
/** /**
@ -184,6 +188,33 @@ const store = createStore({
} }
}); });
}, },
/**
* 设置服务器列表行宽度
*/
setServerListColumnWidths({
commit,
state,
}, data) {
const newWidths = {
...state.serverListColumnWidths,
...data,
};
commit('SET_SERVER_LIST_COLUMN_WIDTHS', newWidths);
},
setServerListColumnWidth({
commit,
state,
}, data) {
const newWidths = {
...state.serverListColumnWidths,
};
if (newWidths[data.prop]) {
newWidths[data.prop] = Math.max(newWidths[data.prop], data.width);
} else {
newWidths[data.prop] = data.width;
}
commit('SET_SERVER_LIST_COLUMN_WIDTHS', newWidths);
},
}, },
}); });

View File

@ -4,7 +4,10 @@
:class="`list-column--${prop}`" :class="`list-column--${prop}`"
:style="columnStyle" :style="columnStyle"
> >
<div class="list-column-content"> <div
ref="columnContentRef"
class="list-column-content"
>
<span class="item-label">{{ label }}</span> <span class="item-label">{{ label }}</span>
<div class="item-content"> <div class="item-content">
<template v-if="slotContent"> <template v-if="slotContent">
@ -34,7 +37,13 @@
import { import {
computed, computed,
ref,
onMounted,
onBeforeUnmount,
} from 'vue'; } from 'vue';
import {
useStore,
} from 'vuex';
const props = defineProps({ const props = defineProps({
prop: { prop: {
@ -67,11 +76,46 @@ const props = defineProps({
}, },
}); });
const store = useStore();
const columnContentRef = ref(null);
let resizeObserver = null;
const columnWidth = computed(() => store.state?.serverListColumnWidths?.[props.prop]);
onMounted(() => {
if (columnContentRef.value) {
resizeObserver = new ResizeObserver((entries) => {
entries.forEach((entry) => {
let { width } = entry.contentRect;
width = Math.ceil(width);
store.dispatch('setServerListColumnWidth', {
prop: props.prop,
width: width > 40 ? width : 40,
});
});
});
resizeObserver.observe(columnContentRef.value);
}
});
onBeforeUnmount(() => {
if (resizeObserver) {
resizeObserver.disconnect();
resizeObserver = null;
}
});
const columnStyle = computed(() => { const columnStyle = computed(() => {
const style = {}; const style = {};
const width = parseInt(props.width, 10); if (props.width) {
if (Number.isNaN(width) === false) { const width = parseInt(props.width, 10);
style.width = `${width}px`; if (Number.isNaN(width) === false) {
style.width = `${width}px`;
}
} else if (columnWidth.value > 0) {
style.width = `${columnWidth.value}px`;
} }
return style; return style;
}); });
@ -79,15 +123,23 @@ const columnStyle = computed(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.list-column { .list-column {
width: 60px; --list-column-label-height: 16px;
--list-column-value-height: 24px;
position: relative;
width: auto;
height: calc(var(--list-column-label-height) + var(--list-column-value-height) + 10px);
.list-column-content { .list-column-content {
--list-column-label-height: 16px; position: absolute;
--list-column-value-height: 24px; top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: max-content;
height: var(--list-item-height); height: var(--list-item-height);
.item-label { .item-label {

View File

@ -3,7 +3,6 @@
v-if="extraFields?.remainingTime" v-if="extraFields?.remainingTime"
prop="remaining-time" prop="remaining-time"
label="剩余" label="剩余"
:width="50"
:value="billAndPlan?.remainingTime?.value || '-'" :value="billAndPlan?.remainingTime?.value || '-'"
/> />
<server-list-column <server-list-column
@ -16,7 +15,6 @@
v-if="extraFields?.orderLink" v-if="extraFields?.orderLink"
prop="order-link" prop="order-link"
label="链接" label="链接"
:wdith="80"
:slot-content="true" :slot-content="true"
> >
<span <span

View File

@ -6,7 +6,6 @@
:label="item.label" :label="item.label"
:value="item.show ? item?.value : '-'" :value="item.show ? item?.value : '-'"
:unit="item.show ? item?.unit : ''" :unit="item.show ? item?.unit : ''"
:width="fieldWidth[item.key]"
/> />
</template> </template>
@ -43,12 +42,4 @@ const {
currentTime, currentTime,
serverRealTimeListTpls: props.serverRealTimeListTpls, serverRealTimeListTpls: props.serverRealTimeListTpls,
}); });
const fieldWidth = {
transfer: 80,
load: 40,
inSpeed: 40,
outSpeed: 40,
};
</script> </script>

View File

@ -8,60 +8,52 @@
}" }"
@click="openDetail" @click="openDetail"
> >
<div class="row-left-box"> <div class="list-column-item list-column-item--server-flag">
<div class="list-column-item list-column-item--server-flag"> <span
class="server-flag"
>
<span <span
class="server-flag" class="fi"
> :class="'fi-' + (info?.Host?.CountryCode || 'un')"
<span />
class="fi" </span>
:class="'fi-' + (info?.Host?.CountryCode || 'un')"
/>
</span>
</div>
<div class="list-column-item list-column-item--server-name">
<span
class="server-name"
:title="info.Name"
>
{{ info.Name }}
</span>
</div>
<server-list-column
prop="server-flag"
label="地区"
:value="info?.Host?.CountryCode?.toUpperCase() || 'UN'"
:width="40"
/>
<server-list-column
prop="server-system"
label="系统"
:value="platformSystemLabel || '-'"
/>
<server-list-column
prop="cpu-mem"
label="配置"
width="80"
:value="cpuAndMemAndDisk || '-'"
/>
</div> </div>
<div class="row-center-box"> <div class="list-column-item list-column-item--server-name">
<server-list-item-status <span
v-if="$config.nazhua.hideListItemStatusDonut !== true" class="server-name"
:info="info" :title="info.Name"
/> >
</div> {{ info.Name }}
<div class="row-right-box"> </span>
<server-list-item-real-time
v-if="$config.nazhua.hideListItemStat !== true"
:info="info"
server-real-time-list-tpls="load,inSpeed,outSpeed,transfer,duration"
/>
<server-list-item-bill
v-if="$config.nazhua.hideListItemBill !== true"
:info="info"
/>
</div> </div>
<server-list-column
prop="server-flag"
label="地区"
:value="info?.Host?.CountryCode?.toUpperCase() || 'UN'"
/>
<server-list-column
prop="server-system"
label="系统"
:value="platformSystemLabel || '-'"
/>
<server-list-column
prop="cpu-mem"
label="配置"
:value="cpuAndMemAndDisk || '-'"
/>
<server-list-item-status
v-if="$config.nazhua.hideListItemStatusDonut !== true"
:info="info"
/>
<server-list-item-real-time
v-if="$config.nazhua.hideListItemStat !== true"
:info="info"
server-real-time-list-tpls="load,inSpeed,outSpeed,transfer,duration"
/>
<server-list-item-bill
v-if="$config.nazhua.hideListItemBill !== true"
:info="info"
/>
</dot-dot-box> </dot-dot-box>
</template> </template>
@ -116,8 +108,8 @@ function openDetail() {
.server-list-row-item { .server-list-row-item {
--list-item-height: 64px; --list-item-height: 64px;
--list-item-border-radius: 8px; --list-item-border-radius: 8px;
--list-item-gap: 10px; --list-item-gap: 0;
--list-item-padding: 0; --list-item-padding: 0 20px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@ -129,23 +121,8 @@ function openDetail() {
filter: grayscale(1); filter: grayscale(1);
} }
.row-left-box, @media (max-width: 1280px) {
.row-center-box, --list-item-padding: 0 10px;
.row-right-box {
display: flex;
align-items: center;
gap: var(--list-item-gap);
}
.row-left-box,
.row-right-box {
flex: 1;
}
.row-right-box {
justify-content: flex-end;
}
.row-center-box {
justify-content: center;
} }
} }
@ -157,13 +134,20 @@ function openDetail() {
&--server-flag { &--server-flag {
--server-flag-size: 24px; --server-flag-size: 24px;
width: calc(var(--server-flag-size) * 1.5); width: calc(var(--server-flag-size) * 1.5);
margin-left: 20px;
.server-flag { .server-flag {
width: calc(var(--server-flag-size) * 1.5); width: calc(var(--server-flag-size) * 1.5);
height: var(--server-flag-size); height: var(--server-flag-size);
line-height: var(--server-flag-size); line-height: var(--server-flag-size);
font-size: var(--server-flag-size); font-size: var(--server-flag-size);
} }
@media (max-width: 1280px) {
display: none;
}
@media (max-width: 1024px) {
display: block;
}
} }
&--server-name { &--server-name {
width: 220px; width: 220px;
@ -177,6 +161,14 @@ function openDetail() {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
@media (max-width: 1280px) {
width: 180px;
}
@media (max-width: 1024px) {
width: 300px;
}
} }
} }
</style> </style>

View File

@ -13,6 +13,10 @@
<div <div
v-if="showFilter" v-if="showFilter"
class="fitler-group" class="fitler-group"
:class="{
'list-is-row': showListRow,
'list-is-card': showListCard,
}"
> >
<div class="left-box"> <div class="left-box">
<server-option-box <server-option-box
@ -30,13 +34,26 @@
</div> </div>
</div> </div>
<transition-group <transition-group
v-if="showListRow"
name="list" name="list"
tag="div" tag="div"
class="server-list-container" class="server-list-container"
:class="`server-list--${serverItemComponentName}`" :class="`server-list--row`"
> >
<component <server-row-item
:is="serverItemComponentMaps[serverItemComponentName]" v-for="item in filterServerList.list"
:key="item.ID"
:info="item"
/>
</transition-group>
<transition-group
v-if="showListCard"
name="list"
tag="div"
class="server-list-container"
:class="`server-list--card`"
>
<server-card-item
v-for="item in filterServerList.list" v-for="item in filterServerList.list"
:key="item.ID" :key="item.ID"
:info="item" :info="item"
@ -76,17 +93,22 @@ import ServerOptionBox from './components/server-list/server-option-box.vue';
import ServerCardItem from './components/server-list/card/server-list-item.vue'; import ServerCardItem from './components/server-list/card/server-list-item.vue';
import ServerRowItem from './components/server-list/row/server-list-item.vue'; import ServerRowItem from './components/server-list/row/server-list-item.vue';
const serverItemComponentMaps = {
card: ServerCardItem,
row: ServerRowItem,
};
const serverItemComponentName = [
'card',
'row',
].includes(config.nazhua.listServerItemType) ? config.nazhua.listServerItemType : 'card';
const store = useStore(); const store = useStore();
const worldMapWidth = ref(); const worldMapWidth = ref();
const windowWidth = ref(window.innerWidth);
const showListRow = computed(() => {
if (windowWidth.value > 1024) {
return config.nazhua.listServerItemType === 'row';
}
return false;
});
const showListCard = computed(() => {
if (windowWidth.value > 1024) {
return config.nazhua.listServerItemType !== 'row';
}
return true;
});
const showFilter = computed(() => config.nazhua.hideFilter !== true); const showFilter = computed(() => config.nazhua.hideFilter !== true);
const filterFormData = ref({ const filterFormData = ref({
@ -246,6 +268,7 @@ const showWorldMap = computed(() => {
*/ */
function handleResize() { function handleResize() {
worldMapWidth.value = document.querySelector('.server-list-container').clientWidth - 40; worldMapWidth.value = document.querySelector('.server-list-container').clientWidth - 40;
windowWidth.value = window.innerWidth;
} }
onMounted(() => { onMounted(() => {
@ -285,6 +308,10 @@ onUnmounted(() => {
gap: 10px 20px; gap: 10px 20px;
width: var(--list-container-width); width: var(--list-container-width);
margin: auto; margin: auto;
&.list-is-card {
padding: 0 20px;
}
} }
.server-list-container.server-list--card { .server-list-container.server-list--card {