Merge branch 'dev_vite' of http://18.167.251.121:10003/aidlab/aida_front into dev_vite

This commit is contained in:
李志鹏
2026-02-02 16:52:11 +08:00
8 changed files with 384 additions and 237 deletions

View File

@@ -0,0 +1 @@
<svg focusable="false" class="" data-icon="paper-clip" width="1em" height="1em" fill="#00000073" aria-hidden="true" viewBox="64 64 896 896"><path d="M779.3 196.6c-94.2-94.2-247.6-94.2-341.7 0l-261 260.8c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l261-260.8c32.4-32.4 75.5-50.2 121.3-50.2s88.9 17.8 121.2 50.2c32.4 32.4 50.2 75.5 50.2 121.2 0 45.8-17.8 88.8-50.2 121.2l-266 265.9-43.1 43.1c-40.3 40.3-105.8 40.3-146.1 0-19.5-19.5-30.2-45.4-30.2-73s10.7-53.5 30.2-73l263.9-263.8c6.7-6.6 15.5-10.3 24.9-10.3h.1c9.4 0 18.1 3.7 24.7 10.3 6.7 6.7 10.3 15.5 10.3 24.9 0 9.3-3.7 18.1-10.3 24.7L372.4 653c-1.7 1.7-2.6 4-2.6 6.4s.9 4.7 2.6 6.4l36.9 36.9a9 9 0 0012.7 0l215.6-215.6c19.9-19.9 30.8-46.3 30.8-74.4s-11-54.6-30.8-74.4c-41.1-41.1-107.9-41-149 0L463 364 224.8 602.1A172.22 172.22 0 00174 724.8c0 46.3 18.1 89.8 50.8 122.5 33.9 33.8 78.3 50.7 122.7 50.7 44.4 0 88.8-16.9 122.6-50.7l309.2-309C824.8 492.7 850 432 850 367.5c.1-64.6-25.1-125.3-70.7-170.9z"></path></svg>

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -89,8 +89,8 @@
<img crossOrigin="anonymous" :src="item?.path" :style="{transform:`rotateZ(${item.pattern?.transform?.rotateZ}deg)`}" class="designOpenrtion_imgItme" draggable="false"> <img crossOrigin="anonymous" :src="item?.path" :style="{transform:`rotateZ(${item.pattern?.transform?.rotateZ}deg)`}" class="designOpenrtion_imgItme" draggable="false">
</div> </div>
</div> </div>
<img :src="selectDetail.path" alt="" class="designOpenrtion_sketch" ref="sketchImg"> <!-- <img :src="selectDetail.path" alt="" class="designOpenrtion_sketch" ref="sketchImg" @load="()=>isSketchLoad = true"> -->
<!-- <img :src="stateOverallSingle == 'single'?(selectDetail.undividedLayer||selectDetail.path):(selectDetail.undividedLayerColor || selectDetail.path)" alt="" class="designOpenrtion_sketch" ref="sketchImg" @load="()=>isSketchLoad = true"> --> <img :src="(selectDetail.path)" alt="" class="designOpenrtion_sketch" ref="sketchImg" @load="()=>isSketchLoad = true">
<img :src="selectDetail.sketchMask" alt="" class="designOpenrtion_sketchMask" ref="sketchMask"> <img :src="selectDetail.sketchMask" alt="" class="designOpenrtion_sketchMask" ref="sketchMask">
<div class="designOpenrtion_btn" v-if="stateOverallSingle == 'single'" > <div class="designOpenrtion_btn" v-if="stateOverallSingle == 'single'" >
<ul v-for="item,index in printStyleList[type][stateOverallSingle]" :key="item" :class="{active:item?.pattern.designOpenrtionBtn?item?.pattern.designOpenrtionBtn:false}" class="designOpenrtion_Mousingle" :style="item?.pattern.style" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))"> <ul v-for="item,index in printStyleList[type][stateOverallSingle]" :key="item" :class="{active:item?.pattern.designOpenrtionBtn?item?.pattern.designOpenrtionBtn:false}" class="designOpenrtion_Mousingle" :style="item?.pattern.style" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))">
@@ -160,7 +160,6 @@ export default defineComponent({
selectDetail:computed(()=>store.state.DesignDetail.selectDetail), selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType), currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
currentPrintElement:computed(()=>store.state.DesignDetail.currentPrintElement), currentPrintElement:computed(()=>store.state.DesignDetail.currentPrintElement),
systemDesignerPercentage:0,
printStyleList:{ printStyleList:{
print:{ print:{
single:[], single:[],
@@ -224,6 +223,7 @@ export default defineComponent({
img.onload = ()=>{ img.onload = ()=>{
let imgScale = img.width / img.height let imgScale = img.width / img.height
let zoom = 2 let zoom = 2
console.log(editPrintElementData.sketchWH)
let width = editPrintElementData.sketchWH.width / zoom let width = editPrintElementData.sketchWH.width / zoom
let height = width / editPrintElementData.sketchWH.height let height = width / editPrintElementData.sketchWH.height
@@ -233,30 +233,43 @@ export default defineComponent({
let sketchH = editPrintElementData.sketchWH.height * editPrintElementData.sketchWH.scale[1] let sketchH = editPrintElementData.sketchWH.height * editPrintElementData.sketchWH.scale[1]
let x = sketchW / 2 - (sketchW * (width / editPrintElementData.sketchWH.width)/2) let x = sketchW / 2 - (sketchW * (width / editPrintElementData.sketchWH.width)/2)
let y = sketchH / 2 -(sketchH * height/2) let y = sketchH / 2 -(sketchH * height/2)
if(!editPrintElementData.stateOverallSingle == 'single'){ if(editPrintElementData.stateOverallSingle !== 'single'){
x = sketchW / 2 x = sketchW / 2
y = sketchH / 2 y = sketchH / 2
} }
let location = [x,y] let location = [x,y]
resolve({scale,location}) resolve({scale,location})
} }
img.src = item.url img.src = item.url || item.path
}) })
} }
const addPrintELement = async (data:any)=>{ const addPrintELement = async (data:any)=>{
if(!editPrintElementData.isSketchLoad)return if(!editPrintElementData.isSketchLoad)return
let {scale,location} = await setScaleLocation(data) let {scale,location} = await setScaleLocation(data)
let allElementPrint = [ let printIndex = 1
...(editPrintElementData.selectDetail.printObject.prints || []), let allElementPrint = []
...(editPrintElementData.selectDetail.trims.prints || []), if(props.type == 'print'){
] allElementPrint = [
let printIndex = Math.max(...allElementPrint.map(item => item.priority)) + 1 ...(editPrintElementData.printStyleList.print.single || []),
...(editPrintElementData.printStyleList.print.overall || []),
...(editPrintElementData.selectDetail.trims.prints || []),
]
}else{
allElementPrint = [
...(editPrintElementData.printStyleList.element.single || []),
...(editPrintElementData.selectDetail.printObject.prints || []),
]
}
if(allElementPrint.length >= 1){
printIndex = Math.max(...allElementPrint.map(item => Number(item.priority))) + 1
}
let item = { let item = {
angle:0, angle:0,
designType:data.designType, designType:data.designType,
ifSingle:editPrintElementData.stateOverallSingle == 'single', ifSingle:editPrintElementData.stateOverallSingle == 'single',
level2Type:data.level2Type, level2Type:data.level2Type,
location:editPrintElementData.stateOverallSingle == 'single'?location:[0,0], location:location,
// location:editPrintElementData.stateOverallSingle == 'single'?location:[0,0],
minIOPath:data.minIOPath || data.originalUrl, minIOPath:data.minIOPath || data.originalUrl,
path:data.url, path:data.url,
priority:printIndex, priority:printIndex,
@@ -344,10 +357,9 @@ export default defineComponent({
top = item.location[1] / editPrintElementData.sketchWH.scale[1] top = item.location[1] / editPrintElementData.sketchWH.scale[1]
}else{ }else{
//overall //overall
editPrintElementData.systemDesignerPercentage = item.scale[0]*1000
left = item.location[0] / editPrintElementData.sketchWH.scale[0] left = item.location[0] / editPrintElementData.sketchWH.scale[0]
top = item.location[1] / editPrintElementData.sketchWH.scale[1] top = item.location[1] / editPrintElementData.sketchWH.scale[1]
editPrintElementData.systemDesignerPercentage = item.scale?.[0]?item.scale[0]*100:30 item.scale = [1,1]
} }
let pattern = { let pattern = {
centers:{left:0,top:0}, centers:{left:0,top:0},
@@ -407,51 +419,49 @@ export default defineComponent({
} }
} }
} }
const setPosition = ()=>{ const setPosition = async ()=>{
nextTick(()=>{ await new Promise<void>((resolve, reject) => {
let img = new Image nextTick(()=>{
img.onload = ()=>{ let img = new Image
// let sketchScale = editPrintElementData.selectDetail.layersObject[0].scale img.onload = ()=>{
let sketchScale = [1,1] // let sketchScale = editPrintElementData.selectDetail.layersObject[0].scale
let scaleX = img.width * sketchScale[0] / editPrintElementDom.sketchImg.offsetWidth let sketchScale = [1,1]
let scaleY = img.height * sketchScale[1] / editPrintElementDom.sketchImg.offsetHeight let scaleX = img.width * sketchScale[0] / editPrintElementDom.sketchImg.offsetWidth
let scaleY = img.height * sketchScale[1] / editPrintElementDom.sketchImg.offsetHeight
editPrintElementData.sketchWH = { editPrintElementData.sketchWH = {
width:editPrintElementDom.sketchImg.offsetWidth, width:editPrintElementDom.sketchImg.offsetWidth,
height:editPrintElementDom.sketchImg.offsetHeight, height:editPrintElementDom.sketchImg.offsetHeight,
scale:[scaleX,scaleY], scale:[scaleX,scaleY],
}
if(!editPrintElementData.selectDetail.printObject.prints)return
let state = true
// editPrintElementData.stateOverallSingle = 'single'
let arr:any = editPrintElementData.selectDetail.printObject.prints
if(props.type == 'element'){
arr = editPrintElementData.selectDetail.trims.prints
}
// if(editPrintElementData.selectDetail.newDetail?.[editPrintElementData.currentDetailType]){
// arr = editPrintElementData.selectDetail.newDetail[editPrintElementData.currentDetailType]
// }
if(arr && arr.length > 0){
editPrintElementData.printStyleList[props.type].single = []
editPrintElementData.printStyleList[props.type].overall = []
arr.forEach((item:any)=>{
// if(!item.ifSingle){
// editPrintElementData.stateOverallSingle = 'overall',
// state = false
// }
getItemPosition(item)
})
setItemPosition()
}
resolve('')
} }
if(!editPrintElementData.selectDetail.printObject.prints)return img.src = editPrintElementData.selectDetail.path
let state = true })
// editPrintElementData.stateOverallSingle = 'single'
let arr:any = editPrintElementData.selectDetail.printObject.prints
if(props.type == 'element'){
arr = editPrintElementData.selectDetail.trims.prints
}
// if(editPrintElementData.selectDetail.newDetail?.[editPrintElementData.currentDetailType]){
// arr = editPrintElementData.selectDetail.newDetail[editPrintElementData.currentDetailType]
// }
if(arr && arr.length > 0){
editPrintElementData.printStyleList[props.type].single = []
editPrintElementData.printStyleList[props.type].overall = []
arr.forEach((item:any)=>{
// if(!item.ifSingle){
// editPrintElementData.stateOverallSingle = 'overall',
// state = false
// }
getItemPosition(item)
})
setItemPosition()
}
// if(props.type == 'print'){
// editPrintElementData.overallSingle = state
// }
}
// undividedLayer
//计算宽高使用editPrintElementData.selectDetail.path
// img.src = editPrintElementData.selectDetail.path
img.src = editPrintElementData.selectDetail.undividedLayer?editPrintElementData.selectDetail.undividedLayer:editPrintElementData.selectDetail.path
}) })
} }
// watch(()=>editPrintElementData.selectDetail?.id,(newVal)=>{ // watch(()=>editPrintElementData.selectDetail?.id,(newVal)=>{
// if(!newVal)return // if(!newVal)return
@@ -862,7 +872,6 @@ export default defineComponent({
let arr:any = editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle] let arr:any = editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle]
arr.forEach((item,index) => {item.uniqueId = `${Date.now()}_${index}`}); arr.forEach((item,index) => {item.uniqueId = `${Date.now()}_${index}`});
console.log(arr)
const sortedArray = [...arr].sort((a, b) => a.priority - b.priority); const sortedArray = [...arr].sort((a, b) => a.priority - b.priority);
const sortMap = {} as any; const sortMap = {} as any;
sortedArray.forEach((item, index) => { sortedArray.forEach((item, index) => {

View File

@@ -13,7 +13,10 @@
<div class="desc">AiDA Users Only</div> <div class="desc">AiDA Users Only</div>
</div> </div>
</div> </div>
<Success :isExpired="isExpired" v-if="isCompleted || isExpired" /> <Success
:isExpired="isExpired"
v-if="isCompleted || isExpired"
/>
<div <div
class="form-container" class="form-container"
v-if="!isCompleted && !isExpired" v-if="!isCompleted && !isExpired"
@@ -36,6 +39,7 @@
<div class="email-wrapper flex align-center"> <div class="email-wrapper flex align-center">
<a-input v-model:value="form.email" /> <a-input v-model:value="form.email" />
<div <div
v-if="!hasValidEmail"
class="code-btn" class="code-btn"
:class="{ disabled: isCountingDown }" :class="{ disabled: isCountingDown }"
@click="handleSendCode" @click="handleSendCode"
@@ -78,19 +82,29 @@
:disabled="readOnly" :disabled="readOnly"
v-model:value="form[item.key]" v-model:value="form[item.key]"
/> />
<a-select <div
class="select-container"
v-if="item.type === 'select'" v-if="item.type === 'select'"
:disabled="readOnly"
v-model:value="form[item.key]"
:options="genderOptions"
> >
<template #suffixIcon> <a-select
:disabled="readOnly"
v-model:value="form[item.key]"
:options="genderOptions"
>
<template #suffixIcon>
<!-- <img
class="arrow-down-icon"
src="@/assets/images/award/arrow_down.svg"
/> -->
</template>
</a-select>
<div class="arrow-wrapper flex flex-center">
<img <img
class="arrow-down-icon" class="arrow-down-icon"
src="@/assets/images/award/arrow_down.svg" src="@/assets/images/award/arrow_down.svg"
/> />
</template> </div>
</a-select> </div>
</a-form-item> </a-form-item>
</template> </template>
</div> </div>
@@ -157,19 +171,15 @@
:validate-trigger="[]" :validate-trigger="[]"
label="How will you use AiDA in your design process?" label="How will you use AiDA in your design process?"
> >
<div <div>
v-if="
pdfUploadStatus === 'idle' ||
pdfUploadStatus === 'error'
"
>
<a-upload-dragger <a-upload-dragger
v-model:fileList="pdfList" v-model:fileList="pdfList"
:disabled="readOnly" :disabled="readOnly"
:showUploadList="false" :maxCount="1"
@change="info => handleFileChange(info, 'pdf')" @change="info => handleFileChange(info, 'pdf')"
:customRequest="handleUploadPdf" :customRequest="handleUploadPdf"
:beforeUpload="beforeUploadPdf" :beforeUpload="beforeUploadPdf"
@remove="handleRemoveFile('pdf')"
accept=".pdf" accept=".pdf"
> >
<img <img
@@ -179,25 +189,48 @@
/> />
<p class="desc">Click to upload or drag and drop</p> <p class="desc">Click to upload or drag and drop</p>
<p class="limit">PDF file, max 20MB</p> <p class="limit">PDF file, max 20MB</p>
<template #itemRender="{ file, actions }">
<div
class="custom-upload-list flex align-center space-between"
>
<div class="flex align-center">
<SvgIcon name="CFile" />
{{ file.name }}
</div>
<div
@click="actions.remove"
class="delete-file"
title="delete file"
>
<SvgIcon
name="CDelete"
color="red"
/>
</div>
</div>
</template>
</a-upload-dragger> </a-upload-dragger>
</div> </div>
<div <div
v-else v-show="
pdfUploadStatus === 'uploading' ||
pdfUploadStatus === 'success'
"
class="uploading-container" class="uploading-container"
> >
<UploadStatus <UploadStatus
:status="pdfUploadStatus" :status="pdfUploadStatus"
type="pdf" type="pdf"
/> />
</div>
<div
class="progress-bar-container"
v-if="pdfUploadStatus === 'uploading'"
>
<div <div
class="progress-bar" class="progress-bar-container"
:style="{ width: `${uploadProgressPdf}%` }" v-if="pdfUploadStatus === 'uploading'"
></div> >
<div
class="progress-bar"
:style="{ width: `${uploadProgressPdf}%` }"
></div>
</div>
</div> </div>
</a-form-item> </a-form-item>
</div> </div>
@@ -209,23 +242,19 @@
:validate-trigger="[]" :validate-trigger="[]"
label="How will you use AiDA in your design process?" label="How will you use AiDA in your design process?"
> >
<div <div>
v-if="
videoUploadStatus === 'idle' ||
videoUploadStatus === 'error'
"
>
<a-upload-dragger <a-upload-dragger
v-model:fileList="videoList" v-model:fileList="videoList"
:showUploadList="false"
:disabled="readOnly" :disabled="readOnly"
:maxCount="1"
@change="info => handleFileChange(info, 'video')" @change="info => handleFileChange(info, 'video')"
:customRequest="handleUploadVideo" :customRequest="handleUploadVideo"
:beforeUpload="beforeUploadVideo" :beforeUpload="beforeUploadVideo"
@remove="handleRemoveFile('video')"
accept=".mp4,.mov" accept=".mp4,.mov"
> >
<img <img
src="@/assets/images/award/upload.png" src="@/assets/images/award/upload_video_icon.png"
alt="" alt=""
class="upload-icon" class="upload-icon"
/> />
@@ -233,25 +262,48 @@
<p class="limit"> <p class="limit">
Video file (MP4, MOV), 1080p, max 100MB Video file (MP4, MOV), 1080p, max 100MB
</p> </p>
<template #itemRender="{ file, actions }">
<div
class="custom-upload-list flex align-center space-between"
>
<div class="flex align-center">
<SvgIcon name="CFile" />
{{ file.name }}
</div>
<div
@click="actions.remove"
class="delete-file"
title="delete file"
>
<SvgIcon
name="CDelete"
color="red"
/>
</div>
</div>
</template>
</a-upload-dragger> </a-upload-dragger>
</div> </div>
<div <div
v-else v-show="
videoUploadStatus === 'success' ||
videoUploadStatus === 'uploading'
"
class="uploading-container" class="uploading-container"
> >
<UploadStatus <UploadStatus
:status="videoUploadStatus" :status="videoUploadStatus"
type="video" type="video"
/> />
</div>
<div
class="progress-bar-container"
v-if="videoUploadStatus === 'uploading'"
>
<div <div
class="progress-bar" class="progress-bar-container"
:style="{ width: `${uploadProgressVideo}%` }" v-if="videoUploadStatus === 'uploading'"
></div> >
<div
class="progress-bar"
:style="{ width: `${uploadProgressVideo}%` }"
></div>
</div>
</div> </div>
</a-form-item> </a-form-item>
</div> </div>
@@ -342,7 +394,7 @@
import { ref, onUnmounted, onMounted, computed } from 'vue' import { ref, onUnmounted, onMounted, computed } from 'vue'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import type { Rule } from 'ant-design-vue/es/form' import type { Rule } from 'ant-design-vue/es/form'
import { message } from 'ant-design-vue' import { message, Upload } from 'ant-design-vue'
import { Https } from '@/tool/https' import { Https } from '@/tool/https'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import type { UploadChangeParam } from 'ant-design-vue' import type { UploadChangeParam } from 'ant-design-vue'
@@ -359,7 +411,7 @@
const route = useRoute() const route = useRoute()
const isCompleted = ref(false) const isCompleted = ref(false)
const hasValidEmail = ref(false)
const readOnly = computed(() => { const readOnly = computed(() => {
if (route.query.id && !hasValidEmail.value) { if (route.query.id && !hasValidEmail.value) {
return true return true
@@ -383,7 +435,10 @@
designDescription: '', designDescription: '',
pdfPath: '', pdfPath: '',
videoPath: '', videoPath: '',
secureToken: null secureToken: ''
})
const hasValidEmail = computed(() => {
return !!form.value.secureToken
}) })
// 验证码输入组件引用 // 验证码输入组件引用
@@ -620,7 +675,6 @@
console.log('coderes', res) console.log('coderes', res)
form.value.secureToken = res.data.secureToken form.value.secureToken = res.data.secureToken
hasValidEmail.value = true
message.success('Verification successful!') message.success('Verification successful!')
showModal.value = false showModal.value = false
@@ -675,7 +729,7 @@
const beforeUploadFile = (type: FileType, file: File) => { const beforeUploadFile = (type: FileType, file: File) => {
if (!hasValidEmail.value) { if (!hasValidEmail.value) {
message.error('Please verify your email first') message.error('Please verify your email first')
return false return Upload.LIST_IGNORE
} }
let maxSize: number let maxSize: number
let allowedExtensions: string[] let allowedExtensions: string[]
@@ -693,7 +747,7 @@
allowedMimeTypes = ['video/mp4', 'video/quicktime'] allowedMimeTypes = ['video/mp4', 'video/quicktime']
errorMessage = 'Please upload a MP4 or MOV file only.' errorMessage = 'Please upload a MP4 or MOV file only.'
} else { } else {
return false return Upload.LIST_IGNORE
} }
// 验证文件类型 // 验证文件类型
@@ -705,18 +759,18 @@
if (!isValidType) { if (!isValidType) {
message.error(errorMessage) message.error(errorMessage)
// 从文件列表中移除 // 从文件列表中移除
if (type === 'pdf') { // if (type === 'pdf') {
const index = pdfList.value.findIndex(item => item.uid === file.uid) // const index = pdfList.value.findIndex(item => item.uid === file.uid)
if (index > -1) { // if (index > -1) {
pdfList.value.splice(index, 1) // pdfList.value.splice(index, 1)
} // }
} else { // } else {
const index = videoList.value.findIndex(item => item.uid === file.uid) // const index = videoList.value.findIndex(item => item.uid === file.uid)
if (index > -1) { // if (index > -1) {
videoList.value.splice(index, 1) // videoList.value.splice(index, 1)
} // }
} // }
return false // 阻止上传 return Upload.LIST_IGNORE
} }
// 验证文件大小 // 验证文件大小
@@ -726,21 +780,21 @@
`File size exceeds ${sizeLimit} limit. Please upload a smaller file.` `File size exceeds ${sizeLimit} limit. Please upload a smaller file.`
) )
// 从文件列表中移除 // 从文件列表中移除
if (type === 'pdf') { // if (type === 'pdf') {
const index = pdfList.value.findIndex(item => item.uid === file.uid) // const index = pdfList.value.findIndex(item => item.uid === file.uid)
if (index > -1) { // if (index > -1) {
pdfList.value.splice(index, 1) // pdfList.value.splice(index, 1)
} // }
} else { // } else {
const index = videoList.value.findIndex(item => item.uid === file.uid) // const index = videoList.value.findIndex(item => item.uid === file.uid)
if (index > -1) { // if (index > -1) {
videoList.value.splice(index, 1) // videoList.value.splice(index, 1)
} // }
} // }
return false // 阻止上传 return Upload.LIST_IGNORE
} }
return true // 允许上传 return true
} }
// PDF文件上传前验证 // PDF文件上传前验证
@@ -822,18 +876,22 @@
} }
const completeChunkUpload = async (type: FileType, file: File) => { const completeChunkUpload = async (type: FileType, file: File) => {
const endpoint = try {
type === 'pdf' const endpoint =
? Https.httpUrls.uploadPDFComplete type === 'pdf'
: Https.httpUrls.uploadVideoComplete ? Https.httpUrls.uploadPDFComplete
: Https.httpUrls.uploadVideoComplete
return Https.axiosPost(endpoint, { return Https.axiosPost(endpoint, {
uploadId: chunkUploadState[type].uploadId, uploadId: chunkUploadState[type].uploadId,
email: form.value.email, email: form.value.email,
fileName: file.name, fileName: file.name,
totalSize: file.size, totalSize: file.size,
secureToken: form.value.secureToken secureToken: form.value.secureToken
}) })
} catch (error) {
console.log('complete错误', error)
}
} }
type FileType = 'pdf' | 'video' type FileType = 'pdf' | 'video'
@@ -922,10 +980,12 @@
isUploadingPdf.value = false isUploadingPdf.value = false
uploadProgressPdf.value = 0 uploadProgressPdf.value = 0
pdfUploadStatus.value = 'error' pdfUploadStatus.value = 'error'
pdfList.value = []
} else { } else {
isUploadingVideo.value = false isUploadingVideo.value = false
uploadProgressVideo.value = 0 uploadProgressVideo.value = 0
videoUploadStatus.value = 'error' videoUploadStatus.value = 'error'
videoList.value = []
} }
} }
} }
@@ -940,6 +1000,18 @@
return handleUploadFile(option, 'video') return handleUploadFile(option, 'video')
} }
const handleRemoveFile = (type: 'video' | 'pdf') => {
if (type === 'pdf') {
form.value.pdfPath = ''
pdfUploadStatus.value = 'idle'
uploadProgressPdf.value = 0
} else if (type === 'video') {
form.value.videoPath = ''
videoUploadStatus.value = 'idle'
uploadProgressVideo.value = 0
}
}
const conditionsList = ref([ const conditionsList = ref([
{ {
check: false, check: false,
@@ -1137,14 +1209,26 @@
line-height: 6rem; line-height: 6rem;
} }
} }
:deep(.ant-select-arrow) { // :deep(.ant-select-arrow) {
height: 4rem;
width: 6.2rem; // justify-content: center;
justify-content: center; // display: flex;
display: flex; // align-items: center;
align-items: center; // }
border-left: 0.1rem solid #d5d5d5; }
} }
.select-container {
position: relative;
.arrow-wrapper {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
width: 6rem;
height: 4rem;
box-sizing: border-box;
border-left: 0.1rem solid #d5d5d5;
pointer-events: none;
} }
} }
@@ -1238,9 +1322,10 @@
.upload-container { .upload-container {
margin-top: 6rem; margin-top: 6rem;
position: relative;
:deep(.ant-upload-drag) { :deep(.ant-upload-drag) {
height: 32rem; height: 32rem;
border-radius: 0.8rem;
.ant-upload-btn { .ant-upload-btn {
padding: 0; padding: 0;
@@ -1276,9 +1361,13 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: 0.2rem solid #d5d5d5; border: 0.2rem dashed #d5d5d5;
border-radius: 0.8rem; border-radius: 0.8rem;
background-color: #fafafa; background-color: #fafafa;
position: absolute;
top: 0;
left: 0;
width: 100%;
.uploading-text { .uploading-text {
color: #585858; color: #585858;
@@ -1306,7 +1395,20 @@
} }
} }
} }
.custom-upload-list {
padding: 0.4rem 1rem;
margin-top: 1rem;
&:hover {
background-color: #f5f5f5;
border-radius: 0.4rem;
}
.c-svg {
width: fit-content;
}
.delete-file {
cursor: pointer;
}
}
.conditions { .conditions {
margin-top: 12rem; margin-top: 12rem;
@@ -1462,9 +1564,12 @@
</style> </style>
<style lang="less"> <style lang="less">
.code-modal { .code-modal {
.ant-modal-content .ant-modal-body { .ant-modal-content {
padding: 0; width: 60rem;
// width: 60rem; height: 49.4rem;
.ant-modal-body {
padding: 0;
}
} }
} }
</style> </style>

View File

@@ -463,7 +463,7 @@
.item-desc { .item-desc {
font-family: 'Instrument'; font-family: 'Instrument';
font-weight: 400; font-weight: 400;
font-size: 24px; font-size: 2.4rem;
color: #585858; color: #585858;
&.indent { &.indent {
padding-left: 3.8rem; padding-left: 3.8rem;

View File

@@ -35,7 +35,7 @@
return { return {
icon: expiredIcon, icon: expiredIcon,
title: 'Application Deadline Passed', title: 'Application Deadline Passed',
desc: 'The submission deadline for AIDA Global Fashion Award 2026 has ended.\nWe are no longer accepting new applications. ' desc: 'The submission deadline for AiDA Global Fashion Award 2026 has ended.\nWe are no longer accepting new applications. '
} }
} else { } else {
return { return {

View File

@@ -5,10 +5,14 @@
> >
<div class="timeline-title">Competition Timeline</div> <div class="timeline-title">Competition Timeline</div>
<div class="desc">Shaping the Future</div> <div class="desc">Shaping the Future</div>
<div class="timeline-point"> <div
<div class="labels-row flex align-center"> class="timeline-point"
ref="timelineRef"
>
<!-- 顶部标签行 -->
<div class="grid-row labels-row">
<div <div
class="item-label flex flex-col" class="grid-cell label-cell"
v-for="item in points" v-for="item in points"
:key="'label-' + item.time" :key="'label-' + item.time"
> >
@@ -21,31 +25,35 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Icons row --> <!-- 图标行 -->
<div class="icons-row flex align-center"> <div class="grid-row icons-row">
<div class="timeline-line"></div> <div class="timeline-line"></div>
<img <div
src="@/assets/images/award/point.png" class="grid-cell icon-cell"
class="point-icon"
v-for="item in points" v-for="item in points"
:key="'icon-' + item.time" :key="'icon-' + item.time"
/> >
<img
src="@/assets/images/award/point.png"
class="point-icon"
/>
</div>
</div> </div>
<!-- 时间行 -->
<!-- Times row --> <div class="grid-row times-row">
<div class="times-row flex align-center">
<div <div
class="item-time" class="grid-cell time-cell"
v-for="item in points" v-for="item in points"
:key="'time-' + item.time" :key="'time-' + item.time"
> >
{{ item.time }} {{ item.time }}
</div> </div>
</div> </div>
<!-- Descriptions row -->
<div class="descs-row flex align-center"> <!-- 描述行 -->
<div class="grid-row descs-row">
<div <div
class="item-desc flex justify-center" class="grid-cell desc-cell"
v-for="item in points" v-for="item in points"
:key="'desc-' + item.time" :key="'desc-' + item.time"
> >
@@ -63,12 +71,13 @@
import { gsap } from 'gsap' import { gsap } from 'gsap'
const containerRef = ref<HTMLElement | null>(null) const containerRef = ref<HTMLElement | null>(null)
const timelineRef = ref<HTMLElement | null>(null)
const hasAnimated = ref(false) const hasAnimated = ref(false)
const points = ref([ const points = ref([
{ {
label: 'Application', label: 'Application',
subLabel:'Deadline', subLabel: 'Deadline',
time: 'Jul 15', time: 'Jul 15',
desc: 'Application deadline and\nentry review process\nbegins.' desc: 'Application deadline and\nentry review process\nbegins.'
}, },
@@ -86,16 +95,16 @@
}, },
{ {
label: 'Receiving Outfits', label: 'Receiving Outfits',
subLabel:'from Finallists', subLabel: 'from Finallists',
time: 'October', time: 'October',
desc: 'AiDA receives physical\noutfits from all 20\nfinalists.' desc: 'AiDA receives physical\noutfits from all 20\nfinalists.'
}, },
{ {
label: 'Award', label: 'Award',
subLabel:'Ceremony', subLabel: 'Ceremony',
time: 'Nov 12', time: 'Nov 12',
desc: 'Award Ceremony &\nCommunity Gathering\n Soho House.' desc: 'Award Ceremony &\nCommunity Gathering\n Soho House.'
}, }
]) ])
const playAnimation = () => { const playAnimation = () => {
@@ -120,7 +129,7 @@
}, },
{ {
clipPath: 'inset(0 0% 0 0)', clipPath: 'inset(0 0% 0 0)',
duration: 1.6, duration: 1.3,
ease: 'power1.out' ease: 'power1.out'
}, },
'start' 'start'
@@ -157,16 +166,14 @@
) )
} }
// 行内文字(标签、时间、描述)与 start 同步开始 // 行内文字(标签、时间、描述、图标)与 start 同步开始
const textItems = containerRef.value.querySelectorAll( const textItems = containerRef.value.querySelectorAll('.grid-cell')
'.item-label, .item-time, .item-desc .txt'
)
if (textItems && textItems.length) { if (textItems && textItems.length) {
tl.from( tl.from(
textItems, textItems,
{ {
autoAlpha: 0.5, // autoAlpha: 0.5,
duration: 0.6, duration: 0.7,
stagger: 0.08, stagger: 0.08,
ease: 'power2.out' ease: 'power2.out'
}, },
@@ -174,22 +181,6 @@
) )
} }
// 所有文字与线条完成后,立即开始点图标动画(按顺序出现)
const icons = containerRef.value.querySelectorAll('.point-icon')
if (icons && icons.length) {
// 与 'start' 标签同步开始:改为纯淡入动画(移除缩放)
tl.from(
icons,
{
autoAlpha: 0,
duration: 2,
stagger: 0.12,
ease: 'power2.out'
},
'start+=0.3'
)
}
hasAnimated.value = true hasAnimated.value = true
} }
@@ -199,8 +190,8 @@
await nextTick() await nextTick()
if (!containerRef.value) return if (!containerRef.value) return
observer = new IntersectionObserver( observer = new IntersectionObserver(
(entries) => { entries => {
entries.forEach((entry) => { entries.forEach(entry => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
playAnimation() playAnimation()
} }
@@ -224,7 +215,7 @@
background: url('@/assets/images/award/timeline_bg.png') no-repeat; background: url('@/assets/images/award/timeline_bg.png') no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
position: relative; position: relative;
padding-top: 12.8rem; padding: 12.8rem 0 15.9rem;
width: 100%; width: 100%;
color: #fff; color: #fff;
.timeline-title { .timeline-title {
@@ -248,42 +239,45 @@
will-change: clip-path; will-change: clip-path;
flex: 1; flex: 1;
width: 100%; width: 100%;
margin-top: 12rem; margin-top: 11rem;
padding: 0 21.2rem 0 22rem; padding: 0 13.8rem;
position: relative; position: relative;
z-index: 2; z-index: 2;
.labels-row { // 主网格布局5列
position: relative; display: grid;
z-index: 2; grid-template-columns: repeat(5, 1fr);
margin-bottom: 8rem; grid-template-rows: auto auto auto auto;
.item-label { grid-column-gap: 0;
flex: 1; grid-row-gap: 0;
color: #fff;
font-family: 'PoppinsBold'; // 所有 grid 子行的通用样式
font-weight: 600; .grid-row {
font-size: 2.8rem; display: grid;
text-align: center; grid-template-columns: repeat(5, 1fr);
white-space: pre-line; grid-column: 1 / -1;
// height: 6rem;
justify-content: center;
}
} }
.grid-cell {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
// 图标行
.icons-row { .icons-row {
margin-bottom: 1.6rem; align-items: center;
height: 6.4rem;
position: relative; position: relative;
z-index: 2; z-index: 2;
.point-icon { margin-bottom: 1.6rem;
width: 6.4rem;
height: 6.4rem;
display: block;
margin: 0 auto;
z-index: 2;
}
.timeline-line { .timeline-line {
width: calc(100% + 22rem + 21.2rem); position: absolute;
top: 50%;
left: -22rem; left: -22rem;
right: -21.2rem;
height: 0.15rem; height: 0.15rem;
background: linear-gradient( background: linear-gradient(
90deg, 90deg,
@@ -293,40 +287,78 @@
rgba(199, 52, 44, 0.762376) 75.96%, rgba(199, 52, 44, 0.762376) 75.96%,
rgba(199, 52, 44, 0) 100% rgba(199, 52, 44, 0) 100%
); );
position: absolute;
bottom: 50%;
transform: translateY(-50%); transform: translateY(-50%);
z-index: 1; z-index: 1;
pointer-events: none;
}
.icon-cell {
position: relative;
.point-icon {
width: 6.4rem;
height: 6.4rem;
display: block;
position: relative;
z-index: 2;
}
} }
} }
// 标签行
.labels-row {
margin-bottom: 8rem;
position: relative;
z-index: 2;
.label-cell {
flex-direction: column;
color: #fff;
font-family: 'PoppinsBold';
font-weight: 600;
font-size: 2.8rem;
white-space: pre-line;
justify-content: center;
min-height: 6rem;
// .sub-label {
// font-family: 'Arial';
// font-weight: 400;
// font-size: 1.4rem;
// color: rgba(255, 255, 255, 0.8);
// margin-top: 0.4rem;
// }
}
}
// 时间行
.times-row { .times-row {
margin-bottom: 6rem; margin-bottom: 6rem;
z-index: 2; z-index: 2;
position: relative; position: relative;
.item-time { .time-cell {
flex: 1;
color: #f95750; color: #f95750;
font-family: 'Arial'; font-family: 'Arial';
font-weight: 400; font-weight: 400;
font-size: 2.8rem; font-size: 2.8rem;
line-height: 4.5rem; line-height: 4.5rem;
text-align: center;
} }
} }
// 描述行
.descs-row { .descs-row {
.item-desc { .desc-cell {
flex: 1;
.txt { .txt {
font-family: 'Arial'; font-family: 'Arial';
font-weight: 400; font-weight: 400;
font-size: 2rem; font-size: 2rem;
text-align: center; text-align: center;
color: #e0e0e0; color: #e0e0e0;
width: 31.2rem; width: 100%;
height: 10.2rem; max-width: 31.2rem;
min-height: 10.2rem;
white-space: pre-line; white-space: pre-line;
display: flex;
align-items: center;
justify-content: center;
} }
} }
} }

View File

@@ -63,7 +63,7 @@
height: 2.4rem; height: 2.4rem;
} }
.banner { .banner {
height: 108rem; height: 100rem;
// background: url('@/assets/images/award/banner.png') no-repeat; // background: url('@/assets/images/award/banner.png') no-repeat;
// background-size: cover; // background-size: cover;
position: relative; position: relative;