添加 老项目的代码 参考
This commit is contained in:
@@ -0,0 +1,505 @@
|
||||
<template>
|
||||
<ScrollWithBar>
|
||||
<div class="clothes-box" ref="containerRef" v-if="props.allMyClothes">
|
||||
<el-row>
|
||||
<el-col
|
||||
:xs="12"
|
||||
:sm="6"
|
||||
:md="4"
|
||||
:lg="3"
|
||||
:xl="2"
|
||||
v-for="item in _clothes"
|
||||
:key="item.clothId"
|
||||
>
|
||||
<div class="item">
|
||||
<template v-if="item.clothType === 'suit'">
|
||||
<div class="suit">
|
||||
<el-image
|
||||
class="cover-img"
|
||||
:src="item.suitList[0].thumbnailFileUrl"
|
||||
fit="cover"
|
||||
lazy
|
||||
:scroll-container="containerRef"
|
||||
/>
|
||||
|
||||
<div class="suit-bottomCloth">
|
||||
<el-image
|
||||
:src="item.suitList[1].thumbnailFileUrl"
|
||||
fit="fill"
|
||||
lazy
|
||||
:scroll-container="containerRef"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<el-image
|
||||
class="cover-img"
|
||||
:src="item.thumbnailFileUrl"
|
||||
fit="cover"
|
||||
lazy
|
||||
:scroll-container="containerRef"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-if="item.fileStatus === 'enable'">
|
||||
<div class="mutiple">
|
||||
<MyIcons
|
||||
:type="
|
||||
props.roomClothes?.some((i) => i.clothId === item.clothId)
|
||||
? 'selected'
|
||||
: 'noSelected'
|
||||
"
|
||||
cursor="pointer"
|
||||
:size="16"
|
||||
class="checkbox"
|
||||
@click="mutipleRoomSelectClothing(item)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="disable-mask">
|
||||
<span> {{ $t('tips.training') }} </span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div class="clothes-box" ref="containerRef" v-if="props.clothes">
|
||||
<el-row>
|
||||
<el-col
|
||||
:xs="12"
|
||||
:sm="6"
|
||||
:md="4"
|
||||
:lg="3"
|
||||
:xl="2"
|
||||
v-for="(item, index) in _clothes"
|
||||
:key="index"
|
||||
>
|
||||
<div class="item">
|
||||
<template v-if="item.clothType === 'suit'">
|
||||
<div class="suit">
|
||||
<el-image
|
||||
class="cover-img"
|
||||
:src="item.suitList[0].thumbnailFileUrl"
|
||||
fit="cover"
|
||||
lazy
|
||||
:scroll-container="containerRef"
|
||||
/>
|
||||
|
||||
<div class="suit-bottomCloth">
|
||||
<el-image
|
||||
:src="item.suitList[1].thumbnailFileUrl"
|
||||
fit="fill"
|
||||
lazy
|
||||
:scroll-container="containerRef"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<el-image
|
||||
class="cover-img"
|
||||
:src="item.thumbnailFileUrl"
|
||||
fit="cover"
|
||||
lazy
|
||||
:scroll-container="containerRef"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-if="item.fileStatus === 'enable'">
|
||||
<template v-if="props.mutipleMode">
|
||||
<div class="mutiple">
|
||||
<MyIcons
|
||||
:type="
|
||||
(
|
||||
item.clothType === 'suit'
|
||||
? selectMutipleClothesIds?.some(
|
||||
(i) =>
|
||||
i.toString() ==
|
||||
JSON.parse(item.thumbnailFileUrl)
|
||||
.map((i: any) => i.clothId)
|
||||
.toString()
|
||||
)
|
||||
: selectMutipleClothesIds?.includes(item.clothId)
|
||||
)
|
||||
? 'selected'
|
||||
: 'noSelected'
|
||||
"
|
||||
cursor="pointer"
|
||||
:size="16"
|
||||
class="checkbox"
|
||||
@click="mutipleSelectClothing(item)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="tool-mask" v-else>
|
||||
<div class="tool-header">
|
||||
<template v-if="props.mine">
|
||||
<span @click="onDelete(item)">{{ $t('tips.delete') }}</span>
|
||||
<span @click="onLink(item)">{{ $t('tips.buyLink') }}</span>
|
||||
<span @click="onUploadMultipleImg(item)">{{ $t('tips.more') }}</span>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<span v-if="item.isHas === 'no'" @click="addToMyClothes(item)">{{
|
||||
$t('tips.addToCloset')
|
||||
}}</span>
|
||||
<span v-else @click="unJoinFromMyClothes(item)">{{ $t('cancel') }}</span>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="tool-footer">
|
||||
<span @click="selectClothing(item)">{{ $t('tips.select') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="disable-mask">
|
||||
<span> {{ $t('tips.training') }} </span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div class="clothes-box" v-if="props.urls">
|
||||
<el-row>
|
||||
<el-col
|
||||
:xs="4"
|
||||
:sm="4"
|
||||
:md="4"
|
||||
:lg="4"
|
||||
:xl="4"
|
||||
v-for="(item, index) in urlsRaw"
|
||||
:key="index"
|
||||
>
|
||||
<div
|
||||
class="item history"
|
||||
:class="{
|
||||
noTop: index > 5,
|
||||
haveLeft: (index + 1) % 6 == 1
|
||||
}"
|
||||
>
|
||||
<el-image
|
||||
class="cover-img"
|
||||
:src="item.url"
|
||||
fit="cover"
|
||||
:preview-src-list="
|
||||
creatingAndFailMarkList.some((mark) => item.url.includes(mark))
|
||||
? []
|
||||
: props.urls
|
||||
.filter((i) => !creatingAndFailMarkList.some((mark) => i.url.includes(mark)))
|
||||
.map((i) => i.url)
|
||||
"
|
||||
preview-teleported
|
||||
:initial-index="index"
|
||||
:infinite="false"
|
||||
/>
|
||||
|
||||
<div class="tool-mask">
|
||||
<div class="delete">
|
||||
<span @click="onDeleteHistory(item)">{{ $t('tips.delete') }}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="preview"
|
||||
v-if="!creatingAndFailMarkList.some((mark) => item.url.includes(mark))"
|
||||
>
|
||||
<div>{{ $t('tips.preview') }}</div>
|
||||
|
||||
<el-image
|
||||
class="previewSit"
|
||||
:src="item.url"
|
||||
:preview-src-list="
|
||||
props.urls
|
||||
.map((i) => i.url)
|
||||
.filter((i) => !creatingAndFailMarkList.some((mark) => i.includes(mark)))
|
||||
"
|
||||
preview-teleported
|
||||
:initial-index="index"
|
||||
:infinite="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<template v-if="(props.clothes && !props.clothes.length) || (props.urls && !props.urls.length)">
|
||||
<el-empty description="暂无数据" />
|
||||
</template>
|
||||
</ScrollWithBar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import ScrollWithBar from '@/components/ScrollWithBar.vue'
|
||||
import { type IClotheList, type IClothType, type IClotheInfo } from '@/interface'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
|
||||
const { t } = useI18n()
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const { creatingAndFailMarkList, selectMutipleClothesIds } = storeToRefs(globalStore)
|
||||
const { updateSelectMutileClothesIds } = globalStore
|
||||
|
||||
const containerRef = ref()
|
||||
|
||||
type IProps = {
|
||||
clothes?: IClotheList
|
||||
allMyClothes?: IClotheList
|
||||
roomClothes?: IClotheList
|
||||
urls?: { historyId: string; url: string }[]
|
||||
paddingRight?: number
|
||||
mine?: boolean
|
||||
mutipleMode?: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
|
||||
const urlsRaw = toRaw(props.urls)
|
||||
|
||||
const _clothes = computed(() =>
|
||||
(props.clothes || props.allMyClothes)?.map((i) => {
|
||||
let suitList = []
|
||||
if (i.clothType === 'suit') {
|
||||
suitList = JSON.parse(i.thumbnailFileUrl)
|
||||
}
|
||||
|
||||
return { ...i, suitList }
|
||||
})
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
addToMyClothes: [{ clothType: IClothType; clothId: string }]
|
||||
unJoinFromMyClothes: [{ clothId: string }]
|
||||
selectClothing: [data: IClotheInfo]
|
||||
deleteClothing: [data: IClotheInfo]
|
||||
onDeleteHistory: [data: any]
|
||||
onUploadMultipleImg: [data: IClotheInfo]
|
||||
onUploadLink: [data: { clothId: string; buyLink: string }]
|
||||
mutipleSelectClothing: [data: IClotheInfo[]]
|
||||
addOrRmRoomCloth: [data: IClotheInfo]
|
||||
}>()
|
||||
|
||||
const addToMyClothes = (data: IClotheInfo) => emit('addToMyClothes', data)
|
||||
|
||||
const unJoinFromMyClothes = (data: IClotheInfo) => emit('unJoinFromMyClothes', data)
|
||||
|
||||
const selectClothing = (data: IClotheInfo) => emit('selectClothing', data)
|
||||
|
||||
const onDelete = (item: IClotheInfo) => emit('deleteClothing', item)
|
||||
|
||||
const onDeleteHistory = (item: { historyId: string; url: string }) => emit('onDeleteHistory', item)
|
||||
|
||||
const onLink = (item: IClotheInfo) => {
|
||||
// console.log('AT-[ onLink &&&&&********** ]', item)
|
||||
|
||||
// alert('缺少添加购买链接接口和相关的字段')
|
||||
if (!item.buyLink) {
|
||||
ElMessageBox.prompt(t('tips.inputBuyLink'), {
|
||||
confirmButtonText: t('tips.confirmText'),
|
||||
cancelButtonText: t('tips.cancelText'),
|
||||
confirmButtonClass: 'custom-message-btn',
|
||||
cancelButtonClass: 'custom-cancel-message-btn',
|
||||
customClass: 'custom-message-box',
|
||||
inputValidator(val) {
|
||||
try {
|
||||
new URL(val)
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
inputErrorMessage: t('tips.inputErrorMessage')
|
||||
}).then(async ({ value }) => {
|
||||
emit('onUploadLink', { clothId: item.clothId, buyLink: value })
|
||||
})
|
||||
} else {
|
||||
window.location.href = item.buyLink
|
||||
}
|
||||
}
|
||||
|
||||
const onUploadMultipleImg = (item: IClotheInfo) => emit('onUploadMultipleImg', item)
|
||||
|
||||
const mutipleSelectClothing = (item: IClotheInfo) => {
|
||||
updateSelectMutileClothesIds(item.clothId, item)
|
||||
// updateSelectedCloth(item)
|
||||
}
|
||||
|
||||
const mutipleRoomSelectClothing = (item: any) => {
|
||||
// console.log('AT-[ item &&&&&********** ]', item)
|
||||
emit('addOrRmRoomCloth', item)
|
||||
}
|
||||
|
||||
const paddingRight = `${props.paddingRight === undefined ? 10 : props.paddingRight}px`
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$border: 0.5px solid rgba(0, 0, 0, 1);
|
||||
|
||||
.clothes-box {
|
||||
padding-right: v-bind(paddingRight);
|
||||
|
||||
.item {
|
||||
border: $border;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-top: 150%;
|
||||
overflow: hidden;
|
||||
|
||||
.cover-img {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: block;
|
||||
> img {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.suit-bottomCloth {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
transform: translateY(-100%);
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tool-mask {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: none;
|
||||
// display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
|
||||
> div {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
> span {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-header {
|
||||
height: 65%;
|
||||
flex-direction: column;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.delete {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.previewSit {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
background-color: pink;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-footer {
|
||||
flex: 1;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.mutiple {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
.checkbox {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 10px;
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
|
||||
.disable-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.history {
|
||||
// border: $border;
|
||||
box-sizing: border-box;
|
||||
border: $border;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.noTop {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.haveLeft {
|
||||
border-left: $border;
|
||||
}
|
||||
.havetop {
|
||||
border-top: $border;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div class="clothes-pool">
|
||||
<div class="tip">
|
||||
{{ $t('tips.select') }} <span>{{ selectedRoomInfo?.roomName }}</span>
|
||||
</div>
|
||||
|
||||
<div class="pool-box">
|
||||
<ClothesBox
|
||||
@addOrRmRoomCloth="props.addOrRmRoomCloth"
|
||||
:roomClothes="props.roomClothes"
|
||||
:allMyClothes="props.allMyClothes"
|
||||
mutipleMode
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import type { IClotheList, IClotheInfo } from '@/interface'
|
||||
// import api from '@/plugins/axios'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
|
||||
// const emit = defineEmits<{
|
||||
// addOrRmRoomCloth: [data: IClotheInfo]
|
||||
// }>()
|
||||
|
||||
const props = defineProps<{
|
||||
allMyClothes: IClotheList
|
||||
roomClothes: IClotheList
|
||||
addOrRmRoomCloth: (item: IClotheInfo) => Promise<void>
|
||||
}>()
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const { selectedRoomInfo } = storeToRefs(globalStore)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.clothes-pool {
|
||||
padding-left: 10px;
|
||||
// padding-right: 20px;
|
||||
border-right: 0.5px solid #000;
|
||||
height: 100%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -5px;
|
||||
width: 9px;
|
||||
height: 1px;
|
||||
background-color: #000;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.pool-box {
|
||||
height: calc(100% - 38px);
|
||||
overflow: hidden;
|
||||
border-top: 0.5px solid #000;
|
||||
border-left: 0.5px solid #000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,259 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import type { IRoomInfo } from '@/interface'
|
||||
import IconAdd from '@/components/icons/IconAdd.vue'
|
||||
import IconDelete from '@/components/icons/IconDelete.vue'
|
||||
import IconEdit from '@/components/icons/IconEdit.vue'
|
||||
import IconLink from '@/components/icons/IconLink.vue'
|
||||
import api from '@/plugins/axios'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const { updateRoomInfo } = globalStore
|
||||
|
||||
const { selectedRoomInfo, gender } = storeToRefs(globalStore)
|
||||
|
||||
const props = defineProps<{
|
||||
roomList: IRoomInfo[]
|
||||
freshRoomList: () => Promise<void>
|
||||
getRoomListLoading: boolean
|
||||
}>()
|
||||
|
||||
const input = ref('')
|
||||
|
||||
const inputRoomRef = ref()
|
||||
|
||||
const tempRoomName = ref('')
|
||||
|
||||
const status = ref(false)
|
||||
|
||||
// const activeRoomItem = ref<IRoomItem>()
|
||||
|
||||
type IRoomItem = Omit<IRoomInfo, 'createTime'> & { selected: boolean; edit?: boolean }
|
||||
|
||||
type IState = IRoomItem[]
|
||||
|
||||
const state = ref<IState>([])
|
||||
|
||||
watchEffect(() => {
|
||||
state.value = props.roomList.map((i) => Object.assign({ ...i, selected: false }))
|
||||
})
|
||||
|
||||
const handleEdit = (item: IRoomItem) => {
|
||||
state.value.map((val) => {
|
||||
val.edit = false
|
||||
if (val.roomId === item.roomId) {
|
||||
val.edit = true
|
||||
}
|
||||
return val
|
||||
})
|
||||
}
|
||||
|
||||
const editInput = (value: string, index: number) => {
|
||||
state.value[index].roomName = value
|
||||
}
|
||||
|
||||
const handleSelect = (item: IRoomItem) => {
|
||||
// activeRoomItem.value = item
|
||||
|
||||
updateRoomInfo(item)
|
||||
}
|
||||
|
||||
const updateRoom = async (item: IRoomItem) => {
|
||||
if (status.value) {
|
||||
return
|
||||
}
|
||||
|
||||
status.value = true
|
||||
|
||||
if (item.roomName) {
|
||||
await api.updateRoom({ roomId: item.roomId, roomName: item.roomName })
|
||||
}
|
||||
|
||||
await props.freshRoomList()
|
||||
|
||||
status.value = false
|
||||
}
|
||||
|
||||
const handleDelete = async (item: IRoomItem) => {
|
||||
await api.deleteRoom({ roomId: item.roomId })
|
||||
|
||||
props.freshRoomList()
|
||||
}
|
||||
|
||||
const add = async () => {
|
||||
if (!input.value) {
|
||||
return
|
||||
}
|
||||
|
||||
await api.addRoom({ roomName: input.value, sex: gender.value })
|
||||
inputRoomRef.value.clear()
|
||||
props.freshRoomList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<div class="dropdown-menu" v-loading="props.getRoomListLoading">
|
||||
<div class="dropdown-item" v-for="(item, i) in state" :key="i">
|
||||
<div class="dropdown-item-name">
|
||||
<div class="botBox">
|
||||
<span
|
||||
:class="{
|
||||
bot: item.roomId != selectedRoomInfo?.roomId,
|
||||
activeBot: item.roomId === selectedRoomInfo?.roomId
|
||||
}"
|
||||
></span>
|
||||
</div>
|
||||
<span
|
||||
:class="{ text: true, activeText: item.roomId === selectedRoomInfo?.roomId }"
|
||||
@click="handleSelect(item)"
|
||||
>
|
||||
<template v-if="!item.edit">{{ item.roomName }}</template>
|
||||
|
||||
<template v-else>
|
||||
<el-input
|
||||
:model-value="(tempRoomName = item.roomName)"
|
||||
@input="(val: string) => editInput(val, i)"
|
||||
autofocus
|
||||
style="width: 140px"
|
||||
size="small"
|
||||
class="edit-input"
|
||||
maxlength="9"
|
||||
@blur="() => updateRoom(item)"
|
||||
@keyup.enter="() => updateRoom(item)"
|
||||
/>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dropdown-item-operating">
|
||||
<el-icon class="dropdown-item-icon" size="16">
|
||||
<IconLink />
|
||||
</el-icon>
|
||||
<el-icon @click="handleEdit(item)" class="dropdown-item-icon" size="13">
|
||||
<IconEdit />
|
||||
</el-icon>
|
||||
<el-icon @click="handleDelete(item)" class="dropdown-item-icon" size="14">
|
||||
<IconDelete />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="add_fittingRoom">
|
||||
<el-input
|
||||
v-model="input"
|
||||
ref="inputRoomRef"
|
||||
style="width: 240px; border: 1px solid #000000"
|
||||
placeholder="添加专题试衣间"
|
||||
@blur="add"
|
||||
@keyup.enter="add"
|
||||
maxlength="9"
|
||||
>
|
||||
<template #suffix>
|
||||
<div class="add_icon" @click="add"><IconAdd /></div>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.edit-input {
|
||||
& :deep(.el-input__wrapper) {
|
||||
// --el-button-active-color: 'none' !important;
|
||||
// border-radius: 0 !important;
|
||||
// box-shadow: none !important;
|
||||
box-shadow: 0 0 0 1px #000 inset !important;
|
||||
box-shadow: #000 !important;
|
||||
border-radius: 0 !important;
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
}
|
||||
.dropdown-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.add_fittingRoom {
|
||||
& :deep(.el-input__wrapper) {
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
border-radius: 0 !important;
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
// margin-top: 120px;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
justify-content: space-between;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.dropdown-item-name {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.botBox {
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.bot {
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: 50%;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.text {
|
||||
max-width: 150px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.activeText {
|
||||
color: #776ce6;
|
||||
}
|
||||
|
||||
.activeBot {
|
||||
display: inline-block;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
background: #776ce6;
|
||||
}
|
||||
}
|
||||
|
||||
.add_icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dropdown-item-operating {
|
||||
flex: 0 0 60px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.dropdown-item-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div class="baby-select">
|
||||
<div class="select-box">
|
||||
<div class="baby-select-header" @click.stop="handleClickHeader">
|
||||
{{ items.selected }}
|
||||
<img class="arrow" :class="{ rotate: isShowSelect }" :src="arrowDownIcon" alt="" />
|
||||
</div>
|
||||
|
||||
<div class="hide-select" v-if="isShowSelect" ref="target" @click.stop="handelSelect">
|
||||
{{ items.option }} <img class="arrow" :src="arrowDownIcon" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="select-main" type="input" @click="() => open()">
|
||||
<MyIcons type="preson" :size="50" class="person" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useFileDialog, onClickOutside } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import arrowDownIcon from '@/assets/imgs/arrow_down.png'
|
||||
import MyIcons from '@/components/MyIcons.vue'
|
||||
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
|
||||
const globalStore = useGlobalStore()
|
||||
const { updateGender } = globalStore
|
||||
const { gender } = storeToRefs(globalStore)
|
||||
|
||||
enum IEnumMaps {
|
||||
BOY = 'male',
|
||||
GIRL = 'female'
|
||||
}
|
||||
|
||||
type IEmitTypes = {
|
||||
onChange: [gender: 'male' | 'female']
|
||||
onFileChange: [formData: FormData]
|
||||
}
|
||||
|
||||
const emit = defineEmits<IEmitTypes>()
|
||||
|
||||
const target = ref(null)
|
||||
|
||||
const isShowSelect = ref(false)
|
||||
|
||||
type IItems = { selected: 'GIRL'; option: 'BOY' } | { selected: 'BOY'; option: 'GIRL' }
|
||||
|
||||
const items = ref<IItems>(
|
||||
gender.value === 'female'
|
||||
? { selected: 'GIRL', option: 'BOY' }
|
||||
: { selected: 'BOY', option: 'GIRL' }
|
||||
)
|
||||
|
||||
const {
|
||||
files,
|
||||
open,
|
||||
onChange: onFileChange
|
||||
} = useFileDialog({ accept: 'image/*', multiple: false })
|
||||
|
||||
onFileChange(() => {
|
||||
console.log('AT-[ files &&&&&********** ]', files.value)
|
||||
|
||||
if (files?.value) {
|
||||
const file = files?.value[0]
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
|
||||
emit('onFileChange', formData)
|
||||
}
|
||||
})
|
||||
|
||||
onClickOutside(target, () => {
|
||||
isShowSelect.value = false
|
||||
})
|
||||
|
||||
const handelSelect = () => {
|
||||
isShowSelect.value = false
|
||||
|
||||
items.value =
|
||||
items.value.selected === 'BOY'
|
||||
? { selected: 'GIRL', option: 'BOY' }
|
||||
: { selected: 'BOY', option: 'GIRL' }
|
||||
|
||||
updateGender(IEnumMaps[items.value.selected])
|
||||
|
||||
emit('onChange', IEnumMaps[items.value.selected])
|
||||
}
|
||||
|
||||
const handleClickHeader = () => {
|
||||
isShowSelect.value = !isShowSelect.value
|
||||
}
|
||||
|
||||
emit('onChange', IEnumMaps[items.value.selected])
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$border1: 0.5px solid #000;
|
||||
|
||||
.bordeer1 {
|
||||
border: $border1;
|
||||
}
|
||||
|
||||
.baby-select {
|
||||
width: 78px;
|
||||
// height: 102px;
|
||||
// width: 100%;
|
||||
height: calc(100% - 1px);
|
||||
background-color: #fff;
|
||||
position: relative;
|
||||
border: $border1;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
margin: 0 auto;
|
||||
|
||||
.select-box {
|
||||
.baby-select-header {
|
||||
height: 27px;
|
||||
width: 100%;
|
||||
background: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
}
|
||||
.arrow {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
transform: rotate(-180deg);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.rotate {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.hide-select {
|
||||
@extend .baby-select-header;
|
||||
|
||||
transition: all 0.3s;
|
||||
background-color: #7b68ee;
|
||||
border: $border1;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
display: flex;
|
||||
|
||||
& .arrow {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-main {
|
||||
height: calc(100% - 27px);
|
||||
}
|
||||
|
||||
.person {
|
||||
width: 50px;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,244 @@
|
||||
<template>
|
||||
<div class="clothes-box" v-if="isShow">
|
||||
<el-row>
|
||||
<el-col :xs="4" :sm="4" :md="4" :lg="4" :xl="4" v-for="(item, index) in urlsRaw" :key="index">
|
||||
<div
|
||||
class="item history"
|
||||
:class="{
|
||||
noTop: index > 5,
|
||||
haveLeft: (index + 1) % 6 == 1
|
||||
}"
|
||||
style="overflow: auto"
|
||||
>
|
||||
<el-image class="cover-img" v-lazy="item.url" :src="item.url" :lazy="true" />
|
||||
|
||||
<div class="tool-mask" v-if="false">
|
||||
<div class="delete">
|
||||
<span @click="onDeleteHistory(item)">{{ $t('tips.delete') }}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="preview"
|
||||
v-if="!creatingAndFailMarkList.some((mark) => item.url.includes(mark))"
|
||||
>
|
||||
<div>{{ $t('tips.preview') }}</div>
|
||||
|
||||
<el-image
|
||||
class="previewSit"
|
||||
v-lazy="item.url"
|
||||
:lazy="true"
|
||||
:src="item.url"
|
||||
:preview-src-list="
|
||||
(props.urls || [])
|
||||
.map((i) => i.url)
|
||||
.filter((i) => !creatingAndFailMarkList.some((mark) => i.includes(mark)))
|
||||
"
|
||||
preview-teleported
|
||||
:initial-index="index"
|
||||
:infinite="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
// import { emit } from 'vite'
|
||||
import { type IClotheList } from '@/interface'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
|
||||
const isShow = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
console.log('AT-[ onMounted &&&&&********** ]')
|
||||
|
||||
setTimeout(() => {
|
||||
isShow.value = true
|
||||
}, 500)
|
||||
})
|
||||
|
||||
// const { t } = useI18n()
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
type IProps = {
|
||||
clothes?: IClotheList
|
||||
allMyClothes?: IClotheList
|
||||
roomClothes?: IClotheList
|
||||
urls?: { historyId: string; url: string }[]
|
||||
paddingRight?: number
|
||||
mine?: boolean
|
||||
mutipleMode?: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
|
||||
const urlsRaw = toRaw(props.urls)
|
||||
|
||||
const emit = defineEmits<{
|
||||
onDeleteHistory: [data: { historyId: string; url: string }]
|
||||
}>()
|
||||
|
||||
const onDeleteHistory = (item: { historyId: string; url: string }) => emit('onDeleteHistory', item)
|
||||
|
||||
const { creatingAndFailMarkList, selectMutipleClothesIds } = storeToRefs(globalStore)
|
||||
const { updateSelectMutileClothesIds } = globalStore
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$border: 0.5px solid rgba(0, 0, 0, 1);
|
||||
|
||||
.clothes-box {
|
||||
padding-right: v-bind(paddingRight);
|
||||
|
||||
.item {
|
||||
border: $border;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-top: 150%;
|
||||
overflow: hidden;
|
||||
|
||||
.cover-img {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: block;
|
||||
> img {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.suit-bottomCloth {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
transform: translateY(-100%);
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tool-mask {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: none;
|
||||
// display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
|
||||
> div {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
> span {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-header {
|
||||
height: 65%;
|
||||
flex-direction: column;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.delete {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.previewSit {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
background-color: pink;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-footer {
|
||||
flex: 1;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.mutiple {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
.checkbox {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 10px;
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
|
||||
.disable-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.history {
|
||||
// border: $border;
|
||||
box-sizing: border-box;
|
||||
border: $border;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.noTop {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.haveLeft {
|
||||
border-left: $border;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<div class="history-scroll" v-infinite-scroll="load" :infinite-scroll-distance="50">
|
||||
<template v-if="data?.length">
|
||||
<el-checkbox-group @change="checkboxChange" :model-value="props.checked">
|
||||
<div v-for="(it, idx) in data" :key="idx" class="block-date">
|
||||
<div class="history-tip">
|
||||
<div class="createTime">{{ it.createTime }}</div>
|
||||
|
||||
<div class="checkbox-btn">
|
||||
<el-checkbox :value="idx" :label="$t('tips.selectAll')" size="small" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-row>
|
||||
<el-col
|
||||
:xs="4"
|
||||
:sm="4"
|
||||
:md="4"
|
||||
:lg="4"
|
||||
:xl="4"
|
||||
v-for="(item, index) in it.clothList"
|
||||
:key="item.historyId"
|
||||
>
|
||||
<div
|
||||
class="item history"
|
||||
:class="{
|
||||
noTop: index > 5,
|
||||
haveLeft: (index + 1) % 6 == 1,
|
||||
havetop: index + 1 <= 6
|
||||
}"
|
||||
>
|
||||
<el-image class="cover-img" :src="item.url" fit="cover" :lazy="true" />
|
||||
|
||||
<div class="tool-mask">
|
||||
<div class="delete">
|
||||
<span @click="onDeleteHistory(item)">{{ $t('tips.delete') }}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="preview"
|
||||
v-if="!creatingAndFailMarkList.some((mark) => item.url.includes(mark))"
|
||||
>
|
||||
<div>{{ $t('tips.preview') }}</div>
|
||||
|
||||
<el-image
|
||||
class="previewSit"
|
||||
:src="item.url"
|
||||
:preview-src-list="
|
||||
it.clothList
|
||||
.map((i) => i.url)
|
||||
.filter((i) => !creatingAndFailMarkList.some((mark) => i.includes(mark)))
|
||||
"
|
||||
preview-teleported
|
||||
:initial-index="
|
||||
it.clothList
|
||||
.map((i) => i.url)
|
||||
.filter((i) => !creatingAndFailMarkList.some((mark) => i.includes(mark)))
|
||||
.findIndex((i) => i == item.url)
|
||||
"
|
||||
:infinite="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
type IProps = {
|
||||
historyList?: { createTime: string; clothList: { historyId: string; url: string }[] }[]
|
||||
checked: number[]
|
||||
paddingRight?: number
|
||||
}
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
onDeleteHistory: [data: any]
|
||||
onHistoryCheckListCHange: [value: number[]]
|
||||
}>()
|
||||
|
||||
const historyCheckListModel = defineModel()
|
||||
|
||||
const checkboxChange = (value: any) => {
|
||||
emit('onHistoryCheckListCHange', value)
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
console.log(
|
||||
'AT-[ historyCheckListModel xxxxxxxxxxxxxxxx ------------------------------ ]',
|
||||
historyCheckListModel.value
|
||||
)
|
||||
})
|
||||
|
||||
const data = ref<IProps['historyList']>([])
|
||||
|
||||
const count = ref(0)
|
||||
|
||||
const { creatingAndFailMarkList } = storeToRefs(globalStore)
|
||||
|
||||
watchEffect(() => {
|
||||
data.value = props.historyList?.slice(0, count.value)
|
||||
})
|
||||
|
||||
const onDeleteHistory = (item: { historyId: string; url: string }) => emit('onDeleteHistory', item)
|
||||
|
||||
const load = () => {
|
||||
console.log('AT-[ props.historyList?.length &&&&&********** ]', props.historyList?.length)
|
||||
console.log('AT-[ count.value &&&&&********** ]', count.value)
|
||||
|
||||
if (props.historyList) {
|
||||
if (count.value >= props.historyList.length) {
|
||||
return
|
||||
}
|
||||
|
||||
count.value = count.value + 5
|
||||
data.value = props.historyList?.slice(0, count.value)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$border: 0.5px solid rgba(0, 0, 0, 1);
|
||||
|
||||
.history-scroll {
|
||||
// background-color: red;
|
||||
overflow-y: scroll;
|
||||
// height: 60%;
|
||||
height: 100%;
|
||||
scrollbar-width: 0;
|
||||
|
||||
.block-date {
|
||||
margin: 0 10px;
|
||||
|
||||
.history-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 10px;
|
||||
color: #7a7a7a;
|
||||
|
||||
& :deep(.el-checkbox) {
|
||||
color: #87909e;
|
||||
}
|
||||
|
||||
& :deep(.is-checked) {
|
||||
.el-checkbox__inner {
|
||||
background-color: #87909e;
|
||||
}
|
||||
}
|
||||
|
||||
& :deep(.el-checkbox__label) {
|
||||
color: #87909e;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
& :deep(.el-checkbox__inner) {
|
||||
border-color: #87909e;
|
||||
background-color: #87909e;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
border: $border;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-top: 150%;
|
||||
overflow: hidden;
|
||||
|
||||
.cover-img {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: block;
|
||||
> img {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.suit-bottomCloth {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
width: 50%;
|
||||
transform: translateY(-100%);
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.tool-mask {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: none;
|
||||
// display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
|
||||
> div {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
> span {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-header {
|
||||
height: 65%;
|
||||
flex-direction: column;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.delete {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.preview {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.previewSit {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 2;
|
||||
background-color: pink;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-footer {
|
||||
flex: 1;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.mutiple {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
.checkbox {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 10px;
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
|
||||
.disable-mask {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.history {
|
||||
// border: $border;
|
||||
box-sizing: border-box;
|
||||
border: $border;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.noTop {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.haveLeft {
|
||||
border-left: $border;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,175 @@
|
||||
<script lang="ts" setup>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import type { INavStatus, IMainNav, ISubNav, IRoomInfo } from '@/interface'
|
||||
import { MENU_CONFIG } from '@/constants'
|
||||
import { MenuEnum } from '@/enum/MenuEnum'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const { menu } = storeToRefs(globalStore)
|
||||
|
||||
const visible = ref(false)
|
||||
|
||||
const props = defineProps<{
|
||||
alertHandle: () => void
|
||||
roomList: IRoomInfo[]
|
||||
freshRoomList: () => void
|
||||
getRoomListLoading: boolean
|
||||
roomMode: boolean
|
||||
}>()
|
||||
|
||||
type IEmitTypes = {
|
||||
onMenuChange: [navStatus: INavStatus]
|
||||
}
|
||||
|
||||
// const navStatus = reactive<INavStatus>({
|
||||
// mainNav: MenuEnum.CLOTHES_LIBRARY,
|
||||
// subNav: MenuEnum.ALL
|
||||
// })
|
||||
const navStatus = reactive<INavStatus>({ ...menu.value })
|
||||
|
||||
watchEffect(() => {
|
||||
navStatus.mainNav = menu.value.mainNav
|
||||
navStatus.subNav = menu.value.subNav
|
||||
})
|
||||
|
||||
const emit = defineEmits<IEmitTypes>()
|
||||
|
||||
const selectMainNav = (mainNav: IMainNav) => {
|
||||
if (navStatus.mainNav != mainNav) {
|
||||
navStatus.mainNav = mainNav
|
||||
emit('onMenuChange', navStatus)
|
||||
}
|
||||
}
|
||||
|
||||
const selectSubNav = (value: any) => {
|
||||
// console.log('AT-[ selectSubNav &&&&&********** ]', value)
|
||||
// const allSubNavVals: ISubNav[] = [
|
||||
// MenuEnum.ALL,
|
||||
// MenuEnum.UPPER_OUTER_GARMENT,
|
||||
// MenuEnum.BOTTOMS,
|
||||
// MenuEnum.DRESS,
|
||||
// MenuEnum.SUIT
|
||||
// ]
|
||||
const allSubNavVals = MENU_CONFIG.value.filter((i) => i.status).map((i) => i.value)
|
||||
|
||||
if (allSubNavVals.includes(value) && navStatus.subNav != value) {
|
||||
navStatus.subNav = value
|
||||
emit('onMenuChange', navStatus)
|
||||
}
|
||||
}
|
||||
|
||||
const visibleChange = (val: any) => {
|
||||
visible.value = val
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="menu">
|
||||
<div
|
||||
:class="{
|
||||
item: true,
|
||||
selected: props.roomMode ? false : navStatus.mainNav === MenuEnum.CLOTHES_LIBRARY
|
||||
}"
|
||||
@click="selectMainNav(MenuEnum.CLOTHES_LIBRARY)"
|
||||
>
|
||||
<!-- 衣服库 -->
|
||||
{{ $t('nav.clothLib') }}
|
||||
</div>
|
||||
|
||||
<div class="item" @click="selectMainNav(MenuEnum.MY_WARDROBE)">
|
||||
<el-dropdown placement="bottom-start" trigger="hover" @visible-change="visibleChange">
|
||||
<span
|
||||
:class="{ selected: props.roomMode ? false : navStatus.mainNav === MenuEnum.MY_WARDROBE }"
|
||||
>
|
||||
<!-- 我的衣橱 -->
|
||||
{{ $t('nav.myCloset') }}
|
||||
</span>
|
||||
<template v-slot:dropdown>
|
||||
<div v-if="visible" class="dropdownContainer">
|
||||
<DropdownMenu
|
||||
:roomList="props.roomList"
|
||||
:freshRoomList="props.freshRoomList"
|
||||
:getRoomListLoading="props.getRoomListLoading"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
/
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="item in MENU_CONFIG"
|
||||
:key="item.name"
|
||||
:class="{
|
||||
item: true,
|
||||
disabledContent: !item.status,
|
||||
selected: navStatus.subNav === item.value
|
||||
}"
|
||||
@click="item.status ? selectSubNav(item.value) : props.alertHandle()"
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu {
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
padding-bottom: 10px;
|
||||
margin-left: 16px;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
|
||||
.item {
|
||||
padding: 10px 4px 0;
|
||||
cursor: pointer;
|
||||
line-height: 24px;
|
||||
height: 24px;
|
||||
user-select: none;
|
||||
|
||||
span {
|
||||
line-height: 24px;
|
||||
height: 24px;
|
||||
display: inline-block;
|
||||
color: #000000;
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selected {
|
||||
//background: red;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
height: 1.5px;
|
||||
background: #000;
|
||||
width: 10px;
|
||||
bottom: -4px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
.disabledContent {
|
||||
color: #88909d;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.dropdownContainer {
|
||||
width: 240px;
|
||||
border: 1px solid #000000;
|
||||
padding: 20px 25px 20px 30px;
|
||||
}
|
||||
.el-popper__arrow {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<div class="model-item-card" :class="{ active: props.active }" ref="containerRef">
|
||||
<el-image :src="thumbnailFileUrl" fit="cover" style="width: 78px; height: 117px" />
|
||||
|
||||
<div class="tool-bar" v-show="!props.mutipleMode">
|
||||
<div class="header">
|
||||
<span @click="onDelete">{{ $t('tips.delete') }}</span>
|
||||
<span @click="onModify">{{ $t('tips.modifyFace') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<span @click="selectModel">{{ $t('tips.select') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mutiple" v-if="props.mutipleMode">
|
||||
<MyIcons
|
||||
:type="checkboxIconName"
|
||||
cursor="pointer"
|
||||
:size="16"
|
||||
class="checkbox"
|
||||
@click="mutipleSelectModel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
type IProps = {
|
||||
size?: number
|
||||
mutipleMode?: boolean
|
||||
checkboxStatus?: boolean
|
||||
active: boolean
|
||||
modelInfo: IModelInfo
|
||||
}
|
||||
|
||||
import { ref } from 'vue'
|
||||
import MyIcons from '@/components/MyIcons.vue'
|
||||
import { type IModelInfo } from '@/interface'
|
||||
|
||||
const containerRef = ref(null)
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
|
||||
// const { size = 15, active = false, modelInfo } = props
|
||||
|
||||
const checkboxIconName = computed(() =>
|
||||
props.mutipleMode && props.checkboxStatus ? 'selected' : 'noSelected'
|
||||
)
|
||||
|
||||
const { thumbnailFileUrl } = props.modelInfo
|
||||
|
||||
const width = `${props.size}px`
|
||||
|
||||
const emit = defineEmits<{
|
||||
selectModel: [modelInfo: IModelInfo]
|
||||
deletetModel: [modelInfo: IModelInfo]
|
||||
modifyModel: [modelInfo: IModelInfo]
|
||||
onMutipleSelectModel: [modelInfo: IModelInfo, checkboxStatus: boolean]
|
||||
}>()
|
||||
|
||||
const selectModel = () => emit('selectModel', props.modelInfo)
|
||||
|
||||
const mutipleSelectModel = () => emit('onMutipleSelectModel', props.modelInfo, props.checkboxStatus)
|
||||
|
||||
const onDelete = () => {
|
||||
emit('deletetModel', props.modelInfo)
|
||||
}
|
||||
|
||||
const onModify = () => {
|
||||
emit('modifyModel', props.modelInfo)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$border1px: 0.5px solid #000;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.model-item-card {
|
||||
width: v-bind(width);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.active {
|
||||
border: $border1px;
|
||||
filter: grayscale(0) !important;
|
||||
|
||||
& :deep(.el-image) {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
filter: grayscale(0%);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
filter: grayscale(0);
|
||||
|
||||
border: $border1px;
|
||||
|
||||
.tool-bar {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
& :deep(.el-image) {
|
||||
filter: grayscale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
& :deep(.el-image) {
|
||||
display: block;
|
||||
font-size: 0;
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.tool-bar {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
display: none;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
> .header,
|
||||
.footer {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
> span {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
// background-color: rgba(0, 0, 0, 0.5);
|
||||
font-size: 10px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
font-size: 12px;
|
||||
// background-color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.mutiple {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 8;
|
||||
|
||||
.checkbox {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 10px;
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="my-button">{{ text }}</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive } from 'vue'
|
||||
|
||||
type IProps = {
|
||||
text: string
|
||||
type?: 'light' | 'dark'
|
||||
}
|
||||
|
||||
const { text, type = 'light' } = defineProps<IProps>()
|
||||
const lightStyle = reactive({ bgColor: 'rgba(255, 255, 255, 0.8)', fontColor: '#000' })
|
||||
|
||||
const darkStyle = reactive({ bgColor: 'rgba(0, 0, 0, 0.8)', fontColor: '#fff' })
|
||||
|
||||
const style = computed(() => (type === 'light' ? lightStyle : darkStyle))
|
||||
|
||||
const { fontColor, bgColor } = style.value
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-button {
|
||||
width: 90px;
|
||||
height: 36px;
|
||||
border: 0.5px solid #000;
|
||||
box-sizing: border-box;
|
||||
font-size: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
color: v-bind(fontColor);
|
||||
background-color: v-bind(bgColor);
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9;
|
||||
font-weight: bolder;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="my-card">my-card</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-card {
|
||||
border: 1px solid #000;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="my-icons">
|
||||
<img :src="icon" alt="" class="icon" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import arrowDownIcon from '@/assets/imgs/arrow_down.png'
|
||||
import closeIcon from '@/assets/imgs/close.png'
|
||||
import hairIcon from '@/assets/imgs/hair_upload.png'
|
||||
import multipleBarIcon from '@/assets/imgs/multiple.png'
|
||||
import multipleActivatedBarIcon from '@/assets/imgs/multipleActivated.png'
|
||||
import noSelectedIcon from '@/assets/imgs/noSelected.png'
|
||||
import personIcon from '@/assets/imgs/person.png'
|
||||
import searchIcon from '@/assets/imgs/search.png'
|
||||
import selectedIcon from '@/assets/imgs/selected.png'
|
||||
import singleBarIcon from '@/assets/imgs/single.png'
|
||||
import singleActivatedBarIcon from '@/assets/imgs/singleActivated.png'
|
||||
import uploadIcon from '@/assets/imgs/upload.png'
|
||||
import uploadEnIcon from '@/assets/imgs/uploadEn.png'
|
||||
import videoPlayIcon from '@/assets/imgs/video_play.png'
|
||||
|
||||
import i18n from '@/i18n'
|
||||
|
||||
const { locale } = i18n.global
|
||||
|
||||
type IProps = {
|
||||
type:
|
||||
| 'single'
|
||||
| 'singleActivated'
|
||||
| 'multiple'
|
||||
| 'multipleActivated'
|
||||
| 'arrow'
|
||||
| 'preson'
|
||||
| 'selected'
|
||||
| 'noSelected'
|
||||
| 'close'
|
||||
| 'video'
|
||||
| 'upload'
|
||||
| 'search'
|
||||
size?: number
|
||||
cursor?: string
|
||||
}
|
||||
|
||||
const props = defineProps<IProps>()
|
||||
const { type, size, cursor = 'default' } = toRefs(props)
|
||||
|
||||
const mapsRef = ref(
|
||||
new Map([
|
||||
['single', singleBarIcon],
|
||||
['singleActivated', singleActivatedBarIcon],
|
||||
['multiple', multipleBarIcon],
|
||||
['multipleActivated', multipleActivatedBarIcon],
|
||||
['arrow', arrowDownIcon],
|
||||
['preson', personIcon],
|
||||
['selected', selectedIcon],
|
||||
['noSelected', noSelectedIcon],
|
||||
['close', closeIcon],
|
||||
['video', videoPlayIcon],
|
||||
['upload', uploadIcon],
|
||||
['search', searchIcon],
|
||||
['hair', hairIcon]
|
||||
])
|
||||
)
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.type === 'upload') {
|
||||
mapsRef.value.set('upload', locale.value == 'zh' ? uploadIcon : uploadEnIcon)
|
||||
}
|
||||
})
|
||||
|
||||
const icon = computed(() => mapsRef.value.get(type.value))
|
||||
|
||||
const height = `${size.value || 15}px`
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-icons {
|
||||
display: inline;
|
||||
|
||||
.icon {
|
||||
height: v-bind(height);
|
||||
cursor: v-bind(cursor);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,428 @@
|
||||
<template>
|
||||
<ScrollWithBar>
|
||||
<div class="pick-And-upload-image">
|
||||
<div class="tip">
|
||||
{{ $t('tips.upload') }} <span>{{ subNavText }}</span>
|
||||
</div>
|
||||
|
||||
<el-upload
|
||||
:fileList="fileList"
|
||||
:auto-upload="true"
|
||||
:headers="{ 'X-Access-Token': cookies.get('token') }"
|
||||
action="/api/cloth/uploadClothFile"
|
||||
multiple
|
||||
accept="image/*"
|
||||
class="custom-uploader"
|
||||
list-type="picture-card"
|
||||
:on-success="uploadSuccess"
|
||||
:before-upload="beforeUpload"
|
||||
ref="uploadRef"
|
||||
:limit="20"
|
||||
>
|
||||
<template #trigger>
|
||||
<div class="trigger-icon">
|
||||
<MyIcons :size="89" :type="nav.clothType == 'hair' ? 'hair' : 'upload'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #file="{ file }">
|
||||
<img class="thumbnail" :src="file.url" alt="" />
|
||||
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span class="el-upload-list__item-delete" @click="handleRemove(file)">
|
||||
<el-icon><CircleClose /></el-icon>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-upload>
|
||||
|
||||
<!-- <p class="prompt">(1-8张,效果越多越好)</p> -->
|
||||
<p class="prompt" v-if="nav.clothType == 'hair'">{{ $t('tips.uploadTip') }}</p>
|
||||
|
||||
<el-input
|
||||
:placeholder="$t('tips.placeholder')"
|
||||
size="large"
|
||||
class="link-input"
|
||||
v-model="linkText"
|
||||
>
|
||||
<template #prefix>
|
||||
<IconLink />
|
||||
</template>
|
||||
<template #suffix>
|
||||
<div class="grabButton" @click="grabImage">{{ $t('tips.pickImg') }}</div>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<div class="grab-img-list">
|
||||
<el-row>
|
||||
<el-col
|
||||
v-for="(item, index) in grapImgList"
|
||||
:key="index"
|
||||
:lg="2"
|
||||
:md="4"
|
||||
:sm="6"
|
||||
:xl="2"
|
||||
:xs="12"
|
||||
>
|
||||
<div class="grap-image" @click="handleSelect(item)">
|
||||
<el-image :src="item.fileUrl" class="cover-img" fit="cover" lazy />
|
||||
|
||||
<span
|
||||
class="cover-icon"
|
||||
:class="{ active: fileList.some((i) => i.name === item.id) }"
|
||||
>
|
||||
<el-icon
|
||||
class="icon-item"
|
||||
v-if="fileList.some((i) => i.name === item.id)"
|
||||
color="#fff"
|
||||
>
|
||||
<SuccessFilled />
|
||||
</el-icon>
|
||||
</span>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="upload-btn">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
v-model="isSyncClothesLibrary"
|
||||
@change="handleSyncToClothingLibrary"
|
||||
>{{ $t('tips.sync') }}</el-checkbox
|
||||
>
|
||||
<MyButton
|
||||
style="width: 151px; height: 36px; margin-left: 5px"
|
||||
:text="$t('tips.upload')"
|
||||
@click="handleUpload"
|
||||
></MyButton>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollWithBar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CircleClose, SuccessFilled } from '@element-plus/icons-vue'
|
||||
|
||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||
|
||||
import { ElMessageBox, ElLoading, type UploadUserFile, type UploadProps } from 'element-plus'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import IconLink from '@/components/icons/IconLink.vue'
|
||||
import MyButton from '@/components/MyButton.vue'
|
||||
import ScrollWithBar from '@/components/ScrollWithBar.vue'
|
||||
import { MENU_CONFIG } from '@/constants'
|
||||
import api from '@/plugins/axios'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
import { getLocalImageSize } from '@/utils'
|
||||
|
||||
const cookies = useCookies(['locale'])
|
||||
|
||||
const fileList = ref<UploadUserFile[]>([])
|
||||
|
||||
const grapImgList = ref<Record<'fileUrl' | 'id' | 'thumbnailFileUrl', string>[]>([])
|
||||
|
||||
const linkText = ref<string>()
|
||||
const isSyncClothesLibrary = ref<boolean>(true)
|
||||
const globalStore = useGlobalStore()
|
||||
const { menu, nav, gender } = storeToRefs(globalStore)
|
||||
|
||||
const emit = defineEmits<{
|
||||
onUploadSuccess: []
|
||||
}>()
|
||||
|
||||
type IStatus = {
|
||||
imgUploading: boolean
|
||||
}
|
||||
|
||||
const status = reactive<IStatus>({
|
||||
imgUploading: false
|
||||
})
|
||||
|
||||
const uploadRef = ref()
|
||||
|
||||
const handleRemove = (file: any) => {
|
||||
const name = file?.response?.result?.id || file?.name
|
||||
|
||||
const newFileList = fileList.value.filter((i) => i.name != name)
|
||||
|
||||
fileList.value = newFileList
|
||||
}
|
||||
|
||||
const subNavText = computed(
|
||||
() => MENU_CONFIG.value.find((item) => item.value === menu.value.subNav)?.name
|
||||
)
|
||||
|
||||
const reset = () => {
|
||||
// isSyncClothesLibrary.value = false
|
||||
fileList.value = []
|
||||
linkText.value = ''
|
||||
grapImgList.value = []
|
||||
}
|
||||
|
||||
// 切换tab 清空数据
|
||||
watch(subNavText, () => reset())
|
||||
|
||||
const grabImage = async () => {
|
||||
linkText.value && (await isValidURL(linkText.value))
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '抓取中',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
const { result } = await api.grabPicture({ grabUrl: linkText.value })
|
||||
|
||||
grapImgList.value = result
|
||||
loading.close()
|
||||
}
|
||||
|
||||
const successListMarkRef = ref<any[]>([])
|
||||
|
||||
const uploadSuccess = (response: any, uploadFile: any, uploadFiles: any) => {
|
||||
successListMarkRef.value.push(uploadFile)
|
||||
|
||||
const { id: name, fileUrl: url } = response.result
|
||||
|
||||
fileList.value.push({ name, url })
|
||||
|
||||
const allUids = uploadFiles.map((i: any) => i.uid)
|
||||
|
||||
const successedUids = successListMarkRef.value.map((i) => i.uid)
|
||||
|
||||
status.imgUploading = !allUids.every((uid: number) => successedUids.includes(uid))
|
||||
}
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = async (rawFile) => {
|
||||
if (!rawFile.type.startsWith('image/')) {
|
||||
ElMessage.error('请选择正确的图片')
|
||||
return Promise.reject()
|
||||
}
|
||||
|
||||
const size = await getLocalImageSize(rawFile)
|
||||
|
||||
// console.log('AT-[ size xxxxxx &&&&&********** ]', size)
|
||||
|
||||
if (size.width < 500) {
|
||||
ElMessage.error('为确保效果,请上传500像素以上的图片')
|
||||
return Promise.reject()
|
||||
}
|
||||
|
||||
status.imgUploading = true
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const handleSelect = async (item: any) => {
|
||||
console.log('AT-[ handleSelect &&&&&********** ]')
|
||||
// 判断图片是否已存在
|
||||
const existingFile = fileList.value.find((file) => item.fileUrl === file.url)
|
||||
|
||||
if (!existingFile) {
|
||||
// 手动上传
|
||||
const imageUrl = item.fileUrl
|
||||
const response = await fetch(imageUrl)
|
||||
const blob = await response.blob()
|
||||
const file = new File([blob], item.id, { type: blob.type })
|
||||
uploadRef.value.handleStart(file)
|
||||
|
||||
// 添加到列表
|
||||
fileList.value.push({
|
||||
name: item.id,
|
||||
url: item.fileUrl
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const handleSyncToClothingLibrary = (val: any) => {
|
||||
isSyncClothesLibrary.value = val
|
||||
}
|
||||
|
||||
const handleUpload = async () => {
|
||||
if (!status.imgUploading && !fileList.value.length) {
|
||||
ElMessage.warning('请先选择图片')
|
||||
return
|
||||
}
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '上传中',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
if (status.imgUploading) {
|
||||
while (status.imgUploading) {
|
||||
await new Promise((r) => setTimeout(r, 2000))
|
||||
}
|
||||
}
|
||||
|
||||
const clothFileList = fileList.value?.map((file) => file.name)
|
||||
|
||||
const clothType = nav.value.clothType as 'topCloth' | 'bottomCloth' | 'dress'
|
||||
|
||||
await api.addClothes({
|
||||
clothFileList,
|
||||
clothType,
|
||||
isSync: isSyncClothesLibrary.value ? 'yes' : 'no',
|
||||
sex: gender.value
|
||||
})
|
||||
|
||||
emit('onUploadSuccess')
|
||||
|
||||
loading.close()
|
||||
}
|
||||
|
||||
// expose
|
||||
|
||||
/**
|
||||
* 输入链接校验
|
||||
*/
|
||||
const isValidURL = (url: string) => {
|
||||
try {
|
||||
const parsedURL = new URL(url)
|
||||
const hostname = parsedURL.hostname
|
||||
const domain = hostname.split('.').slice(-2).join('.')
|
||||
return domain === 'vip.com'
|
||||
} catch {
|
||||
ElMessageBox({
|
||||
type: 'error',
|
||||
message: '请输入正确的链接'
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ reset })
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pick-And-upload-image {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
border-right: 0.5px solid #000;
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -5px;
|
||||
width: 9px;
|
||||
height: 1px;
|
||||
background-color: #000;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
& :deep(.el-upload--picture-card) {
|
||||
--el-upload-picture-card-size: 89px;
|
||||
}
|
||||
|
||||
& :deep(.el-upload-list) {
|
||||
--el-upload-list-picture-card-size: 89px;
|
||||
}
|
||||
|
||||
& :deep(.el-upload-list__item) {
|
||||
border-radius: 0;
|
||||
border: 0.5px solid #000;
|
||||
}
|
||||
|
||||
.trigger-icon {
|
||||
width: 89px;
|
||||
height: 89px;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 89px;
|
||||
height: 89px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
// background-color: red;
|
||||
// border-width: 0.5px;
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.prompt {
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.link-input {
|
||||
max-width: 580px;
|
||||
width: 100%;
|
||||
border: 0.5px solid #000000;
|
||||
margin-top: 10px;
|
||||
|
||||
.grabButton {
|
||||
cursor: pointer;
|
||||
color: #000000;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.grab-img-list {
|
||||
margin-top: 10px;
|
||||
height: auto;
|
||||
|
||||
.grap-image {
|
||||
position: relative;
|
||||
border: 0.5px solid #000;
|
||||
.cover-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s ease;
|
||||
display: none;
|
||||
|
||||
.icon-item {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .cover-icon {
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
text-align: center;
|
||||
|
||||
& :deep(.el-checkbox__label) {
|
||||
color: #87909e;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
& :deep(.el-checkbox__inner) {
|
||||
border-color: #87909e;
|
||||
background-color: #87909e;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<swiper
|
||||
class="swiper"
|
||||
:modules="modules"
|
||||
direction="vertical"
|
||||
slides-per-view="auto"
|
||||
:free-mode="true"
|
||||
:scrollbar="true"
|
||||
:mousewheel="true"
|
||||
:auto-height="true"
|
||||
>
|
||||
<swiper-slide class="slide">
|
||||
<slot></slot>
|
||||
</swiper-slide>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Pagination, FreeMode, Scrollbar, Mousewheel } from 'swiper/modules'
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue'
|
||||
import 'swiper/css'
|
||||
import 'swiper/css/pagination'
|
||||
import 'swiper/css/free-mode'
|
||||
import 'swiper/css/scrollbar'
|
||||
|
||||
const modules = [Pagination, FreeMode, Scrollbar, Mousewheel]
|
||||
|
||||
const height = '10000000000px'
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.swiper-scrollbar) {
|
||||
width: 0.5px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
:deep(.swiper-scrollbar-drag) {
|
||||
width: 0.5px;
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: v-bind(height);
|
||||
background-color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
height: 100%;
|
||||
|
||||
.slide {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="search-input">
|
||||
<MyIcons type="search" :size="15" style="display: inline-flex" />
|
||||
<span>{{ $t('nav.search') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-input {
|
||||
width: 123px;
|
||||
height: 22px;
|
||||
border: 1px solid #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
font-size: 10px;
|
||||
box-sizing: border-box;
|
||||
|
||||
// background-color: red;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,74 @@
|
||||
<script lang="ts" setup>
|
||||
import { useToggle } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useGlobalStore } from '@/stores/globalStore'
|
||||
const globalStore = useGlobalStore()
|
||||
|
||||
const { menu } = storeToRefs(globalStore)
|
||||
const emit = defineEmits(['change'])
|
||||
const props = defineProps<{
|
||||
checked?: boolean
|
||||
}>()
|
||||
console.log(props.checked, '饿', menu.value)
|
||||
const [value, toggle] = useToggle(props.checked)
|
||||
const handleToggle = () => {
|
||||
toggle()
|
||||
emit('change', value.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="singleCheckbox" @click="handleToggle">
|
||||
<div v-if="!value">
|
||||
<svg
|
||||
fill="none"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
width="15"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
fill="#D9D9D9"
|
||||
height="14.5"
|
||||
stroke="black"
|
||||
stroke-width="0.5"
|
||||
width="14.5"
|
||||
x="0.25"
|
||||
y="0.25"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div v-else>
|
||||
<svg
|
||||
fill="none"
|
||||
height="15"
|
||||
viewBox="0 0 18 15"
|
||||
width="18"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
fill="#D9D9D9"
|
||||
height="14.5"
|
||||
stroke="black"
|
||||
stroke-width="0.5"
|
||||
width="14.5"
|
||||
x="0.25"
|
||||
y="0.25"
|
||||
/>
|
||||
<path
|
||||
d="M2.91675 5.41666L6.66675 10.8333L17.0834 0.416656"
|
||||
stroke="black"
|
||||
stroke-width="0.5"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.singleCheckbox {
|
||||
width: 16px;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,88 @@
|
||||
<script setup lang="ts">
|
||||
import WelcomeItem from './WelcomeItem.vue'
|
||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
||||
import ToolingIcon from './icons/IconTooling.vue'
|
||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
||||
import CommunityIcon from './icons/IconCommunity.vue'
|
||||
import SupportIcon from './icons/IconSupport.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<DocumentationIcon />
|
||||
</template>
|
||||
<template #heading>Documentation</template>
|
||||
|
||||
Vue’s
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
||||
provides you with all information you need to get started.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<ToolingIcon />
|
||||
</template>
|
||||
<template #heading>Tooling</template>
|
||||
|
||||
This project is served and bundled with
|
||||
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
||||
recommended IDE setup is
|
||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
|
||||
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
|
||||
you need to test your components and web pages, check out
|
||||
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
|
||||
<a href="https://on.cypress.io/component" target="_blank" rel="noopener"
|
||||
>Cypress Component Testing</a
|
||||
>.
|
||||
|
||||
<br />
|
||||
|
||||
More instructions are available in <code>README.md</code>.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<EcosystemIcon />
|
||||
</template>
|
||||
<template #heading>Ecosystem</template>
|
||||
|
||||
Get official tools and libraries for your project:
|
||||
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
||||
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
||||
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
||||
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
||||
you need more resources, we suggest paying
|
||||
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
||||
a visit.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<CommunityIcon />
|
||||
</template>
|
||||
<template #heading>Community</template>
|
||||
|
||||
Got stuck? Ask your question on
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
|
||||
Discord server, or
|
||||
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
||||
>StackOverflow</a
|
||||
>. You should also subscribe to
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
|
||||
the official
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
||||
twitter account for latest news in the Vue world.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<SupportIcon />
|
||||
</template>
|
||||
<template #heading>Support Vue</template>
|
||||
|
||||
As an independent project, Vue relies on community backing for its sustainability. You can help
|
||||
us by
|
||||
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
||||
</WelcomeItem>
|
||||
</template>
|
||||
@@ -0,0 +1,72 @@
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { ref } from 'vue'
|
||||
import IconLink from '@/components/icons/IconLink.vue'
|
||||
|
||||
const emit = defineEmits(['grabImage'])
|
||||
const input = ref('')
|
||||
const grabImage = () => {
|
||||
// console.log(input.value)
|
||||
// input.value && emit('grabImage', input.value)
|
||||
|
||||
const isOk = isValidURL(input.value)
|
||||
|
||||
if (isOk) {
|
||||
emit('grabImage', input.value)
|
||||
} else {
|
||||
ElMessageBox({
|
||||
type: 'error',
|
||||
message: '请输入正确的链接'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const isValidURL = (url: string) => {
|
||||
try {
|
||||
const parsedURL = new URL(url)
|
||||
const hostname = parsedURL.hostname
|
||||
const domain = hostname.split('.').slice(-2).join('.')
|
||||
return domain === 'vip.com'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vpShop-link">
|
||||
<el-input
|
||||
v-model="input"
|
||||
placeholder="输入唯品会链接自动抓取图片"
|
||||
size="large"
|
||||
style="max-width: 580px; width: 100%; border: 1px solid #000000"
|
||||
>
|
||||
<template #prefix>
|
||||
<IconLink />
|
||||
</template>
|
||||
<template #suffix>
|
||||
<div class="grabButton" @click="grabImage">抓取图片</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vpShop-link {
|
||||
:deep(.el-input__wrapper) {
|
||||
border-radius: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.grabButton {
|
||||
cursor: pointer;
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.grabButton {
|
||||
cursor: pointer;
|
||||
color: #000000;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<i>
|
||||
<slot name="icon"></slot>
|
||||
</i>
|
||||
<div class="details">
|
||||
<h3>
|
||||
<slot name="heading"></slot>
|
||||
</h3>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.item {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex: 1;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.4rem;
|
||||
color: var(--color-heading);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.item {
|
||||
margin-top: 0;
|
||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
i {
|
||||
top: calc(50% - 25px);
|
||||
left: -26px;
|
||||
position: absolute;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 8px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.item:before {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:after {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:first-of-type:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item:last-of-type:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="18" height="15" viewBox="0 0 18 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.25" y="0.25" width="14.5" height="14.5" fill="#D9D9D9" stroke="black" stroke-width="0.5"/>
|
||||
<path d="M2.91675 5.41666L6.66675 10.8333L17.0834 0.416656" stroke="black" stroke-width="0.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 301 B |
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<svg width="1em" height="1em" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1743_871)">
|
||||
<path
|
||||
d="M9.625 11H1.375C0.61875 11 0 10.3813 0 9.625V1.375C0 0.61875 0.61875 0 1.375 0H9.625C10.3813 0 11 0.61875 11 1.375V9.625C11 10.3813 10.3813 11 9.625 11ZM1.375 0.6875C0.9625 0.6875 0.6875 0.9625 0.6875 1.375V9.625C0.6875 10.0375 0.9625 10.3125 1.375 10.3125H9.625C10.0375 10.3125 10.3125 10.0375 10.3125 9.625V1.375C10.3125 0.9625 10.0375 0.6875 9.625 0.6875H1.375Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
<path
|
||||
d="M8.25 5.84375H2.75C2.54375 5.84375 2.40625 5.70625 2.40625 5.5C2.40625 5.29375 2.54375 5.15625 2.75 5.15625H8.25C8.45625 5.15625 8.59375 5.29375 8.59375 5.5C8.59375 5.70625 8.45625 5.84375 8.25 5.84375Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
<path
|
||||
d="M5.5 8.59375C5.29375 8.59375 5.15625 8.45625 5.15625 8.25V2.75C5.15625 2.54375 5.29375 2.40625 5.5 2.40625C5.70625 2.40625 5.84375 2.54375 5.84375 2.75V8.25C5.84375 8.45625 5.70625 8.59375 5.5 8.59375Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1743_871">
|
||||
<rect width="11" height="11" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<svg width="1em" height="1em" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1991_465)">
|
||||
<path
|
||||
d="M6.53009 8.25046C6.33977 8.25046 6.1864 8.09709 6.1864 7.90676V4.1243C6.1864 3.93398 6.33977 3.78061 6.53009 3.78061C6.72042 3.78061 6.87379 3.93398 6.87379 4.1243V7.90492C6.87379 8.09524 6.72042 8.25046 6.53009 8.25046Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
<path
|
||||
d="M4.46796 8.25046C4.27764 8.25046 4.12427 8.09709 4.12427 7.90676V4.1243C4.12427 3.93398 4.27764 3.78061 4.46796 3.78061C4.65828 3.78061 4.81165 3.93398 4.81165 4.1243V7.90492C4.81165 8.09524 4.65828 8.25046 4.46796 8.25046Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
<path
|
||||
d="M9.96892 2.40584H8.25046V1.71845C8.25046 1.14933 7.7922 0.687378 7.22677 0.687378H3.78061C3.21148 0.687378 2.74953 1.14933 2.74953 1.71845V2.40584H1.03107C0.840746 2.40584 0.687378 2.55921 0.687378 2.74953C0.687378 2.93986 0.840746 3.09322 1.03107 3.09322H9.96892C10.1592 3.09322 10.3126 2.93986 10.3126 2.74953C10.3126 2.55921 10.1592 2.40584 9.96892 2.40584ZM3.43692 1.71845C3.43692 1.52998 3.59213 1.37476 3.78061 1.37476H7.22677C7.41525 1.37476 7.56307 1.52628 7.56307 1.71845V2.40584H3.43692V1.71845Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
<path
|
||||
d="M7.90673 10.3126H3.09504C2.52592 10.3126 2.06396 9.85066 2.06396 9.28154V4.12061C2.06396 3.93028 2.21733 3.77692 2.40766 3.77692C2.59798 3.77692 2.75135 3.93028 2.75135 4.12061V9.28154C2.75135 9.47186 2.90657 9.62523 3.09504 9.62523H7.90858C8.09891 9.62523 8.25227 9.47186 8.25227 9.28154V4.13354C8.25227 3.94322 8.40564 3.78985 8.59597 3.78985C8.78629 3.78985 8.93966 3.94322 8.93966 4.13354V9.28154C8.93781 9.84881 8.47586 10.3126 7.90673 10.3126Z"
|
||||
fill="#2C2C2C"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1991_465">
|
||||
<rect width="11" height="11" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<svg width="16" height="4" viewBox="0 0 16 4" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect x="6" y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect x="6" y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect x="6" y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect x="12" y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect x="12" y="0.00012207" width="4" height="4" fill="black" />
|
||||
<rect x="12" y="0.00012207" width="4" height="4" fill="black" />
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<svg width="1em" height="1em" viewBox="0 0 9 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8.26743 0.246544C8.29914 0.213713 8.33707 0.187525 8.379 0.16951C8.42094 0.151494 8.46605 0.142011 8.51169 0.141615C8.55734 0.141218 8.6026 0.149915 8.64485 0.167199C8.68709 0.184483 8.72547 0.210008 8.75775 0.242284C8.79002 0.274559 8.81555 0.31294 8.83283 0.355185C8.85012 0.397431 8.85881 0.442696 8.85842 0.488338C8.85802 0.533981 8.84854 0.579088 8.83052 0.621027C8.81251 0.662966 8.78632 0.700897 8.75349 0.732607L3.89252 5.59369C3.82805 5.65816 3.74061 5.69438 3.64943 5.69438C3.55826 5.69438 3.47081 5.65816 3.40634 5.59369C3.34187 5.52922 3.30565 5.44178 3.30565 5.3506C3.30565 5.25943 3.34187 5.17198 3.40634 5.10751L8.26743 0.246659V0.246544ZM8.16671 3.81249C8.16671 3.72132 8.20292 3.63389 8.26739 3.56942C8.33185 3.50496 8.41929 3.46874 8.51046 3.46874C8.60162 3.46874 8.68906 3.50496 8.75352 3.56942C8.81799 3.63389 8.85421 3.72132 8.85421 3.81249V7.59374C8.85421 8.28983 8.28988 8.85416 7.59379 8.85416H1.40629C0.710197 8.85416 0.145874 8.28983 0.145874 7.59374V1.40624C0.145874 0.710148 0.710197 0.145826 1.40629 0.145826H5.07296C5.16412 0.145826 5.25156 0.182042 5.31602 0.246508C5.38049 0.310973 5.41671 0.398408 5.41671 0.489576C5.41671 0.580744 5.38049 0.668178 5.31602 0.732644C5.25156 0.797109 5.16412 0.833326 5.07296 0.833326H1.40629C1.25434 0.833326 1.10862 0.893686 1.00118 1.00113C0.893735 1.10857 0.833374 1.2543 0.833374 1.40624V7.59374C0.833374 7.74569 0.893735 7.89141 1.00118 7.99885C1.10862 8.1063 1.25434 8.16666 1.40629 8.16666H7.59379C7.74574 8.16666 7.89146 8.1063 7.9989 7.99885C8.10635 7.89141 8.16671 7.74569 8.16671 7.59374V3.81249Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<svg width="1em" height="1em" viewBox="0 0 11 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M1.85732 5.76748V2.16777C1.85732 1.99053 2.00234 1.84658 2.18174 1.84658H7.00283C7.18223 1.84658 7.32725 1.99053 7.32725 2.16777V5.76855C7.32725 5.9458 7.18223 6.08975 7.00283 6.08975H5.35928C5.19814 6.08975 5.06709 6.2208 5.06709 6.38193V6.44102C5.06709 6.60215 5.19814 6.7332 5.35928 6.7332H7.32617C7.68389 6.7332 7.975 6.44531 7.975 6.08975V1.84658C7.975 1.49102 7.68496 1.20312 7.32617 1.20312H1.53291C1.35352 1.20312 1.2085 1.34707 1.2085 1.52432V6.08867C1.2085 6.44424 1.49854 6.73213 1.85732 6.73213H2.18174C2.34287 6.73213 2.47393 6.60107 2.47393 6.43994V6.38086C2.47393 6.21973 2.34287 6.08867 2.18174 6.08867C2.00234 6.08975 1.85732 5.9458 1.85732 5.76748Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M9.15342 4.26788H8.829C8.68613 4.26788 8.56904 4.3839 8.56904 4.52784V4.65138C8.56904 4.79425 8.68506 4.91134 8.829 4.91134C9.0084 4.91134 9.15342 5.05529 9.15342 5.23253V8.83331C9.15342 9.01056 9.0084 9.1545 8.829 9.1545H3.97568C3.79629 9.1545 3.65127 9.01056 3.65127 8.83331V5.23253C3.65127 5.05529 3.79629 4.91134 3.97568 4.91134H5.68369C5.82656 4.91134 5.94365 4.79532 5.94365 4.65138V4.52784C5.94365 4.38497 5.82764 4.26788 5.68369 4.26788H3.65127C3.29355 4.26788 3.00244 4.55577 3.00244 4.91134V9.1545C3.00244 9.51007 3.29248 9.79796 3.65127 9.79796H9.15342C9.51113 9.79796 9.80225 9.51007 9.80225 9.1545V4.91134C9.80225 4.55577 9.51221 4.26788 9.15342 4.26788Z"
|
||||
fill="black"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<svg width="123" height="21" viewBox="0 0 123 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.5" y="0.5" width="122" height="20" fill="white" stroke="black"/>
|
||||
<g clip-path="url(#clip0_1650_2387)">
|
||||
<path d="M21.0001 17.39L16.5551 12.94C17.5712 11.7647 18.0917 10.2411 18.0072 8.68974C17.9228 7.13842 17.2398 5.68034 16.1021 4.62232C14.9644 3.5643 13.4607 2.98884 11.9073 3.01701C10.3539 3.04518 8.87205 3.6748 7.77347 4.77338C6.67489 5.87196 6.04528 7.35384 6.0171 8.90722C5.98893 10.4606 6.56439 11.9643 7.62241 13.102C8.68043 14.2397 10.1385 14.9227 11.6898 15.0071C13.2412 15.0916 14.7648 14.5711 15.9401 13.555L20.3901 18L21.0001 17.39ZM6.8401 9.00001C6.83911 7.97684 7.14174 6.97638 7.70967 6.12531C8.27759 5.27423 9.08528 4.61081 10.0305 4.21903C10.9757 3.82726 12.0158 3.72475 13.0193 3.92448C14.0228 4.12421 14.9445 4.6172 15.6676 5.34104C16.3907 6.06488 16.8828 6.98701 17.0816 7.99069C17.2804 8.99437 17.1768 10.0345 16.7842 10.9793C16.3915 11.9241 15.7273 12.7311 14.8756 13.2982C14.024 13.8653 13.0233 14.167 12.0001 14.165C10.6311 14.1637 9.31867 13.6189 8.35112 12.6504C7.38358 11.682 6.8401 10.369 6.8401 9.00001Z" fill="black"/>
|
||||
</g>
|
||||
<path d="M97.55 5.97L98.1 6.47C97.59 6.77 96.93 7.03 96.37 7.21C96.33 7.07 96.23 6.85 96.14 6.7C96.65 6.51 97.22 6.23 97.55 5.97ZM96 6.49L96.66 6.7V9.92H96V6.49ZM96 9.58H100.52V7.04H99.25V6.43H101.2V10.2H96V9.58ZM96.29 8.01H97.75V8.58H96.29V8.01ZM99.29 8.01H100.82V8.58H99.29V8.01ZM98.2 5.61H98.88V11.25H98.2V5.61ZM95.73 11.11H100.64V11.75H95.73V11.11ZM100.43 11.11H100.57L100.7 11.08L101.17 11.31C100.22 13.44 97.94 14.42 95.49 14.82C95.43 14.63 95.29 14.34 95.16 14.18C97.45 13.88 99.64 13 100.43 11.22V11.11ZM97.04 11.68C97.85 13.02 99.6 13.88 101.7 14.21C101.53 14.37 101.33 14.66 101.23 14.87C99.08 14.46 97.32 13.48 96.38 11.93L97.04 11.68ZM92.28 10.92C93.14 10.7 94.42 10.32 95.66 9.96L95.75 10.64C94.61 11 93.41 11.38 92.48 11.65L92.28 10.92ZM92.41 7.62H95.65V8.32H92.41V7.62ZM93.8 5.61H94.53V13.94C94.53 14.35 94.43 14.56 94.17 14.67C93.91 14.79 93.51 14.81 92.84 14.8C92.82 14.62 92.71 14.32 92.62 14.12C93.07 14.13 93.49 14.13 93.61 14.13C93.75 14.13 93.8 14.08 93.8 13.94V5.61ZM107.6 12.05H108.35V14.82H107.6V12.05ZM107.6 5.6H108.34V8.4H107.6V5.6ZM107.23 8.58L107.93 8.92C107.35 9.46 106.64 10.04 106.06 10.44L105.51 10.13C106.07 9.72 106.82 9.06 107.23 8.58ZM109.39 9.23L110.07 9.6C108.94 10.52 107.4 11.58 106.18 12.26L105.65 11.9C106.87 11.21 108.45 10.08 109.39 9.23ZM104.74 10.1L105.24 9.67C105.99 10.04 106.94 10.61 107.43 11.03L106.91 11.51C106.45 11.09 105.51 10.49 104.74 10.1ZM109.28 10.89L109.78 10.49C110.66 11.01 111.77 11.78 112.33 12.31L111.8 12.77C111.27 12.24 110.17 11.42 109.28 10.89ZM109.31 13.03L109.88 12.64C110.74 13.06 111.84 13.73 112.41 14.22L111.79 14.67C111.27 14.18 110.19 13.48 109.31 13.03ZM103.65 11.74C105.48 11.74 108.5 11.7 111.35 11.64L111.31 12.24C108.54 12.32 105.59 12.41 103.69 12.43L103.65 11.74ZM105.89 12.63L106.6 12.89C105.93 13.58 104.9 14.27 104.03 14.7C103.9 14.56 103.62 14.3 103.44 14.17C104.33 13.8 105.29 13.22 105.89 12.63ZM103.76 6.49H112.21V7.15H103.76V6.49ZM103.73 8.11H112.3V9.99H111.56V8.76H104.44V9.99H103.73V8.11Z" fill="black"/>
|
||||
<defs>
|
||||
<clipPath id="clip0_1650_2387">
|
||||
<rect width="15" height="15" fill="white" transform="translate(6 3)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.25" y="0.25" width="14.5" height="14.5" fill="#D9D9D9" stroke="black" stroke-width="0.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 205 B |
Reference in New Issue
Block a user