This commit is contained in:
李志鹏
2026-04-24 09:38:25 +08:00
6 changed files with 243 additions and 125 deletions

View File

@@ -1,4 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.32243 7.4255L9.409 10.5121C9.43299 10.5361 9.46897 10.5441 9.50096 10.5321C9.53294 10.5201 9.55293 10.4881 9.55293 10.4561V2.94757C9.55293 2.69968 9.75284 2.49977 10.0007 2.49977C10.2486 2.49977 10.4485 2.69968 10.4485 2.94757V10.4561C10.4485 10.4921 10.4685 10.5201 10.5005 10.5321C10.5325 10.5441 10.5685 10.5401 10.5925 10.5121L13.679 7.4255C13.851 7.25758 14.1468 7.25758 14.3147 7.4255C14.3987 7.50946 14.4467 7.6254 14.4467 7.74535C14.4467 7.86529 14.3987 7.97724 14.3147 8.0652L10.1287 12.2513C10.0607 12.3192 9.93676 12.3192 9.86879 12.2513L5.68272 8.0652C5.59876 7.98124 5.55078 7.86529 5.55078 7.74535C5.55078 7.6254 5.59876 7.51346 5.68272 7.4255C5.85064 7.25758 6.1505 7.25758 6.31843 7.4255H6.32243Z" fill="white"/>
<path d="M17.1966 12.6064C16.9487 12.6064 16.7488 12.8064 16.7488 13.0542V16.2528C16.7488 16.4447 16.5929 16.6046 16.397 16.6046H3.60289C3.41098 16.6046 3.25106 16.4487 3.25106 16.2528V13.0542C3.25106 12.8064 3.05115 12.6064 2.80326 12.6064C2.55538 12.6064 2.35547 12.8064 2.35547 13.0542V16.2528C2.35547 16.9404 2.91521 17.5002 3.60289 17.5002H16.397C17.0847 17.5002 17.6444 16.9404 17.6444 16.2528V13.0542C17.6444 12.8064 17.4445 12.6064 17.1966 12.6064Z" fill="white"/>
<svg width="26" height="20" viewBox="0 0 26 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 18.6667H25.3333V20H0V18.6667ZM18 8.39067L13.3333 13.0573V0H12V13.0573L7.33333 8.39067L6.39067 9.33333L12.6667 15.6093L18.9427 9.33333L18 8.39067Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 284 B

View File

@@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.32243 7.42574L9.409 10.5123C9.43299 10.5363 9.46897 10.5443 9.50096 10.5323C9.53294 10.5203 9.55293 10.4883 9.55293 10.4563V2.94781C9.55293 2.69992 9.75284 2.50002 10.0007 2.50002C10.2486 2.50002 10.4485 2.69992 10.4485 2.94781V10.4563C10.4485 10.4923 10.4685 10.5203 10.5005 10.5323C10.5325 10.5443 10.5685 10.5403 10.5925 10.5123L13.679 7.42574C13.851 7.25782 14.1468 7.25782 14.3147 7.42574C14.3987 7.5097 14.4467 7.62565 14.4467 7.74559C14.4467 7.86554 14.3987 7.97749 14.3147 8.06545L10.1287 12.2515C10.0607 12.3195 9.93676 12.3195 9.86879 12.2515L5.68272 8.06545C5.59876 7.98148 5.55078 7.86554 5.55078 7.74559C5.55078 7.62565 5.59876 7.5137 5.68272 7.42574C5.85064 7.25782 6.1505 7.25782 6.31843 7.42574H6.32243Z" fill="currentColor"/>
<path d="M17.1966 12.6062C16.9487 12.6062 16.7488 12.8061 16.7488 13.054V16.2525C16.7488 16.4444 16.5929 16.6044 16.397 16.6044H3.60289C3.41098 16.6044 3.25106 16.4484 3.25106 16.2525V13.054C3.25106 12.8061 3.05115 12.6062 2.80326 12.6062C2.55538 12.6062 2.35547 12.8061 2.35547 13.054V16.2525C2.35547 16.9402 2.91521 17.4999 3.60289 17.4999H16.397C17.0847 17.4999 17.6444 16.9402 17.6444 16.2525V13.054C17.6444 12.8061 17.4445 12.6062 17.1966 12.6062Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
import { ref, onMounted, onUnmounted, reactive, toRefs } from 'vue'
const props = defineProps({
url: {
type: String,
@@ -12,79 +12,89 @@ const props = defineProps({
price: {
type: String,
default: '111'
},
download: {
type: Boolean,
default: false
}
})
const emit = defineEmits([
'addShopping',
'openDetail'
])
let data = reactive({
})
const emit = defineEmits(['addShopping', 'openDetail', 'download'])
let data = reactive({})
const addShopping = () => {
if (props.download) {
emit('download')
} else {
emit('addShopping')
}
}
const openDetail = () => {
emit('openDetail')
}
onMounted(()=>{
})
onUnmounted(()=>{
})
onMounted(() => {})
onUnmounted(() => {})
defineExpose({})
const {} = toRefs(data);
const {} = toRefs(data)
</script>
<template>
<div class="commodity-item">
<img :src="props.url" alt="" @click="openDetail">
<div class="commodity-item" :class="{ 'is-download': download }">
<img :src="props.url" alt="" @click="openDetail" />
<div class="detail">
<div class="text">
<div class="name">
{{ props.name }}
</div>
<div class="price">
<div class="price" :class="{ 'is-download': download }">
{{ props.price }}
</div>
</div>
<div class="btn" @click="addShopping">
<div class="text">
<SvgIcon name="add" size="26"></SvgIcon>
<SvgIcon :name="download ? 'download' : 'add'" size="26" color="#232323"></SvgIcon>
</div>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.commodity-item{
width: var(--commodity-width,100%);
> img{
.commodity-item {
width: var(--commodity-width, 100%);
&.is-download{
img{
cursor: initial;
}
}
> img {
width: 100%;
cursor: pointer;
height: var(--commodity-height,auto);
margin-bottom: var(--commodity-marginBottom,1rem);
height: var(--commodity-height, auto);
margin-bottom: var(--commodity-marginBottom, 1rem);
}
> .detail{
> .detail {
display: flex;
justify-content: space-between;
align-items: center;
> .text{
> .text {
color: #232323;
> .name{
font-family: "KaiseiOpti-Regular";
> .name {
font-family: 'KaiseiOpti-Regular';
font-weight: 400;
font-size: var(--commodity-name-fontSize,1.6rem);
line-height: var(--commodity-name-lineHeight,2.3rem);
margin-bottom: var(--commodity-name-marginBottom,0rem);
font-size: var(--commodity-name-fontSize, 1.6rem);
line-height: var(--commodity-name-lineHeight, 2.3rem);
margin-bottom: var(--commodity-name-marginBottom, 0rem);
}
> .price{
font-family: "KaiseiOpti-Regular";
> .price {
font-family: 'KaiseiOpti-Regular';
font-weight: 400;
font-size: var(--commodity-price-fontSize,1.4rem);
line-height: var(--commodity-price-lineHeight,2.3rem);
font-size: var(--commodity-price-fontSize, 1.4rem);
line-height: var(--commodity-price-lineHeight, 2.3rem);
&.is-download {
color: #979797;
}
}
}
.btn{
}
.btn {
cursor: pointer;
}
}
}
</style>

View File

@@ -49,28 +49,52 @@
</div>
</aside>
<section class="wardrobe-assets__content flex flex-1 flex-col">
<section
class="wardrobe-assets__content flex flex-1 flex-col"
:class="{ 'has-data': dataList.length }"
>
<div class="assets-toolbar">
<div class="assets-toolbar__selection">
<div class="select-count flex align-center">
<img src="@/assets/images/wardrobe/select.png" />
<span class="assets-toolbar__count">{{ selectedCount }} Selected</span>
<div class="assets-toolbar__link">Select All</div>
<div class="assets-toolbar__link">Deselect All</div>
</div>
<div class="assets-toolbar__link" @click="handleSelectAll(true)">Select All</div>
<div class="assets-toolbar__link" @click="handleSelectAll(false)">Deselect All</div>
</div>
<div class="assets-toolbar__actions">
<div
class="assets-toolbar__download flex flex-center"
:class="{ disabled: selectedCount < 1 }"
@click="handleDownloadSelected"
>
<SvgIcon name="download" color="#fff" />
<SvgIcon name="downloadBtn" color="#fff" />
<span>Download Selected</span>
</div>
</div>
</div>
<div v-if="dataList.length" class="data-list-container">
<div class="data-list datalist">
<div class="item" v-for="item in dataList" :key="item.url">
<CommodityItem :url="item.url" :name="item.title" :price="item.price"></CommodityItem>
<div ref="dataListRef" class="data-list">
<div
v-for="(item, index) in dataList"
:key="item.url"
class="item"
:class="{ 'is-last-column': isLastColumn(index) }"
>
<img
v-show="item.checked"
src="@/assets/images/wardrobe/checked.png"
@click="handleSelectItem(item)"
class="checkbox"
/>
<div v-show="!item.checked" class="checkbox" @click="handleSelectItem(item)" />
<CommodityItem
download
:url="item.url"
:name="item.title"
:price="item.price"
></CommodityItem>
</div>
</div>
</div>
@@ -90,7 +114,7 @@
</div>
</template>
<script setup lang="ts">
import { computed, ref, reactive, watch } from 'vue'
import { computed, nextTick, onMounted, onUnmounted, reactive, ref, shallowRef, watch } from 'vue'
import { useRouter } from 'vue-router'
import img from '@/assets/images/collectionStory/Rectangle.png'
@@ -130,44 +154,55 @@ const dataList = ref([
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
},
{
url: img,
title: 'Windswept Burden',
price: '$100.00'
price: '$100.00',
checked: false
}
])
const dataListRef = ref<HTMLDivElement | null>(null)
const gridColumnCount = shallowRef(1)
let gridResizeObserver: ResizeObserver | null = null
watch(
() => filters,
@@ -177,7 +212,9 @@ watch(
{ deep: true }
)
const selectedCount = computed(() => 0)
const selectedCount = computed(() => {
return dataList.value.filter((el) => el.checked === true).length
})
const allCategoriesSelected = computed(() => {
return (
filters.categories.length === categoryValues.length &&
@@ -216,9 +253,63 @@ const clearFilters = () => {
filters.gender = 'all'
}
const handleSelectItem = (item) => {
console.log('111', item)
item.checked = !item.checked
}
const handleSelectAll = (flag) => {
dataList.value.forEach((item) => {
item.checked = flag
})
}
const handleDownloadSelected = () => {
const items = dataList.value.filter((item) => item.checked)
console.log(items)
}
const updateGridColumnCount = () => {
if (!dataListRef.value) {
gridColumnCount.value = 1
return
}
const templateColumns = window.getComputedStyle(dataListRef.value).gridTemplateColumns
const columnCount =
templateColumns && templateColumns !== 'none'
? templateColumns.split(' ').filter(Boolean).length
: 1
gridColumnCount.value = Math.max(columnCount, 1)
}
const isLastColumn = (index: number) => {
return (index + 1) % gridColumnCount.value === 0
}
const goToDigitalItems = () => {
router.push('/digitalItem')
}
onMounted(() => {
nextTick(() => {
updateGridColumnCount()
if (!dataListRef.value || typeof ResizeObserver === 'undefined') {
return
}
gridResizeObserver = new ResizeObserver(() => {
updateGridColumnCount()
})
gridResizeObserver.observe(dataListRef.value)
})
})
onUnmounted(() => {
gridResizeObserver?.disconnect()
})
</script>
<style lang="less" scoped>
.c-svg {
@@ -350,8 +441,10 @@ const goToDigitalItems = () => {
}
.wardrobe-assets__content {
min-width: 0;
border-right: 0.05rem solid #585858;
// &.has-data {
// border: none;
// }
.assets-toolbar {
display: flex;
@@ -368,34 +461,26 @@ const goToDigitalItems = () => {
}
.assets-toolbar__selection {
font-family: 'KaiseiOpti-Regular';
.select-count {
column-gap: 1.2rem;
img{
width: 2.4rem;
height: 2.4rem ;
}
.assets-toolbar__count {
position: relative;
padding-left: 1.8rem;
font-family: 'KaiseiOpti-Regular';
font-size: 1.4rem;
line-height: 1.2;
color: #57524b;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 1rem;
height: 1rem;
background: #232323;
transform: translateY(-50%);
}
}
.assets-toolbar__link {
border: 0;
padding: 0;
background: transparent;
cursor: pointer;
font-family: 'KaiseiOpti-Regular';
font-size: 1.4rem;
line-height: 1.2;
color: #a0978b;
text-decoration: underline;
}
@@ -425,21 +510,41 @@ const goToDigitalItems = () => {
.data-list-container {
overflow-y: auto;
.datalist {
padding-bottom: 8rem;
&::-webkit-scrollbar {
display: none;
}
.data-list {
width: 100%;
flex: 1;
display: grid;
align-content: start;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr));
padding: 0.05rem 0 0 0.05rem;
border-top: 0.05rem solid #585858;
border-left: 0.05rem solid #585858;
.item {
width: 100%;
min-width: 0;
padding: 1.2rem;
border: 0.05rem solid #585858;
margin-left: -0.05rem;
margin-top: -0.05rem;
background: #ffffff;
position: relative;
box-sizing: border-box;
border-bottom: 0.05rem solid #585858;
&:not(.is-last-column) {
border-right: 0.05rem solid #585858;
}
.checkbox {
position: absolute;
top: 1.2rem;
left: 1.2rem;
width: 2.4rem;
height: 2.4rem;
border: 0.15rem solid #585858;
cursor: pointer;
}
:deep(.commodity-item) {
width: 100%;