Compare commits
101 Commits
758f63615a
...
StableVers
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ed5a37e5b | ||
|
|
5546c71ec0 | ||
|
|
8a7776a4b6 | ||
|
|
a1281c8e3f | ||
|
|
9a40e69081 | ||
|
|
e27b43dc67 | ||
|
|
b6a55a8124 | ||
| 6cace08a51 | |||
| 6207095221 | |||
|
|
7bb38bf2e5 | ||
|
|
743fc762d6 | ||
| 7297e4e7a4 | |||
| 3bff1ebb66 | |||
| 0d1656ee0a | |||
| 7d0873d874 | |||
| 82941bca7c | |||
| 949ff9292d | |||
|
|
11c9de8ced | ||
|
|
fd518ad9b3 | ||
|
|
a2b45e2041 | ||
|
|
da64b57c1c | ||
|
|
7c14b1d831 | ||
|
|
8966b52430 | ||
|
|
5fa049f73d | ||
|
|
575445f767 | ||
|
|
f43c56236b | ||
|
|
4352f7c2f4 | ||
|
|
c6b1bdbdf1 | ||
|
|
f16aa6ea14 | ||
|
|
a25abeb527 | ||
|
|
d359cd7763 | ||
| 23085d9a9b | |||
| bb021ae9ac | |||
| bfb4e128f5 | |||
| 2f9b33e4ca | |||
|
|
35c6dfe29c | ||
|
|
48c37e0810 | ||
| b869a82fae | |||
| e61a8e372d | |||
|
|
f5a74991c9 | ||
|
|
e58e8540c9 | ||
| e75ed7684e | |||
| 918d71072b | |||
|
|
242bc7a01d | ||
|
|
02ad8a340a | ||
|
|
0c250a21b4 | ||
|
|
f781060e7b | ||
|
|
832c9101ab | ||
|
|
c48e836f8e | ||
|
|
6f0780ac2e | ||
|
|
5acb91e584 | ||
|
|
f66ba9e6fa | ||
| 7a90cb8db9 | |||
| dafe87fad8 | |||
| c44747e2c2 | |||
|
|
341c765c73 | ||
|
|
ed6cc294a5 | ||
|
|
a77dc718f9 | ||
|
|
86953a91a1 | ||
| cabbb653bd | |||
| 99533c12b6 | |||
|
|
59da67e4b4 | ||
|
|
1428f191dd | ||
|
|
13024cdd99 | ||
|
|
fd85ea02c1 | ||
|
|
c196ab6678 | ||
|
|
c005b85c06 | ||
|
|
b50dbbc246 | ||
|
|
01d09f4c34 | ||
|
|
79c9a66296 | ||
|
|
761b1b3512 | ||
|
|
b2cb7378d6 | ||
| 4d9ea75146 | |||
| f7e6926ee9 | |||
| 7aba4e30c9 | |||
| dc1ab330cf | |||
|
|
18c70fe6a3 | ||
|
|
5c746aca4d | ||
|
|
72c4898101 | ||
|
|
a905971dae | ||
| 69643dbc83 | |||
| f3a707d6d8 | |||
| 8f4a43db14 | |||
| 186a158114 | |||
| 3da4a97400 | |||
|
|
96b3636aea | ||
| 228e3d56b5 | |||
| 99ea7eedc7 | |||
| d4fb435db9 | |||
| 0c8b3ee8f1 | |||
| ca782d0aff | |||
|
|
3dfb607b91 | ||
|
|
981b4dad5c | ||
|
|
181e6a87b8 | ||
| 287825b4bf | |||
| 1ffc303721 | |||
|
|
bdf1bb2669 | ||
|
|
1fe79ffcf9 | ||
|
|
012f0ef1b5 | ||
|
|
2d5d1b7a5e | ||
|
|
f6556ec9a9 |
33
.prettierrc.js
Normal file
33
.prettierrc.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/** @type {import('prettier').Config} */
|
||||
module.exports = {
|
||||
// 打印宽度
|
||||
printWidth: 100,
|
||||
// 使用 4 空格缩进
|
||||
tabWidth: 4,
|
||||
// 使用 4 空格缩进,不使用制表符
|
||||
useTabs: true,
|
||||
// 行尾使用 LF (Unix 风格)
|
||||
endOfLine: 'lf',
|
||||
// 语句末尾使用分号
|
||||
semi: false,
|
||||
// 使用单引号
|
||||
singleQuote: false,
|
||||
// 对象和数组末尾不添加尾随逗号
|
||||
trailingComma: 'none',
|
||||
// JSX 引号使用单引号
|
||||
jsxSingleQuote: false,
|
||||
// 括号内侧空格
|
||||
bracketSpacing: true,
|
||||
// JSX 标签不换行
|
||||
bracketSameLine: false,
|
||||
// 箭头函数参数始终使用括号
|
||||
arrowParens: 'always',
|
||||
// HTML、Vue、Angular 和 Markdown 使用 LF
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
// Vue 文件脚本和样式缩进
|
||||
vueIndentScriptAndStyle: false,
|
||||
// 行注释位置在注释上方,不加空格
|
||||
proseWrap: 'preserve',
|
||||
// 根据文件类型自动推断
|
||||
embeddedLanguageFormatting: 'auto',
|
||||
};
|
||||
BIN
public/image/events/award-poster-zh.gif
Normal file
BIN
public/image/events/award-poster-zh.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 MiB |
BIN
public/image/events/award-poster.gif
Normal file
BIN
public/image/events/award-poster.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 252 B After Width: | Height: | Size: 327 B |
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 MiB |
BIN
src/assets/images/award/banner_chinese.mp4
Normal file
BIN
src/assets/images/award/banner_chinese.mp4
Normal file
Binary file not shown.
@@ -2,92 +2,129 @@
|
||||
"eventsList": [
|
||||
{
|
||||
"id": 1,
|
||||
"title":"Just post your design work, you could have the chance to come to Hong Kong and interact with industry leaders face-to-face!",
|
||||
"title": "Just post your design work, you could have the chance to come to Hong Kong and interact with industry leaders face-to-face!",
|
||||
"imgUrl": "/image/events/workshop-En.jpg"
|
||||
},{
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title":"AiDA X SFT AI Fashion Award 2024",
|
||||
"title": "AiDA X SFT AI Fashion Award 2024",
|
||||
"imgUrl": "/image/events/Fashion-Award-2024.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "AiDA Global Design Awards 2026",
|
||||
"imgUrl": "/image/events/award-poster.gif"
|
||||
}
|
||||
],
|
||||
"eventsItem":[
|
||||
"eventsItem": [
|
||||
{
|
||||
"id":1,
|
||||
"title":"Just post your design work, you could have the chance to come to Hong Kong and interact with industry leaders face-to-face!",
|
||||
"imgUrl": "/image/events/workshop-En.jpg",
|
||||
"textList":[
|
||||
"id": 3,
|
||||
"title": "AiDA Global Design Awards 2026",
|
||||
"imgUrl": "/image/events/award-poster.gif",
|
||||
"tips": "For inquiries: awards2026@code-create.com.hk",
|
||||
"textList": [
|
||||
{
|
||||
"paragraph":[
|
||||
"paragraph": [
|
||||
{
|
||||
"text":"🎨AiDA Workshop!"
|
||||
"text": "Click the “View Details” button for more information and to join the competition! The AiDA Global Design Award 2026 is an international design competition hosted by Code‑Create, a globally leading AI fashion solutions provider, celebrating the future of creativity powered by artificial intelligence. Open to designers worldwide the competition brings together global talent, empowering AI as a creative partner—pushing fashion beyond traditional boundaries and unlocking new possibilities where technology amplifies human imagination."
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
},
|
||||
{
|
||||
"text":"The process is simple: use AiDA to post your design work on the 'Gallery', and the one with the most likes(at least 20 likes) will be invited to the AiDA Workshop offline event in Hong Kong on November 14th, to exchange ideas with the Royal College of Art (RCA), Jae Lim, co-founder of the renowned fashion brand BESFXXK, and outstanding designers! "
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
"paragraph": [
|
||||
{
|
||||
"text":"<b>⚠️ATTENTION❗❗</b>"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"1. Add the tag in the work description #AiDAworkshop_2024"
|
||||
},{
|
||||
"text":"2. One winner only"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"<b>🤩Code-Create will provide (Terms and conditions apply):</b>"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"✅Round-trip transportation fee (only within China)"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"✅One night accommodation fee"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"⌛️Deadline: October 31, 2024"
|
||||
"text": "Participants have the opportunity to compete for cash prizes totaling up to US$9,000, gain global media exposure showcased by top international platforms, and connect with designers and industry leaders worldwide. Finalists will also attend an exclusive award ceremony in Hong Kong, with travel allowance, allowing them to showcase their talent, network with professionals, and celebrate their achievements on an international stage."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id":2,
|
||||
"title":"AiDA X SFT AI Fashion Award 2024",
|
||||
"id": 1,
|
||||
"title": "Just post your design work, you could have the chance to come to Hong Kong and interact with industry leaders face-to-face!",
|
||||
"imgUrl": "/image/events/workshop-En.jpg",
|
||||
"textList": [
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "🎨AiDA Workshop!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "The process is simple: use AiDA to post your design work on the 'Gallery', and the one with the most likes(at least 20 likes) will be invited to the AiDA Workshop offline event in Hong Kong on November 14th, to exchange ideas with the Royal College of Art (RCA), Jae Lim, co-founder of the renowned fashion brand BESFXXK, and outstanding designers! "
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "<b>⚠️ATTENTION❗❗</b>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "1. Add the tag in the work description #AiDAworkshop_2024"
|
||||
},
|
||||
{
|
||||
"text": "2. One winner only"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "<b>🤩Code-Create will provide (Terms and conditions apply):</b>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "✅Round-trip transportation fee (only within China)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "✅One night accommodation fee"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "⌛️Deadline: October 31, 2024"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "AiDA X SFT AI Fashion Award 2024",
|
||||
"imgUrl": "/image/events/Fashion-Award-2024.png",
|
||||
"textList":[
|
||||
"textList": [
|
||||
{
|
||||
"paragraph":[
|
||||
"paragraph": [
|
||||
{
|
||||
"text":"With the aim of inspiring students to innovate in fashion design using AI, Code-Create and The Hong Kong Polytechnic University School of Fashion and Textiles (SFT) have jointly launched the 'AiDA X SFT AI Fashion Award 2024'. This competition provides students with valuable practical AiDA experience, laying the foundation for the future fashion design industry and positioning them as pioneers in AI fashion."
|
||||
"text": "With the aim of inspiring students to innovate in fashion design using AI, Code-Create and The Hong Kong Polytechnic University School of Fashion and Textiles (SFT) have jointly launched the 'AiDA X SFT AI Fashion Award 2024'. This competition provides students with valuable practical AiDA experience, laying the foundation for the future fashion design industry and positioning them as pioneers in AI fashion."
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
},
|
||||
{
|
||||
"text":"The competition is open to all SFT students, with the winners having the chance to win cash prizes (up to 20,000 HKD), internship opportunity at BESFXXK (will work with the renowned designer, Mr Jae Hyuk Lim, for the BESFXXK collection, that will be featured at NY Fashion Week and Paris Fashion Week) and more surprises! Scan the QR code to learn more."
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "The competition is open to all SFT students, with the winners having the chance to win cash prizes (up to 20,000 HKD), internship opportunity at BESFXXK (will work with the renowned designer, Mr Jae Hyuk Lim, for the BESFXXK collection, that will be featured at NY Fashion Week and Paris Fashion Week) and more surprises! Scan the QR code to learn more."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,88 +2,125 @@
|
||||
"eventsList": [
|
||||
{
|
||||
"id": 1,
|
||||
"title":"什么?只要发布设计作品就有机会来香港与大佬面对面交流?!",
|
||||
"title": "什么?只要发布设计作品就有机会来香港与大佬面对面交流?!",
|
||||
"imgUrl": "/image/events/workshop-Cn.jpg"
|
||||
},{
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title":"AiDA X SFT AI时尚设计比赛2024",
|
||||
"title": "AiDA X SFT AI时尚设计比赛2024",
|
||||
"imgUrl": "/image/events/Fashion-Award-2024.png"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "AiDA全球设计奖 2026",
|
||||
"imgUrl": "/image/events/award-poster-zh.gif"
|
||||
}
|
||||
],
|
||||
"eventsItem":[
|
||||
"eventsItem": [
|
||||
{
|
||||
"id":1,
|
||||
"title":"什么?只要发布设计作品就有机会来香港与大佬面对面交流?!",
|
||||
"imgUrl": "/image/events/workshop-Cn.jpg",
|
||||
"textList":[
|
||||
"id": 3,
|
||||
"title": "AiDA全球设计奖 2026",
|
||||
"imgUrl": "/image/events/award-poster-zh.gif",
|
||||
"tips": "如有疑问,请联系:awards2026@code-create.com.hk",
|
||||
"textList": [
|
||||
{
|
||||
"paragraph":[
|
||||
"paragraph": [
|
||||
{
|
||||
"text":"🎨这是一趟艺术巅峰之旅!AiDA Workshop!"
|
||||
"text": "秉承推动 AI 赋能创意设计的初衷,Code‑Create 举办了「AiDA 全球设计大奖 2026」,面向来全球的设计师,鼓励大家探索 AI 与时尚设计的无限可能,突破传统界限,释放科技与想象力的创新潜能。点击“查看详情”按钮获取更多比赛信息,抓住成为 AI 时尚先锋的机会吧!"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
},
|
||||
{
|
||||
"text":"参与过程很简单,利用AiDA 在 “Gallery广场 ”发布设计作品,最终获赞最高者(至少20个赞)将被邀请至11月14日 举办的AiDA Workshop香港线下活动,与英国皇家艺术学院(RCA)、韩国知名时尚品牌BESFXXK创始人JAE以及优秀设计师一同交流!(名额仅限1名)"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
"paragraph": [
|
||||
{
|
||||
"text":"<b>⚠️注意❗❗</b>"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"1. 作品描述添加tag: #AiDAworkshop_2024"
|
||||
},{
|
||||
"text":"2. 一个冠军名额"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"<b>🤩Code-Create将提供(适用条款条规):</b>"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"✅往返机票/动车费用(仅限中国地区)"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"✅一晚酒店住宿费用"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
{
|
||||
"text":"⌛️截止时间:2024.10.31"
|
||||
"text": "参赛者将有机会赢取总奖金 9,000 美元,作品还将获得国际媒体展示机会,并与全球设计师和行业领袖建立联系。入围决赛者将受邀参加在香港举办的 专属颁奖典礼,主办方提供差旅津贴,让设计师在国际舞台展示才华、拓展人脉,并共同庆祝创意成果。"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id":2,
|
||||
"title":"AiDA X SFT AI时尚设计比赛2024",
|
||||
"imgUrl": "/image/events/Fashion-Award-2024.png",
|
||||
"textList":[
|
||||
"id": 1,
|
||||
"title": "什么?只要发布设计作品就有机会来香港与大佬面对面交流?!",
|
||||
"imgUrl": "/image/events/workshop-Cn.jpg",
|
||||
"textList": [
|
||||
{
|
||||
"paragraph":[
|
||||
"paragraph": [
|
||||
{
|
||||
"text":"秉承着激发学生使用AI进行时尚设计的创新能力的初衷,Code-Create和香港理工大学时装及纺织学院(SFT)共同举办了“AiDA X SFT AI时尚设计比赛2024”让学生们在比赛中获得宝贵的AiDA实践经验,为未来的时尚设计行业打下了坚实的基础,成为时尚界的AI先锋。"
|
||||
"text": "🎨这是一趟艺术巅峰之旅!AiDA Workshop!"
|
||||
}
|
||||
]
|
||||
},{
|
||||
"paragraph":[
|
||||
},
|
||||
{
|
||||
"text":" 此次比赛面向全体SFT 学生,最终获奖者将赢取丰厚奖金(最高可达2万港币),获得在BESFXXK的实习机会(将与著名设计师Lim Jae Hyuk先生合作设计BESFXXK 系列,该系列将在纽约时装周和巴黎时装周上展出)及更多惊喜哦!扫描二维码获取更多比赛信息。"
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "参与过程很简单,利用AiDA 在 “Gallery广场 ”发布设计作品,最终获赞最高者(至少20个赞)将被邀请至11月14日 举办的AiDA Workshop香港线下活动,与英国皇家艺术学院(RCA)、韩国知名时尚品牌BESFXXK创始人JAE以及优秀设计师一同交流!(名额仅限1名)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "<b>⚠️注意❗❗</b>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "1. 作品描述添加tag: #AiDAworkshop_2024"
|
||||
},
|
||||
{
|
||||
"text": "2. 一个冠军名额"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "<b>🤩Code-Create将提供(适用条款条规):</b>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "✅往返机票/动车费用(仅限中国地区)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "✅一晚酒店住宿费用"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "⌛️截止时间:2024.10.31"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "AiDA X SFT AI时尚设计比赛2024",
|
||||
"imgUrl": "/image/events/Fashion-Award-2024.png",
|
||||
"textList": [
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": "秉承着激发学生使用AI进行时尚设计的创新能力的初衷,Code-Create和香港理工大学时装及纺织学院(SFT)共同举办了“AiDA X SFT AI时尚设计比赛2024”让学生们在比赛中获得宝贵的AiDA实践经验,为未来的时尚设计行业打下了坚实的基础,成为时尚界的AI先锋。"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"paragraph": [
|
||||
{
|
||||
"text": " 此次比赛面向全体SFT 学生,最终获奖者将赢取丰厚奖金(最高可达2万港币),获得在BESFXXK的实习机会(将与著名设计师Lim Jae Hyuk先生合作设计BESFXXK 系列,该系列将在纽约时装周和巴黎时装周上展出)及更多惊喜哦!扫描二维码获取更多比赛信息。"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,21 +2,36 @@
|
||||
<div class="account_systemMessage">
|
||||
<div class="account_generalMessage_title modal_title_text">
|
||||
<!-- <span>系统消息</span> -->
|
||||
<div class="account_generalMessage_title_setting" @click="allRead">{{$t('account.AllRead')}}</div>
|
||||
<div class="account_generalMessage_title_setting" @click="allRead">
|
||||
{{ $t("account.AllRead") }}
|
||||
</div>
|
||||
<div class="account_generalMessage_item modal_title_text" v-for="item in dataList" :key="item.id" @click="setRead(item)">
|
||||
</div>
|
||||
<div
|
||||
class="account_generalMessage_item modal_title_text"
|
||||
v-for="item in dataList"
|
||||
:key="item.id"
|
||||
@click="setRead(item)"
|
||||
>
|
||||
<a-badge :dot="item.isRead == 0"></a-badge>
|
||||
<div class="account_generalMessage_item_title">
|
||||
<div class="account_generalMessage_item_title_text" :title="item.content">{{ item.content.title }}</div>
|
||||
<div class="account_generalMessage_item_title_text" :title="item.content">
|
||||
{{ item.content.title }}
|
||||
</div>
|
||||
<div class="modal_title_text_intro">{{ item.createTime }}</div>
|
||||
</div>
|
||||
<div class="modal_title_text_intro">
|
||||
{{ item.content.content }}
|
||||
<span v-if="item.content.link" class="account_generalMessage_item_link">{{ item.content.link }}</span>
|
||||
<span v-if="item.content.link" class="account_generalMessage_item_link">{{
|
||||
item.content.link
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="account_generalMessage_item modal_title_text" style="display:flex;justify-content: center;" v-if="dataList.length == 0 && isNoData">
|
||||
{{$t('account.dataNull')}}
|
||||
<div
|
||||
class="account_generalMessage_item modal_title_text"
|
||||
style="display: flex; justify-content: center"
|
||||
v-if="dataList.length == 0 && isNoData"
|
||||
>
|
||||
{{ $t("account.dataNull") }}
|
||||
</div>
|
||||
<div class="page_loading_box" v-show="!isNoData">
|
||||
<span class="page_loading" ref="loadingDom" v-show="!isShowMark"></span>
|
||||
@@ -27,117 +42,135 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,ref,reactive,nextTick,toRefs,createVNode, onMounted} from 'vue'
|
||||
import { Https } from "@/tool/https";
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import { useStore } from "vuex";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
defineComponent,
|
||||
computed,
|
||||
ref,
|
||||
reactive,
|
||||
nextTick,
|
||||
toRefs,
|
||||
createVNode,
|
||||
onMounted
|
||||
} from "vue"
|
||||
import { Https } from "@/tool/https"
|
||||
import { useRouter, useRoute } from "vue-router"
|
||||
import { useStore } from "vuex"
|
||||
import { useI18n } from "vue-i18n"
|
||||
import { isValidUrl } from "@/tool/util"
|
||||
export default defineComponent({
|
||||
components:{
|
||||
},
|
||||
components: {},
|
||||
// emits:['putListData'],
|
||||
props:['setReadStatus','setAllmessage','getHistory'],
|
||||
setup(prop,{emit}) {
|
||||
props: ["setReadStatus", "setAllmessage", "getHistory"],
|
||||
setup(prop, { emit }) {
|
||||
const router = useRouter()
|
||||
const store = useStore();
|
||||
const store = useStore()
|
||||
let accountMessage = reactive({
|
||||
dataList: [],
|
||||
page:1,
|
||||
size:10,
|
||||
page: 1,
|
||||
size: 10,
|
||||
isNoData: false,
|
||||
isShowMark: false,
|
||||
isShowMark: false
|
||||
})
|
||||
let loadingDom:any = ref(null)
|
||||
let setmessageList = ()=>{
|
||||
let loadingDom: any = ref(null)
|
||||
let setmessageList = () => {
|
||||
accountMessage.isShowMark = true
|
||||
let data = {
|
||||
page: accountMessage.page,
|
||||
size: accountMessage.size,
|
||||
size: accountMessage.size
|
||||
}
|
||||
prop.getHistory(data).then((rv:any)=>{
|
||||
prop.getHistory(data)
|
||||
.then((rv: any) => {
|
||||
accountMessage.isShowMark = false
|
||||
|
||||
if(rv.content.length == 0) {
|
||||
if (rv.content.length == 0) {
|
||||
accountMessage.isNoData = true
|
||||
}else{
|
||||
rv.content.forEach((item:any) => {
|
||||
} else {
|
||||
rv.content.forEach((item: any) => {
|
||||
item.content = JSON.parse(item.content)
|
||||
});
|
||||
})
|
||||
accountMessage.dataList.push(...rv.content)
|
||||
}
|
||||
}).catch(() => {
|
||||
})
|
||||
.catch(() => {
|
||||
accountMessage.isShowMark = false
|
||||
accountMessage.isNoData = true
|
||||
})
|
||||
}
|
||||
let setRead = (item:any)=>{
|
||||
prop.setReadStatus(item).then((rv:any)=>{
|
||||
item.isRead = 1
|
||||
}).catch((err:any)=>{
|
||||
})
|
||||
let setRead = (item: any) => {
|
||||
let content = item.content.content
|
||||
if (isValidUrl(content)) {
|
||||
if (import.meta.env.VITE_APP_BASE_URL === "https://develop.api.aida.com.hk") {
|
||||
content += "&env=dev"
|
||||
}
|
||||
let allRead = ()=>{
|
||||
// emit('setAllmessage')
|
||||
prop.setAllmessage().then(()=>{
|
||||
accountMessage.dataList.forEach((item:any)=>{
|
||||
window.open(content, "_blank")
|
||||
}
|
||||
|
||||
prop.setReadStatus(item)
|
||||
.then((rv: any) => {
|
||||
item.isRead = 1
|
||||
})
|
||||
}).catch((err:any)=>{
|
||||
.catch((err: any) => {})
|
||||
}
|
||||
let allRead = () => {
|
||||
// emit('setAllmessage')
|
||||
prop.setAllmessage()
|
||||
.then(() => {
|
||||
accountMessage.dataList.forEach((item: any) => {
|
||||
item.isRead = 1
|
||||
})
|
||||
})
|
||||
.catch((err: any) => {})
|
||||
}
|
||||
// provide('exhibitionList',exhibitionList)
|
||||
onMounted (()=>{
|
||||
onMounted(() => {
|
||||
accountMessage.isNoData = false
|
||||
accountMessage.page = 0
|
||||
let imgParent:any = document.querySelector('.account_systemMessage .page_loading')
|
||||
let imgParent: any = document.querySelector(".account_systemMessage .page_loading")
|
||||
new IntersectionObserver(
|
||||
(entries, observer) => {
|
||||
// 如果不是相交,则直接返回
|
||||
// console.log(entries[0]);
|
||||
if (!entries[0].intersectionRatio) return;
|
||||
accountMessage.page+=1
|
||||
if (!entries[0].intersectionRatio) return
|
||||
accountMessage.page += 1
|
||||
setmessageList()
|
||||
},
|
||||
}
|
||||
// { root:worksPage }
|
||||
).observe(loadingDom.value);
|
||||
).observe(loadingDom.value)
|
||||
})
|
||||
return{
|
||||
return {
|
||||
...toRefs(accountMessage),
|
||||
setmessageList,
|
||||
setRead,
|
||||
allRead,
|
||||
loadingDom,
|
||||
loadingDom
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.account_systemMessage{
|
||||
.account_systemMessage {
|
||||
width: 100%;
|
||||
.account_generalMessage_item{
|
||||
.account_generalMessage_item {
|
||||
font-size: var(--aida-fsize1-6);
|
||||
.account_generalMessage_item_title{
|
||||
.account_generalMessage_item_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
.account_generalMessage_item_title_text{
|
||||
.account_generalMessage_item_title_text {
|
||||
max-width: 80%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.modal_title_text_intro{
|
||||
.modal_title_text_intro {
|
||||
margin-left: 4rem;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal_title_text_intro{
|
||||
.modal_title_text_intro {
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
font-family: Arial, sans-serif;
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
total: total,
|
||||
showQuickJumper: true,
|
||||
bordered: false,
|
||||
showTotal: (total) => `Total Transaction: ${total}`
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, text, record, index }">
|
||||
@@ -465,13 +466,16 @@ export default defineComponent({
|
||||
(rv: any) => {
|
||||
if (rv) {
|
||||
// this.dataList = rv
|
||||
// console.log('rv----',rv);
|
||||
|
||||
filter.dataList = rv.content;
|
||||
filterData.total = rv.total;
|
||||
filter.tableLoading = false;
|
||||
filterData.totalPayer = rv.content.reduce((total: number, item: any) => {
|
||||
const value = item && item.status === 'Success' ? parseFloat(item.payerTotal) : 0;
|
||||
return total + (isNaN(value) ? 0 : value);
|
||||
}, 0);
|
||||
filterData.totalPayer = rv.totalAmount;
|
||||
// filterData.totalPayer = rv.content.reduce((total: number, item: any) => {
|
||||
// const value = item && item.status === 'Success' ? parseFloat(item.payerTotal) : 0;
|
||||
// return total + (isNaN(value) ? 0 : value);
|
||||
// }, 0);
|
||||
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="admin_page">
|
||||
<div class="admin_table_search" :style="{height:isAwayOrUnfold?'7rem':''}">
|
||||
<div class="admin_table_search" :style="{ height: isAwayOrUnfold ? '7rem' : '' }">
|
||||
<div class="admin_state">
|
||||
<div class="admin_state_item">
|
||||
<span>Create Time:</span>
|
||||
@@ -8,16 +8,11 @@
|
||||
style="width: 250px"
|
||||
class="range_picker"
|
||||
v-model:value="rangePickerValue"
|
||||
:placeholder="[
|
||||
$t('HistoryPage.StartDate'),
|
||||
$t('HistoryPage.EndDate'),
|
||||
]"
|
||||
:placeholder="[$t('HistoryPage.StartDate'), $t('HistoryPage.EndDate')]"
|
||||
valueFormat="YYYY-MM-DD"
|
||||
>
|
||||
<template #suffixIcon>
|
||||
<span
|
||||
class="icon iconfont range_picker_icon icon-rili"
|
||||
></span>
|
||||
<span class="icon iconfont range_picker_icon icon-rili"></span>
|
||||
</template>
|
||||
</a-range-picker>
|
||||
</div>
|
||||
@@ -63,38 +58,50 @@
|
||||
show-search
|
||||
></a-select>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Orgnization:</span>
|
||||
<a-select
|
||||
v-model:value="organizationId"
|
||||
placeholder="Select the organization"
|
||||
allow-clear
|
||||
style="width: 250px"
|
||||
@popupScroll="handleOrganizationScroll"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in organizationOptions"
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
>
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
<div class="admin_search_item" @click="searchHistoryList" :style="{height:isAwayOrUnfold?'4rem':''}">
|
||||
<div
|
||||
class="admin_search_item"
|
||||
@click="searchHistoryList"
|
||||
:style="{ height: isAwayOrUnfold ? '4rem' : '' }"
|
||||
>
|
||||
Search
|
||||
</div>
|
||||
<div class="admin_search_item" @click="addhHistoryList">
|
||||
Add
|
||||
</div>
|
||||
<div class="admin_search_item" @click="addhHistoryList">Add</div>
|
||||
</div>
|
||||
<div class="admin_state_list">
|
||||
<div
|
||||
class="admin_state_list_item"
|
||||
@click="lastGeTrialList('year')"
|
||||
>
|
||||
<div class="admin_state_list_item" @click="lastGeTrialList('year')">
|
||||
Nearly a year
|
||||
</div>
|
||||
<div
|
||||
class="admin_state_list_item"
|
||||
@click="lastGeTrialList('month')"
|
||||
>
|
||||
<div class="admin_state_list_item" @click="lastGeTrialList('month')">
|
||||
Last month
|
||||
</div>
|
||||
<div
|
||||
class="admin_state_list_item"
|
||||
@click="lastGeTrialList('week')"
|
||||
>
|
||||
Last week
|
||||
<div class="admin_state_list_item" @click="lastGeTrialList('week')">Last week</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="awayOrUnfold" :class="{active:isAwayOrUnfold}">
|
||||
<span class="icon iconfont menu_icon icon-xiala" @click="()=>isAwayOrUnfold = !isAwayOrUnfold"></span>
|
||||
<div class="awayOrUnfold" :class="{ active: isAwayOrUnfold }">
|
||||
<span
|
||||
class="icon iconfont menu_icon icon-xiala"
|
||||
@click="() => (isAwayOrUnfold = !isAwayOrUnfold)"
|
||||
></span>
|
||||
</div>
|
||||
<div class="admin_table_content" ref="historyTable">
|
||||
<a-table
|
||||
@@ -104,24 +111,19 @@
|
||||
:data-source="dataList"
|
||||
:scroll="{ y: historyTableHeight }"
|
||||
@change="changePage"
|
||||
:showSorterTooltip='false'
|
||||
:showSorterTooltip="false"
|
||||
:pagination="{
|
||||
showSizeChanger: true,
|
||||
current: currentPage,
|
||||
pageSize: pageSize,
|
||||
total: total,
|
||||
showQuickJumper: true,
|
||||
bordered: false,
|
||||
bordered: false
|
||||
}"
|
||||
>
|
||||
<template #bodyCell="{ column, text, record, index }">
|
||||
<div class="operate_list" v-if="column?.Operations">
|
||||
<div
|
||||
class="operate_item"
|
||||
@click="setAagree(record)"
|
||||
>
|
||||
Edit
|
||||
</div>
|
||||
<div class="operate_item" @click="setAagree(record)">Edit</div>
|
||||
<!-- <div
|
||||
class="operate_item"
|
||||
@click="deleteGroup(record, index)"
|
||||
@@ -132,34 +134,29 @@
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<allUserPoerationsVue ref="allUserPoerationsVue" @searchHistoryList="searchHistoryList"></allUserPoerationsVue>
|
||||
<allUserPoerationsVue
|
||||
ref="allUserPoerationsVue"
|
||||
@searchHistoryList="searchHistoryList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
createVNode,
|
||||
computed,
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
} from "vue";
|
||||
import { formatTime } from "@/tool/util";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https";
|
||||
import allUserPoerationsVue from "./allUserPoerations.vue";
|
||||
import SelectUser from '@/component/common/SelectUser.vue'
|
||||
import { defineComponent, ref, createVNode, computed, reactive, toRefs, onMounted } from "vue"
|
||||
import { formatTime } from "@/tool/util"
|
||||
import { useStore } from "vuex"
|
||||
import { Https } from "@/tool/https"
|
||||
import allUserPoerationsVue from "./allUserPoerations.vue"
|
||||
import SelectUser from "@/component/common/SelectUser.vue"
|
||||
export default defineComponent({
|
||||
components: {allUserPoerationsVue,SelectUser},
|
||||
components: { allUserPoerationsVue, SelectUser },
|
||||
setup() {
|
||||
const store:any = useStore()
|
||||
const store: any = useStore()
|
||||
let filter: any = reactive({
|
||||
dataList: [],
|
||||
tableLoading: false,
|
||||
allCountry:[],
|
||||
isAwayOrUnfold:false
|
||||
});
|
||||
allCountry: [],
|
||||
isAwayOrUnfold: false
|
||||
})
|
||||
let filterData: any = reactive({
|
||||
rangePickerValue: [],
|
||||
currentPage: 1,
|
||||
@@ -172,40 +169,41 @@ export default defineComponent({
|
||||
occupation: "",
|
||||
systemUser: "",
|
||||
order: "", //'Ascending 升序 Descending 降序'
|
||||
orderBy:'',
|
||||
orderBy: "",
|
||||
userName: "",
|
||||
});
|
||||
organizationId: null
|
||||
})
|
||||
let state: any = ref([
|
||||
{
|
||||
label: "all",
|
||||
value: "",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
label:'visitor',
|
||||
value:'0',
|
||||
label: "visitor",
|
||||
value: "0"
|
||||
},
|
||||
{
|
||||
label:'yearly',
|
||||
value:'1',
|
||||
label: "yearly",
|
||||
value: "1"
|
||||
},
|
||||
{
|
||||
label:'monthly',
|
||||
value:'2',
|
||||
label: "monthly",
|
||||
value: "2"
|
||||
},
|
||||
{
|
||||
label:'trial',
|
||||
value:'3',
|
||||
label: "trial",
|
||||
value: "3"
|
||||
},
|
||||
{
|
||||
label: "userInEvent",
|
||||
value: "4",
|
||||
value: "4"
|
||||
},
|
||||
{
|
||||
label: "Edu Admin",
|
||||
value: "7",
|
||||
},
|
||||
]);
|
||||
let renameData: any = ref({}); //修改名字选中的数据
|
||||
value: "7"
|
||||
}
|
||||
])
|
||||
let renameData: any = ref({}) //修改名字选中的数据
|
||||
const columns: any = computed(() => {
|
||||
return [
|
||||
{
|
||||
@@ -213,25 +211,25 @@ export default defineComponent({
|
||||
align: "center",
|
||||
dataIndex: "id",
|
||||
key: "id",
|
||||
width:100,
|
||||
width: 100,
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: "Email",
|
||||
align: "center",
|
||||
dataIndex: "userEmail",
|
||||
key: "userEmail",
|
||||
width:200,
|
||||
ellipsis:true
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: "User Name",
|
||||
align: "center",
|
||||
dataIndex: "userName",
|
||||
key: "userName",
|
||||
width:150,
|
||||
ellipsis:true
|
||||
width: 150,
|
||||
ellipsis: true
|
||||
// customRender: (record: any) => {
|
||||
// let time = formatTime(
|
||||
// record.text / 1000,
|
||||
@@ -245,77 +243,77 @@ export default defineComponent({
|
||||
align: "center",
|
||||
dataIndex: "language",
|
||||
key: "language",
|
||||
width:100,
|
||||
ellipsis:true,
|
||||
width: 100,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: "Valid Start Time",
|
||||
align: "center",
|
||||
dataIndex: "validStartTime",
|
||||
key: "validstartTime",
|
||||
width:200,
|
||||
ellipsis:true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
customRender: (record: any) => {
|
||||
let time = ''
|
||||
if(record.text){
|
||||
time = formatTime(record.text / 1000, 'YYYY-MM-DD hh:mm:ss')
|
||||
let time = ""
|
||||
if (record.text) {
|
||||
time = formatTime(record.text / 1000, "YYYY-MM-DD hh:mm:ss")
|
||||
}
|
||||
return time
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Valid End Time",
|
||||
align: "center",
|
||||
dataIndex: "validEndTime",
|
||||
key: "validendTime",
|
||||
width:200,
|
||||
ellipsis:true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
customRender: (record: any) => {
|
||||
let time = ''
|
||||
if(record.text){
|
||||
time = formatTime(record.text / 1000, 'YYYY-MM-DD hh:mm:ss')
|
||||
let time = ""
|
||||
if (record.text) {
|
||||
time = formatTime(record.text / 1000, "YYYY-MM-DD hh:mm:ss")
|
||||
}
|
||||
return time
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Country or Region",
|
||||
align: "center",
|
||||
dataIndex: "country",
|
||||
key: "country",
|
||||
width:200,
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: "Create Date",
|
||||
align: "center",
|
||||
dataIndex: "createDate",
|
||||
key: "createDate",
|
||||
width:200,
|
||||
sorter: true,
|
||||
width: 200,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: "Is Beginner",
|
||||
align: "center",
|
||||
dataIndex: "isBeginner",
|
||||
key: "isBeginner",
|
||||
width:80,
|
||||
ellipsis:true,
|
||||
width: 80,
|
||||
ellipsis: true,
|
||||
customRender: (record: any) => {
|
||||
let str;
|
||||
let str
|
||||
if (record.value == 1) {
|
||||
str = "Yes";
|
||||
str = "Yes"
|
||||
} else {
|
||||
str = "No";
|
||||
str = "No"
|
||||
}
|
||||
return str
|
||||
}
|
||||
return str;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Machine Room Ip',
|
||||
title: "Machine Room Ip",
|
||||
align: "center",
|
||||
dataIndex: "browserIdentifiers",
|
||||
key: "browserIdentifiers",
|
||||
width:200,
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: "Credits",
|
||||
@@ -326,11 +324,11 @@ export default defineComponent({
|
||||
// resizable: true,
|
||||
dataIndex: "credits",
|
||||
key: "credits",
|
||||
width:100,
|
||||
sorter: true,
|
||||
width: 100,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: 'User Type',
|
||||
title: "User Type",
|
||||
align: "center",
|
||||
// width: 150,
|
||||
// minWidth: 100,
|
||||
@@ -338,84 +336,84 @@ export default defineComponent({
|
||||
// resizable: true,
|
||||
dataIndex: "systemUser",
|
||||
key: "systemUser",
|
||||
width:100,
|
||||
width: 100,
|
||||
customRender: (record: any) => {
|
||||
let str;
|
||||
let str
|
||||
if (record.value == 0) {
|
||||
str = "visitor";
|
||||
str = "visitor"
|
||||
} else if (record.value == 1) {
|
||||
str = "yearly";
|
||||
str = "yearly"
|
||||
} else if (record.value == 2) {
|
||||
str = "monthly";
|
||||
str = "monthly"
|
||||
} else if (record.value == 3) {
|
||||
str = "trial";
|
||||
str = "trial"
|
||||
} else if (record.value == 4) {
|
||||
str = "userInEvent";
|
||||
str = "userInEvent"
|
||||
} else if (record.value == 7) {
|
||||
str = "Edu Admin";
|
||||
str = "Edu Admin"
|
||||
}
|
||||
return str
|
||||
}
|
||||
return str;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Operations",
|
||||
key: "operation",
|
||||
width:120,
|
||||
width: 120,
|
||||
align: "center",
|
||||
fixed: "right",
|
||||
// slots:{customRender:'action'}
|
||||
Operations: true,
|
||||
},
|
||||
];
|
||||
});
|
||||
Operations: true
|
||||
}
|
||||
]
|
||||
})
|
||||
//改变页码
|
||||
let changePage = (e: any, filters:any, sorter:any) => {
|
||||
filterData.currentPage = e.current;
|
||||
filterData.pageSize = e.pageSize;
|
||||
if(sorter.order){
|
||||
if(sorter.columnKey == 'id'){
|
||||
filterData.orderBy = 'id'
|
||||
}else if(sorter.columnKey == "createDate"){
|
||||
filterData.orderBy = 'time'
|
||||
}else if(sorter.columnKey == "credits"){
|
||||
filterData.orderBy = 'credits'
|
||||
let changePage = (e: any, filters: any, sorter: any) => {
|
||||
filterData.currentPage = e.current
|
||||
filterData.pageSize = e.pageSize
|
||||
if (sorter.order) {
|
||||
if (sorter.columnKey == "id") {
|
||||
filterData.orderBy = "id"
|
||||
} else if (sorter.columnKey == "createDate") {
|
||||
filterData.orderBy = "time"
|
||||
} else if (sorter.columnKey == "credits") {
|
||||
filterData.orderBy = "credits"
|
||||
}
|
||||
}
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
if (sorter.order) {
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending"
|
||||
} else {
|
||||
filterData.order = ""
|
||||
}
|
||||
gettrialList()
|
||||
}
|
||||
gettrialList();
|
||||
};
|
||||
|
||||
//查询列表
|
||||
let searchHistoryList = () => {
|
||||
filterData.currentPage = 1;
|
||||
gettrialList();
|
||||
};
|
||||
filterData.currentPage = 1
|
||||
gettrialList()
|
||||
}
|
||||
let clearHistoryList = () => {
|
||||
filterData.rangePickerValue = [],
|
||||
filterData.currentPage = 1,
|
||||
filterData.pageSize = 10,
|
||||
filterData.total = 0,
|
||||
filterData.country = "",
|
||||
filterData.email = "",
|
||||
filterData.userType = "",
|
||||
filterData.ids = [],
|
||||
filterData.occupation = "",
|
||||
filterData.order = "", //'Ascending 升序 Descending 降序'
|
||||
filterData.orderBy = "", //'Ascending 升序 Descending 降序'
|
||||
filterData.systemUser = "",
|
||||
filterData.userName = "";
|
||||
};
|
||||
;((filterData.rangePickerValue = []),
|
||||
(filterData.currentPage = 1),
|
||||
(filterData.pageSize = 10),
|
||||
(filterData.total = 0),
|
||||
(filterData.country = ""),
|
||||
(filterData.email = ""),
|
||||
(filterData.userType = ""),
|
||||
(filterData.ids = []),
|
||||
(filterData.occupation = ""),
|
||||
(filterData.order = ""), //'Ascending 升序 Descending 降序'
|
||||
(filterData.orderBy = ""), //'Ascending 升序 Descending 降序'
|
||||
(filterData.systemUser = ""),
|
||||
(filterData.userName = ""))
|
||||
}
|
||||
let setHistoryListData = () => {
|
||||
let startDate: any = filterData.rangePickerValue?.[0]
|
||||
? filterData.rangePickerValue[0] + " " + "00:00:00"
|
||||
: "";
|
||||
: ""
|
||||
let endDate: any = filterData.rangePickerValue?.[1]
|
||||
? filterData.rangePickerValue[1] + " " + "23:59:59"
|
||||
: "";
|
||||
: ""
|
||||
let data = {
|
||||
endTime: endDate,
|
||||
startTime: startDate,
|
||||
@@ -430,63 +428,118 @@ export default defineComponent({
|
||||
order: filterData.order,
|
||||
orderBy: filterData.orderBy,
|
||||
userName: filterData.userName,
|
||||
};
|
||||
return data;
|
||||
};
|
||||
organizationId: filterData.organizationId
|
||||
}
|
||||
return data
|
||||
}
|
||||
//获取列表
|
||||
let gettrialList = () => {
|
||||
filter.tableLoading = true;
|
||||
let data = setHistoryListData();
|
||||
Https.axiosPost(Https.httpUrls.getUserInfo, data).then(
|
||||
(rv: any) => {
|
||||
filter.tableLoading = true
|
||||
let data = setHistoryListData()
|
||||
Https.axiosPost(Https.httpUrls.getUserInfo, data).then((rv: any) => {
|
||||
if (rv) {
|
||||
// this.dataList = rv
|
||||
filter.dataList = rv.records;
|
||||
filterData.total = rv.total;
|
||||
filter.tableLoading = false;
|
||||
filter.dataList = rv.records
|
||||
filterData.total = rv.total
|
||||
filter.tableLoading = false
|
||||
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
};
|
||||
let lastGeTrialList = (str: string) => {
|
||||
clearHistoryList();
|
||||
let currentDate = new Date();
|
||||
let currentTimestamp = Math.floor(currentDate.getTime() / 1000);
|
||||
clearHistoryList()
|
||||
let currentDate = new Date()
|
||||
let currentTimestamp = Math.floor(currentDate.getTime() / 1000)
|
||||
// 计算30天前的时间戳
|
||||
let thirtyDaysAgoTimestamp;
|
||||
let thirtyDaysAgoTimestamp
|
||||
if (str == "year") {
|
||||
thirtyDaysAgoTimestamp = currentTimestamp - 360 * 24 * 60 * 60;
|
||||
thirtyDaysAgoTimestamp = currentTimestamp - 360 * 24 * 60 * 60
|
||||
} else if (str == "month") {
|
||||
thirtyDaysAgoTimestamp = currentTimestamp - 30 * 24 * 60 * 60;
|
||||
thirtyDaysAgoTimestamp = currentTimestamp - 30 * 24 * 60 * 60
|
||||
} else if (str == "week") {
|
||||
thirtyDaysAgoTimestamp = currentTimestamp - 7 * 24 * 60 * 60;
|
||||
thirtyDaysAgoTimestamp = currentTimestamp - 7 * 24 * 60 * 60
|
||||
}
|
||||
filterData.rangePickerValue[0] = formatTime(thirtyDaysAgoTimestamp, "YYYY-MM-DD")
|
||||
gettrialList()
|
||||
}
|
||||
filterData.rangePickerValue[0] = formatTime(
|
||||
thirtyDaysAgoTimestamp,
|
||||
"YYYY-MM-DD"
|
||||
);
|
||||
gettrialList();
|
||||
};
|
||||
let filterOption = (input: any, option: any) => {
|
||||
// 使用 option.label 进行搜索
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}
|
||||
let addhHistoryList = () => {
|
||||
allUserPoerationsVue.value.init('Add','')
|
||||
};
|
||||
allUserPoerationsVue.value.init("Add", "")
|
||||
}
|
||||
let allUserPoerationsVue = ref()
|
||||
let setAagree = (data:any) =>{
|
||||
allUserPoerationsVue.value.init('Edit',data)
|
||||
let setAagree = (data: any) => {
|
||||
allUserPoerationsVue.value.init("Edit", data)
|
||||
}
|
||||
|
||||
const organizationOptions = ref([])
|
||||
const organizationParams = reactive({
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0
|
||||
})
|
||||
const organizationLoading = ref(false)
|
||||
const getOrganizationList = async (isLoadMore = false) => {
|
||||
console.log("111111")
|
||||
if (organizationLoading.value) return
|
||||
if (isLoadMore) {
|
||||
const loaded = organizationParams.page * organizationParams.size
|
||||
if (organizationParams.total && loaded >= organizationParams.total) return
|
||||
organizationParams.page += 1
|
||||
} else {
|
||||
organizationParams.page = 1
|
||||
organizationOptions.value = []
|
||||
}
|
||||
organizationLoading.value = true
|
||||
try {
|
||||
const { total, ...requestParams } = organizationParams
|
||||
const rv: any = await Https.axiosPost(
|
||||
Https.httpUrls.queryOrganization,
|
||||
requestParams
|
||||
)
|
||||
if (rv) {
|
||||
const newRecords = rv.records || []
|
||||
// 遍历新数据,如果已存在则覆盖,不存在则追加
|
||||
newRecords.forEach((newOrg: any) => {
|
||||
const newOrgId = String(newOrg.id)
|
||||
const existingIndex = organizationOptions.value.findIndex(
|
||||
(org: any) => String(org.id) === newOrgId
|
||||
)
|
||||
if (existingIndex !== -1) {
|
||||
// 如果已存在,用新数据覆盖旧项
|
||||
organizationOptions.value[existingIndex] = newOrg
|
||||
} else {
|
||||
// 如果不存在,追加到末尾
|
||||
organizationOptions.value.push(newOrg)
|
||||
}
|
||||
})
|
||||
organizationParams.total = rv.total || 0
|
||||
}
|
||||
} finally {
|
||||
organizationLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleOrganizationScroll = (e: any) => {
|
||||
const target = e?.target
|
||||
if (!target) return
|
||||
const nearBottom = target.scrollTop + target.clientHeight >= target.scrollHeight - 20
|
||||
if (nearBottom) {
|
||||
getOrganizationList(true)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
let allCountry: any = sessionStorage.getItem("allCountry");
|
||||
let allCountry: any = sessionStorage.getItem("allCountry")
|
||||
if (allCountry) {
|
||||
filter.allCountry = JSON.parse(allCountry);
|
||||
filter.allCountry = JSON.parse(allCountry)
|
||||
}
|
||||
gettrialList();
|
||||
});
|
||||
gettrialList()
|
||||
getOrganizationList()
|
||||
})
|
||||
return {
|
||||
...toRefs(filter),
|
||||
...toRefs(filterData),
|
||||
@@ -501,29 +554,32 @@ export default defineComponent({
|
||||
filterOption,
|
||||
allUserPoerationsVue,
|
||||
setAagree,
|
||||
};
|
||||
handleOrganizationScroll,
|
||||
getOrganizationList,
|
||||
organizationOptions,
|
||||
organizationParams
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
historyTableHeight: 0,
|
||||
handleResizeColumn: (w: any, col: any) => {
|
||||
col.width = w;
|
||||
},
|
||||
};
|
||||
col.width = w
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let historyTable: any = this.$refs.historyTable;
|
||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
||||
let historyTable: any = this.$refs.historyTable
|
||||
this.historyTableHeight = historyTable.clientHeight - 200
|
||||
},
|
||||
methods: {},
|
||||
});
|
||||
methods: {}
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.admin_page .admin_table_search .admin_state {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.admin_page{
|
||||
|
||||
.admin_page {
|
||||
}
|
||||
</style>
|
||||
@@ -321,6 +321,7 @@ export default defineComponent({
|
||||
data = setEditData()
|
||||
if (!data.userName || !data.userEmail || !data.validEndTime || !data.systemUser)
|
||||
return message.warning('Please check the input box marked with *')
|
||||
delete data.userName
|
||||
Https.axiosPost(Https.httpUrls.modifyUser, {}, { params: data }).then(rv => {
|
||||
if (rv) {
|
||||
cancelDsign()
|
||||
|
||||
99
src/component/Administrator/globalAwardPopularity.vue
Normal file
99
src/component/Administrator/globalAwardPopularity.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="admin_page globalAwardPopularity" ref="adminPage">
|
||||
<div class="admin_table_search">
|
||||
<div class="admin_state">
|
||||
<div class="admin_state_item">
|
||||
<span>Current Time:</span>
|
||||
<span>{{ currentTimeStr }}</span>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Raw Visi Count:</span>
|
||||
<span>{{ rawVisitCount }}</span>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Unique Visit Count:</span>
|
||||
<span>{{ uniqueVisitCount }}</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
<div class="admin_search_item" @click="getGlobalAwardPopularity">
|
||||
<i class="fi fi-br-refresh"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="admin_table_content" ref="questionnaireTable">
|
||||
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, createVNode,toRefs, computed,reactive, onMounted, nextTick } from "vue";
|
||||
import { Https } from "@/tool/https";
|
||||
import type { TableColumnsType } from 'ant-design-vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {},
|
||||
setup() {
|
||||
const currentTime = ref(new Date())
|
||||
const currentTimeStr = computed(()=>{
|
||||
return currentTime.value.toLocaleString()
|
||||
})
|
||||
const rawVisitCount = ref(0)
|
||||
const uniqueVisitCount = ref(0)
|
||||
const getGlobalAwardPopularity = () => {
|
||||
Https.axiosGet(Https.httpUrls.getGlobalAwardPopularity,).then((rv)=>{
|
||||
currentTime.value = new Date()
|
||||
rawVisitCount.value = rv.rawVisitCount
|
||||
uniqueVisitCount.value = rv.uniqueVisitCount
|
||||
})
|
||||
}
|
||||
onMounted(()=>{
|
||||
getGlobalAwardPopularity()
|
||||
})
|
||||
return {
|
||||
currentTimeStr,
|
||||
getGlobalAwardPopularity,
|
||||
rawVisitCount,
|
||||
uniqueVisitCount,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
methods: {},
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.admin_page.globalAwardPopularity{
|
||||
.admin_table_search{
|
||||
// flex: 1;
|
||||
width: min-content;
|
||||
justify-content: flex-start;
|
||||
border-radius: 2rem;
|
||||
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.2);
|
||||
margin-left: 2rem;
|
||||
flex-wrap: nowrap;
|
||||
gap: 3rem;
|
||||
}
|
||||
.admin_state{
|
||||
flex-direction: column;
|
||||
width: auto;
|
||||
cursor: auto;
|
||||
.admin_state_item{
|
||||
> span{
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.admin_search{
|
||||
i{
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,7 @@ commandManager.setChangeCallback((info) => {
|
||||
emit("undo-redo-status-changed", {
|
||||
canUndo: canUndo.value,
|
||||
canRedo: canRedo.value,
|
||||
type: info.type,
|
||||
commandManager,
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -409,7 +409,7 @@ export class BrushIndicator {
|
||||
// this.show(e.e);
|
||||
this._mouseEnterHandler && this._mouseEnterHandler(e)
|
||||
} else {
|
||||
// requestIdleCallback(() => {
|
||||
// setTimeout(() => {
|
||||
// this.updatePosition(e.e);
|
||||
// });
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
isGroupLayer,
|
||||
OperationType,
|
||||
OperationTypes,
|
||||
findLayer,
|
||||
createLayer,
|
||||
LayerType,
|
||||
SpecialLayerId,
|
||||
@@ -20,7 +19,6 @@ import { AnimationManager } from "./animation/AnimationManager";
|
||||
import { createCanvas } from "../utils/canvasFactory";
|
||||
import { CanvasEventManager } from "./events/CanvasEventManager";
|
||||
import CanvasConfig from "../config/canvasConfig";
|
||||
import { RedGreenModeManager } from "./RedGreenModeManager";
|
||||
import { EraserStateManager } from "./EraserStateManager";
|
||||
import {
|
||||
deepClone,
|
||||
@@ -49,7 +47,7 @@ import { getObjectAlphaToCanvas } from "../utils/objectHelper";
|
||||
import { AddLayerCommand, RemoveLayerCommand, ToggleChildLayerVisibilityCommand } from "../commands/LayerCommands";
|
||||
import { fa, id } from "element-plus/es/locales.mjs";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const {t} = i18n.global;
|
||||
const { t } = i18n.global;
|
||||
|
||||
export class CanvasManager {
|
||||
constructor(canvasElement, options) {
|
||||
@@ -72,7 +70,7 @@ export class CanvasManager {
|
||||
this.handleCanvasInit = null; // 画布初始化回调函数
|
||||
this.partManager = options.partManager || null;
|
||||
this.props = options.props || {};
|
||||
this.emit = options.emit || (() => {});
|
||||
this.emit = options.emit || (() => { });
|
||||
this.awaitCanvasRun = null;
|
||||
this.canvasChangeing = false;
|
||||
// 初始化画布
|
||||
@@ -178,9 +176,9 @@ export class CanvasManager {
|
||||
// 添加笔刷图像转换处理回调
|
||||
this.canvas.onBrushImageConverted = async (fabricImage) => {
|
||||
const activeTool = this.toolManager?.activeTool?.value;
|
||||
if(activeTool === OperationType.PART_BRUSH){
|
||||
if (activeTool === OperationType.PART_BRUSH) {
|
||||
this.partManager?.addDrawPartImage(fabricImage);
|
||||
}else{
|
||||
} else {
|
||||
await this.addImageToLayer({ fabricImage, targetLayerId: null });
|
||||
}
|
||||
// 返回false表示使用默认行为(直接添加到画布)
|
||||
@@ -205,7 +203,7 @@ export class CanvasManager {
|
||||
// 可以在这里保存状态到命令管理器
|
||||
const affectedObjects = e.targets || [];
|
||||
const activeTool = this.toolManager?.activeTool?.value;
|
||||
if(activeTool === OperationType.PART_ERASER){
|
||||
if (activeTool === OperationType.PART_ERASER) {
|
||||
return this.partManager?.onErasingEnd(affectedObjects);
|
||||
}
|
||||
const command = this.eraserStateManager.endErasing(affectedObjects);
|
||||
@@ -463,7 +461,7 @@ export class CanvasManager {
|
||||
// this.canvas.renderAll();
|
||||
}
|
||||
// 重置画布大小参照固定图层
|
||||
async resetCanvasSizeByFixedLayer(){
|
||||
async resetCanvasSizeByFixedLayer() {
|
||||
// 重置画布大小为固定图层的大小
|
||||
const fixedLayerObj = this.getFixedLayerObject();
|
||||
const backgroundObject = this.getBackgroundLayerObject();
|
||||
@@ -477,10 +475,10 @@ export class CanvasManager {
|
||||
fixedLayerObj.height,
|
||||
fixedLayerObj.scaleY,
|
||||
backgroundObject.width,
|
||||
backgroundObject.scaleX,
|
||||
backgroundObject.height,
|
||||
backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
if(Math.abs(fwidth/bwidth - fheight/bheight) < 0.1) return;
|
||||
backgroundObject.scaleX,
|
||||
backgroundObject.height,
|
||||
backgroundObject.scaleY, 'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
if (Math.abs(fwidth / bwidth - fheight / bheight) < 0.1) return;
|
||||
this.canvasWidth.value = fwidth
|
||||
this.canvasHeight.value = fheight
|
||||
backgroundObject.set({
|
||||
@@ -491,7 +489,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
width: this.canvasWidth.value,
|
||||
height: this.canvasHeight.value,
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 重置视图变换,使元素回到原始位置
|
||||
* @private
|
||||
@@ -625,17 +623,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
this.updateMaskPosition(backgroundObject);
|
||||
}
|
||||
|
||||
// 更新颜色层信息
|
||||
// const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||
// if(colorObject){
|
||||
// await this.setObjecCliptInfo(colorObject);
|
||||
// }
|
||||
const groupLayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
|
||||
if(groupLayer){
|
||||
const groupRect = new fabric.Rect({});
|
||||
await this.setObjecCliptInfo(groupRect);
|
||||
groupLayer.clippingMask = groupRect.toObject();
|
||||
}
|
||||
this.setSpecialCliptInfo(false, true)
|
||||
|
||||
// 重新渲染画布
|
||||
this.canvas.renderAll();
|
||||
@@ -870,7 +858,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
|
||||
return layerObjectByLayerId;
|
||||
}
|
||||
getObjectsByIdOrLayerId(ids){
|
||||
getObjectsByIdOrLayerId(ids) {
|
||||
const objects = this.canvas.getObjects().filter((obj) => {
|
||||
return ids.includes(obj.id) || ids.includes(obj.layerId);
|
||||
});
|
||||
@@ -1037,16 +1025,16 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
|
||||
// 处理特殊图层的显示状态
|
||||
const ptlids = [];
|
||||
if(!enhancedOptions.isPrintTrimsNoRepeat || !enhancedOptions.isPrintTrimsRepeat){
|
||||
if (!enhancedOptions.isPrintTrimsNoRepeat || !enhancedOptions.isPrintTrimsRepeat) {
|
||||
let layers = this.layers?.value?.find((layer) => layer.isPrintTrimsGroup)?.children || [];
|
||||
for(let layer of layers){
|
||||
if(!layer.visible) continue;
|
||||
for (let layer of layers) {
|
||||
if (!layer.visible) continue;
|
||||
let repeat = layer.fabricObjects?.[0]?.fill?.repeat || "no-repeat";
|
||||
if(typeof repeat !== "string") repeat = "no-repeat";
|
||||
if(repeat === "no-repeat"){
|
||||
if(enhancedOptions.isPrintTrimsNoRepeat) continue;
|
||||
}else{
|
||||
if(enhancedOptions.isPrintTrimsRepeat) continue;
|
||||
if (typeof repeat !== "string") repeat = "no-repeat";
|
||||
if (repeat === "no-repeat") {
|
||||
if (enhancedOptions.isPrintTrimsNoRepeat) continue;
|
||||
} else {
|
||||
if (enhancedOptions.isPrintTrimsRepeat) continue;
|
||||
}
|
||||
ptlids.push(layer.id);
|
||||
const command = new ToggleChildLayerVisibilityCommand({
|
||||
@@ -1061,8 +1049,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
}
|
||||
const res = await this.exportManager.exportImage(enhancedOptions);
|
||||
// 恢复特殊图层的显示状态
|
||||
if(ptlids.length > 0){
|
||||
for(let id of ptlids){
|
||||
if (ptlids.length > 0) {
|
||||
for (let id of ptlids) {
|
||||
const command = new ToggleChildLayerVisibilityCommand({
|
||||
canvas: this.canvas,
|
||||
layers: this.layers,
|
||||
@@ -1088,7 +1076,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
// 导出颜色图层信息
|
||||
const color = await this.exportColorLayer().catch(() => (null));
|
||||
// 导出印花和元素图层信息
|
||||
const printTrimsData = await this.exportPrintTrimsLayers().catch(() => ({prints: null, trims: null}));
|
||||
const printTrimsData = await this.exportPrintTrimsLayers().catch(() => ({ prints: null, trims: null }));
|
||||
|
||||
const obj = {
|
||||
color,
|
||||
@@ -1108,7 +1096,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
return Promise.reject("颜色图层不存在");
|
||||
}
|
||||
const object = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||
if(!object){
|
||||
if (!object) {
|
||||
console.warn("颜色图层不存在,请确保已添加颜色图层");
|
||||
return Promise.reject("颜色图层不存在");
|
||||
}
|
||||
@@ -1139,7 +1127,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
});
|
||||
canvas.clear();
|
||||
const color = object.originColor;
|
||||
return {css, base64, color};
|
||||
return { css, base64, color };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1147,11 +1135,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
*/
|
||||
async exportPrintTrimsLayers() {
|
||||
const glayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
|
||||
if(!glayer) return Promise.reject("印花和元素图层组不存在");
|
||||
if (!glayer) return Promise.reject("印花和元素图层组不存在");
|
||||
const ids = glayer.children.map((v) => v.id);
|
||||
const objects = this.getObjectsByIdOrLayerId(ids);
|
||||
const fixedLayerObj = this.getFixedLayerObject();
|
||||
if(!fixedLayerObj) return Promise.reject("固定图层不存在");
|
||||
if (!fixedLayerObj) return Promise.reject("固定图层不存在");
|
||||
const flWidth = fixedLayerObj.width
|
||||
const flHeight = fixedLayerObj.height
|
||||
const flTop = fixedLayerObj.top
|
||||
@@ -1163,7 +1151,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
objects.forEach((v, i) => {
|
||||
const label = glayer.children.find((v_) => (v_.id === v.layerId || v_.id === v.id));
|
||||
const sourceData = label?.metadata?.sourceData;
|
||||
if(!sourceData) return;
|
||||
if (!sourceData) return;
|
||||
const obj = {
|
||||
ifSingle: typeof v.fill === "string",
|
||||
level2Type: sourceData.level2Type,
|
||||
@@ -1175,7 +1163,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
angle: v.angle,
|
||||
name: sourceData.name,
|
||||
priority: i + 1,
|
||||
object:{
|
||||
object: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
scaleX: 0,//对象的缩放比例
|
||||
@@ -1194,8 +1182,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
let top = (v.top - (flTop - flHeight * flScaleY / 2));
|
||||
let width = (v.width * v.scaleX);
|
||||
let height = (v.height * v.scaleY);
|
||||
if(v.originX === "center" && v.originY === "center") {
|
||||
let {x:cx, y:cy} = calculateTopLeftPoint(width, height, left, top, v.angle);
|
||||
if (v.originX === "center" && v.originY === "center") {
|
||||
let { x: cx, y: cy } = calculateTopLeftPoint(width, height, left, top, v.angle);
|
||||
left = cx;
|
||||
top = cy;
|
||||
}
|
||||
@@ -1207,18 +1195,18 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
obj.object.left = oX;
|
||||
obj.object.scaleX = oScaleX;
|
||||
obj.object.scaleY = oScaleY;
|
||||
if(obj.ifSingle){
|
||||
if (obj.ifSingle) {
|
||||
// 单个的是从中心计算的
|
||||
let {x:cx, y:cy} = calculateCenterPoint(width, height, left, top, v.angle);
|
||||
let oX = (cx-width/2) / flScaleX;
|
||||
let oY = (cy-height/2) / flScaleY;
|
||||
let { x: cx, y: cy } = calculateCenterPoint(width, height, left, top, v.angle);
|
||||
let oX = (cx - width / 2) / flScaleX;
|
||||
let oY = (cy - height / 2) / flScaleY;
|
||||
obj.location = [oX, oY];
|
||||
obj.scale = [oScaleX, oScaleY];
|
||||
}else{
|
||||
} else {
|
||||
let fill = v.fill;
|
||||
let fill_ = v.fill_;
|
||||
if(!fill || !fill_) return console.warn("印花元素不存在fill或fill_属性");
|
||||
let {scale, angle} = getTransformScaleAngle(fill.patternTransform);
|
||||
if (!fill || !fill_) return console.warn("印花元素不存在fill或fill_属性");
|
||||
let { scale, angle } = getTransformScaleAngle(fill.patternTransform);
|
||||
let scaleX = scale * 5 * v.fill_.width / flWidth;
|
||||
let scaleY = scale * 5 * v.fill_.height / flHeight;
|
||||
let scaleXY = flWidth > flHeight ? scaleX : scaleY;
|
||||
@@ -1233,16 +1221,16 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
obj.object.gapY = fill_.gapY;
|
||||
obj.object.fill_repeat = fill.repeat;
|
||||
}
|
||||
if(sourceData.type === "print"){
|
||||
if (sourceData.type === "print") {
|
||||
prints.push(obj);
|
||||
}else if(sourceData.type === "trims"){
|
||||
} else if (sourceData.type === "trims") {
|
||||
trims.push(obj);
|
||||
}
|
||||
})
|
||||
// prints.sort((a, b) => a.ifSingle ? 1 : -1);
|
||||
// prints.forEach((v, i) => v.priority = i + 1);
|
||||
// trims.forEach((v, i) => v.priority = i + 1);
|
||||
return {prints, trims};
|
||||
return { prints, trims };
|
||||
}
|
||||
|
||||
|
||||
@@ -1285,7 +1273,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
// 排除颜色图层和特殊组图层
|
||||
const excludedLayers = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP];
|
||||
this.layers.value.forEach((layer) => {
|
||||
if(excludedLayers.includes(layer.id)){
|
||||
if (excludedLayers.includes(layer.id)) {
|
||||
excludedLayers.push(...layer.children?.map((child) => child.id));
|
||||
}
|
||||
})
|
||||
@@ -1337,7 +1325,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
}
|
||||
}
|
||||
loadJSON(json, calllBack) {
|
||||
|
||||
this.canvas.loading.value = true;
|
||||
// 确保传入的json是字符串格式
|
||||
if (typeof json === "object") {
|
||||
json = JSON.stringify(json);
|
||||
@@ -1467,16 +1455,16 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
}
|
||||
}
|
||||
/** 修复JSON数据中的ID丢失问题 */
|
||||
FixJsonIdLoss(json){
|
||||
FixJsonIdLoss(json) {
|
||||
const layerIds = [];
|
||||
const layers = json?.layers || [];
|
||||
const objects = json?.canvas?.objects || [];
|
||||
layers.forEach((layer) => {
|
||||
layerIds.push(layer.id);
|
||||
layer.children?.forEach((child) => layerIds.push(child.id));
|
||||
if(!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id){
|
||||
if (!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id) {
|
||||
const obj = objects?.find((o) => o.layerId === layer.id);
|
||||
if(obj) {
|
||||
if (obj) {
|
||||
layer.fabricObjects = [{
|
||||
id: obj.id,
|
||||
type: obj.type,
|
||||
@@ -1493,11 +1481,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
const excludedObjects = [SpecialLayerId.PART_SELECTOR];
|
||||
json.canvas.objects = objects.filter((v) => {
|
||||
// 指定ID排除
|
||||
if(excludedObjects.includes(v.id)) return false;
|
||||
if (excludedObjects.includes(v.id)) return false;
|
||||
|
||||
if(v.isBackground || v.isFixed) return true;
|
||||
if (v.isBackground || v.isFixed) return true;
|
||||
// 当前图层不存在当前对象
|
||||
if(!layerIds.includes(v.layerId)) return false;
|
||||
if (!layerIds.includes(v.layerId)) return false;
|
||||
return true
|
||||
});
|
||||
}
|
||||
@@ -1509,23 +1497,22 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
*/
|
||||
async createOtherLayers(otherData) {
|
||||
if (!otherData) return console.warn("otherData 为空不需要添加");
|
||||
this.canvas.loading.value = true;
|
||||
let resolve = ()=>{};
|
||||
this.awaitCanvasRun = ()=>(new Promise((v) => resolve = v))
|
||||
let resolve = () => { };
|
||||
this.awaitCanvasRun = () => (new Promise((v) => resolve = v))
|
||||
const otherData_ = JSON.parse(JSON.stringify(otherData));
|
||||
console.log("==========创建其他图层", otherData_);
|
||||
|
||||
// 删除颜色图层和特殊组图层
|
||||
const ids = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP];
|
||||
this.layers.value = this.layers.value.filter((layer) => {
|
||||
if(ids.includes(layer.id)){
|
||||
if (ids.includes(layer.id)) {
|
||||
ids.push(...layer.children?.map((child) => child.id));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
this.canvas.getObjects().forEach((v) => {
|
||||
if(ids.includes(v.id) || ids.includes(v.layerId)){
|
||||
if (ids.includes(v.id) || ids.includes(v.layerId)) {
|
||||
this.canvas.remove(v)
|
||||
}
|
||||
})
|
||||
@@ -1539,31 +1526,50 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
otherData_.printObject?.prints?.forEach((print, index) => {// 印花
|
||||
print.name = t("Canvas.Print") + (index + 1);
|
||||
print.type = "print";
|
||||
if(print.ifSingle){
|
||||
printTrimsLayers.unshift({...print});
|
||||
}else{
|
||||
singleLayers.unshift({...print});
|
||||
if (print.ifSingle) {
|
||||
printTrimsLayers.unshift({ ...print });
|
||||
} else {
|
||||
singleLayers.unshift({ ...print });
|
||||
}
|
||||
})
|
||||
otherData_.trims?.prints?.forEach((trims, index) => {// 元素
|
||||
trims.name = t("Canvas.Elements") + (index + 1);
|
||||
trims.type = "trims";
|
||||
printTrimsLayers.unshift({...trims});
|
||||
printTrimsLayers.unshift({ ...trims });
|
||||
})
|
||||
if(printTrimsLayers.length || singleLayers.length){
|
||||
if (printTrimsLayers.length || singleLayers.length) {
|
||||
await this.createPrintTrimsLayers(printTrimsLayers, singleLayers);
|
||||
}
|
||||
await this.changeCanvas();
|
||||
console.log("==========创建其他图层成功");
|
||||
resolve();
|
||||
this.awaitCanvasRun = null;
|
||||
this.canvas.loading.value = false;
|
||||
}
|
||||
|
||||
//设置印花元素颜色的裁剪信息
|
||||
async setSpecialCliptInfo(isColor = true, isGroup = true) {
|
||||
// 更新颜色层信息
|
||||
if (isColor) {
|
||||
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||
if (colorObject) {
|
||||
await this.setObjecCliptInfo(colorObject);
|
||||
}
|
||||
|
||||
}
|
||||
// 更新特殊组图层信息
|
||||
if (isGroup) {
|
||||
const groupLayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
|
||||
if (groupLayer) {
|
||||
const groupRect = new fabric.Rect({});
|
||||
await this.setObjecCliptInfo(groupRect);
|
||||
groupLayer.clippingMask = groupRect.toObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置画布对象的裁剪信息
|
||||
async setObjecCliptInfo(tagObject, data){
|
||||
async setObjecCliptInfo(tagObject, data) {
|
||||
const fixedLayerObj = this.getFixedLayerObject();
|
||||
if(!fixedLayerObj) return console.warn("固定图层为空");
|
||||
if (!fixedLayerObj) return console.warn("固定图层为空");
|
||||
tagObject.set({
|
||||
top: fixedLayerObj.top,
|
||||
left: fixedLayerObj.left,
|
||||
@@ -1576,7 +1582,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
});
|
||||
var object = fixedLayerObj;
|
||||
const imageUrl = this.props.clothingImageUrl2;
|
||||
if(imageUrl){
|
||||
if (imageUrl) {
|
||||
object = await new Promise((resolve, reject) => {
|
||||
fabric.Image.fromURL(imageUrl, (imgObject) => {
|
||||
tagObject.set({
|
||||
@@ -1596,8 +1602,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
});
|
||||
tagObject.set('clipPath', transparentMask);
|
||||
}
|
||||
async createColorLayer(color_){
|
||||
const color = color_ || {r:0,g:0,b:0,a:0};
|
||||
async createColorLayer(color_) {
|
||||
const color = color_ || { r: 0, g: 0, b: 0, a: 0 };
|
||||
// if(findLayer(this.layers.value, SpecialLayerId.COLOR)) {
|
||||
// return console.warn("画布中已存在颜色图层");
|
||||
// }
|
||||
@@ -1641,7 +1647,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
}
|
||||
|
||||
// 创建印花和元素图层
|
||||
async createPrintTrimsLayers(printTrimsLayers, singleLayers){
|
||||
async createPrintTrimsLayers(printTrimsLayers, singleLayers) {
|
||||
// if(findLayer(this.layers.value, SpecialLayerId.SPECIAL_GROUP)) {
|
||||
// return console.warn("画布中已存在印花和元素组图层");
|
||||
// }
|
||||
@@ -1655,12 +1661,12 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
const flScaleY = fixedLayerObj.scaleY
|
||||
const children = [];
|
||||
// 添加印花和元素图层
|
||||
for(let index = 0; index < printTrimsLayers.length; index++){
|
||||
for (let index = 0; index < printTrimsLayers.length; index++) {
|
||||
let item = printTrimsLayers[index];
|
||||
let id = generateId("layer_image_");
|
||||
let name = item.name;
|
||||
let image = await new Promise(resolve => {
|
||||
fabric.Image.fromURL(item.path, (fabricImage)=>{
|
||||
fabric.Image.fromURL(item.path, (fabricImage) => {
|
||||
resolve(fabricImage);
|
||||
}, { crossOrigin: "anonymous" });
|
||||
})
|
||||
@@ -1668,7 +1674,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
let top = flTop - flHeight * flScaleY / 2 + (item.location?.[1] || 0) * flScaleY
|
||||
let scaleX = flWidth * (item.scale?.[0] || 1) / image.width * flScaleX
|
||||
let scaleY = flHeight * (item.scale?.[1] || 1) / image.height * flScaleY
|
||||
let {x, y} = calculateRotatedTopLeftDeg(
|
||||
let { x, y } = calculateRotatedTopLeftDeg(
|
||||
image.width * scaleX,
|
||||
image.height * scaleY,
|
||||
left,
|
||||
@@ -1683,11 +1689,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
let flipY = false;
|
||||
let blendMode = BlendMode.NORMAL;
|
||||
// if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常
|
||||
if(item.object){
|
||||
if (item.object) {
|
||||
opacity = item.object.opacity
|
||||
flipX = item.object.flipX
|
||||
flipY = item.object.flipY
|
||||
if(item.object.blendMode) blendMode = item.object.blendMode;
|
||||
if (item.object.blendMode) blendMode = item.object.blendMode;
|
||||
}
|
||||
image.set({
|
||||
left: x,
|
||||
@@ -1718,18 +1724,18 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
isPrintTrims: true,
|
||||
blendMode: blendMode,
|
||||
fabricObjects: [image.toObject(["id", "layerId", "layerName"])],
|
||||
metadata: {sourceData: item},
|
||||
metadata: { sourceData: item },
|
||||
object: image,
|
||||
})
|
||||
children.push(layer);
|
||||
};
|
||||
// 添加平铺图层
|
||||
for(let index = 0; index < singleLayers.length; index++){
|
||||
for (let index = 0; index < singleLayers.length; index++) {
|
||||
let item = singleLayers[index];
|
||||
let id = generateId("layer_image_");
|
||||
let name = item.name;
|
||||
let image = await new Promise(resolve => {
|
||||
fabric.Image.fromURL(item.path, (fabricImage)=>{
|
||||
fabric.Image.fromURL(item.path, (fabricImage) => {
|
||||
const imgElement = fabricImage.getElement();
|
||||
const tcanvas = document.createElement('canvas');
|
||||
tcanvas.width = imgElement.width;
|
||||
@@ -1758,7 +1764,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
let flipY = false;
|
||||
let blendMode = BlendMode.NORMAL;
|
||||
let fill_repeat = "repeat"
|
||||
if(item.object){
|
||||
if (item.object) {
|
||||
top += item.object.top * flScaleY
|
||||
left += item.object.left * flScaleX
|
||||
scaleX *= item.object.scaleX
|
||||
@@ -1767,11 +1773,11 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
angle = item.object.angle
|
||||
flipX = item.object.flipX
|
||||
flipY = item.object.flipY
|
||||
if(item.object.blendMode) blendMode = item.object.blendMode;
|
||||
if (item.object.blendMode) blendMode = item.object.blendMode;
|
||||
gapX = item.object.gapX
|
||||
gapY = item.object.gapY
|
||||
fillSource = imageAddGapToCanvas(image, gapX, gapY);
|
||||
if(item.object.fill_repeat) fill_repeat = item.object.fill_repeat;
|
||||
if (item.object.fill_repeat) fill_repeat = item.object.fill_repeat;
|
||||
}
|
||||
let rect = new fabric.Rect({
|
||||
id: id,
|
||||
@@ -1795,7 +1801,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
offsetX: offsetX, // 水平偏移
|
||||
offsetY: offsetY, // 垂直偏移
|
||||
}),
|
||||
fill_ : {
|
||||
fill_: {
|
||||
source: item.path,
|
||||
gapX: gapX,
|
||||
gapY: gapY,
|
||||
@@ -1815,7 +1821,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
isPrintTrims: true,
|
||||
blendMode: blendMode,
|
||||
fabricObjects: [rect.toObject(["id", "layerId", "layerName"])],
|
||||
metadata: {sourceData: item},
|
||||
metadata: { sourceData: item },
|
||||
object: rect,
|
||||
})
|
||||
children.push(layer);
|
||||
@@ -1832,9 +1838,9 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
// })
|
||||
// children.push(layer);
|
||||
// }
|
||||
if(children.length === 0) return;
|
||||
if (children.length === 0) return;
|
||||
// 印花元素排序
|
||||
if(new Set(children.map(v => v.metadata.sourceData.priority)).size === children.length){
|
||||
if (new Set(children.map(v => v.metadata.sourceData.priority)).size === children.length) {
|
||||
children.sort((a, b) => b.metadata.sourceData.priority - a.metadata.sourceData.priority);
|
||||
}
|
||||
children.forEach(layer => {
|
||||
@@ -1862,21 +1868,21 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
/**
|
||||
* 画布事件变更后
|
||||
*/
|
||||
async changeCanvas(fids = [], isBeforeChange = false){
|
||||
if(!isBeforeChange) this.canvasChangeing = false;
|
||||
async changeCanvas(fids = [], isBeforeChange = false) {
|
||||
if (!isBeforeChange) this.canvasChangeing = false;
|
||||
const fixedLayerObj = this.getFixedLayerObject();
|
||||
if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
|
||||
if (!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
|
||||
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
|
||||
if(colorObject){
|
||||
if (colorObject) {
|
||||
const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP).filter(id => !fids.includes(id));
|
||||
if(ids.length === 0){
|
||||
if (ids.length === 0) {
|
||||
ids.unshift(SpecialLayerId.SPECIAL_GROUP);
|
||||
await this.setObjecCliptInfo(colorObject);
|
||||
this.canvas.renderAll();
|
||||
return;
|
||||
}
|
||||
const base64 = await this.exportManager.exportImage({layerIdArray2: ids, isEnhanceImg: true});
|
||||
if(!base64) return console.warn("导出图片失败", base64)
|
||||
const base64 = await this.exportManager.exportImage({ layerIdArray2: ids, isEnhanceImg: true });
|
||||
if (!base64) return console.warn("导出图片失败", base64)
|
||||
const canvas = await base64ToCanvas(base64, fixedLayerObj.scaleX * 2, true);
|
||||
const ctx = canvas.getContext('2d');
|
||||
const width = fixedLayerObj.width;
|
||||
@@ -1889,15 +1895,15 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
}
|
||||
}
|
||||
/** 画布变更之前 */
|
||||
async beforeChangeCanvas(objects){
|
||||
if(this.canvasChangeing) return;
|
||||
async beforeChangeCanvas(objects) {
|
||||
if (this.canvasChangeing) return;
|
||||
const ids = objects.filter(v => {
|
||||
return v.isPrintTrims && v.globalCompositeOperation && v.globalCompositeOperation !== BlendMode.NORMAL
|
||||
}).map(v => v.layerId);
|
||||
if(ids.length > 0){
|
||||
if (ids.length > 0) {
|
||||
this.canvasChangeing = true;
|
||||
this.canvas.getObjects().forEach(v => {
|
||||
if(ids.includes(v.layerId)){
|
||||
if (ids.includes(v.layerId)) {
|
||||
v.globalCompositeOperation_ = v.globalCompositeOperation;
|
||||
v.globalCompositeOperation = BlendMode.NORMAL;
|
||||
}
|
||||
@@ -2107,13 +2113,13 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
moveActiveObject(direction, step = 1) {
|
||||
const objects = [];
|
||||
const activeObject = this.canvas.getActiveObject();
|
||||
if(!activeObject) return;
|
||||
if (!activeObject) return;
|
||||
const initPos = {
|
||||
id: activeObject.id,
|
||||
left: activeObject.left,
|
||||
top: activeObject.top,
|
||||
};
|
||||
switch(direction) {
|
||||
switch (direction) {
|
||||
case "up":
|
||||
activeObject.top -= step;
|
||||
break;
|
||||
@@ -2127,7 +2133,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
|
||||
activeObject.left += step;
|
||||
break;
|
||||
}
|
||||
if(!activeObject.id) return this.canvas.renderAll();
|
||||
if (!activeObject.id) return this.canvas.renderAll();
|
||||
const cmd = new ObjectMoveCommand({
|
||||
canvas: this.canvas,
|
||||
initPos,
|
||||
|
||||
@@ -606,7 +606,9 @@ export class ExportManager {
|
||||
imageSmoothingEnabled: true,
|
||||
});
|
||||
// tempFabricCanvas.setZoom(1);
|
||||
console.log("==========", fixedLayerObject)
|
||||
const ox = fixedLayerObject.left - fixedLayerObject.width * fixedLayerObject.scaleX / 2
|
||||
const oy = fixedLayerObject.top - fixedLayerObject.height * fixedLayerObject.scaleY / 2
|
||||
// console.log("==========", fixedLayerObject, ox, oy)
|
||||
try {
|
||||
// 克隆并添加所有对象到临时画布,需要调整位置相对于固定图层
|
||||
for (let i = 0; i < objectsToExport.length; i++) {
|
||||
@@ -616,15 +618,20 @@ export class ExportManager {
|
||||
restoreOpacityInRedGreen && true
|
||||
);
|
||||
if (cloned) {
|
||||
let scaleX = cloned.scaleX / fixedLayerObject.scaleX
|
||||
let scaleY = cloned.scaleY / fixedLayerObject.scaleY
|
||||
let top = (cloned.top - oy) * scaleY
|
||||
let left = (cloned.left - ox) * scaleX
|
||||
if (cloned.originX === "center" && cloned.originY === "center") {
|
||||
top = canvasHeight / 2
|
||||
left = canvasWidth / 2
|
||||
}
|
||||
cloned.set({
|
||||
left: canvasWidth / 2,
|
||||
top: canvasHeight / 2,
|
||||
scaleX: cloned.scaleX / fixedLayerObject.scaleX,
|
||||
scaleY: cloned.scaleY / fixedLayerObject.scaleY,
|
||||
originX: "center",
|
||||
originY: "center",
|
||||
left: left,
|
||||
top: top,
|
||||
scaleX: scaleX,
|
||||
scaleY: scaleY,
|
||||
});
|
||||
console.log("==========", {...cloned})
|
||||
// 更新对象坐标
|
||||
cloned.setCoords();
|
||||
tempFabricCanvas.add(cloned);
|
||||
|
||||
@@ -1580,7 +1580,7 @@ export class LayerManager {
|
||||
/**
|
||||
* 排序图层,确保图层顺序: 普通图层 > 固定图层 > 背景图层
|
||||
*/
|
||||
sortLayers() {
|
||||
async sortLayers() {
|
||||
// 对图层进行排序:背景图层在最底层(数组最后),固定图层在中间
|
||||
this.layers.value.sort((a, b) => {
|
||||
// 如果a是背景图层,它应该排在后面(最底层)
|
||||
@@ -1604,17 +1604,17 @@ export class LayerManager {
|
||||
});
|
||||
|
||||
// 更新画布对象顺序
|
||||
this._rearrangeObjects();
|
||||
await this._rearrangeObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新排列画布上的对象以匹配图层顺序
|
||||
* @private
|
||||
*/
|
||||
_rearrangeObjects() {
|
||||
async _rearrangeObjects() {
|
||||
if (this.layerSort) {
|
||||
// 使用LayerSort的高级排序
|
||||
this.layerSort.rearrangeObjects();
|
||||
await this.layerSort.rearrangeObjects();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,16 +90,17 @@ export class PartManager {
|
||||
|
||||
if (toolId === OperationType.PART_ERASER) {
|
||||
this.setEraserTool();
|
||||
} else if (toolId === OperationType.PART || toolId === OperationType.PART_RECTANGLE) {
|
||||
this.clearPointData();
|
||||
this.resetPartObject();
|
||||
}
|
||||
if (toolId === OperationType.PART_ERASER || toolId === OperationType.PART_BRUSH) {
|
||||
if (this.pointList.length > 0) {
|
||||
this.clearPointData();
|
||||
this.resetPartObject();
|
||||
}
|
||||
}
|
||||
// else if (toolId === OperationType.PART || toolId === OperationType.PART_RECTANGLE) {
|
||||
// this.clearPointData();
|
||||
// this.resetPartObject();
|
||||
// }
|
||||
// if (toolId === OperationType.PART_ERASER || toolId === OperationType.PART_BRUSH) {
|
||||
// if (this.pointList.length > 0) {
|
||||
// this.clearPointData();
|
||||
// this.resetPartObject();
|
||||
// }
|
||||
// }
|
||||
|
||||
// 如果从非选区工具切换到选区工具,初始化事件
|
||||
if (!wasActive && this.isActive) {
|
||||
@@ -380,7 +381,8 @@ export class PartManager {
|
||||
box: [...this.pointList],
|
||||
});
|
||||
const image = await this.loadImageToObject(url);
|
||||
const canvas = getObjectAlphaToCanvas(image, null, 0, this.rgba);
|
||||
const data = this.partCanvas?.getContext("2d")?.getImageData(0, 0, this.partCanvas.width, this.partCanvas.height);
|
||||
const canvas = getObjectAlphaToCanvas(image, data, 0, this.rgba, !!data);
|
||||
this.partDrawCommand(canvas);
|
||||
}
|
||||
/** 获取分隔后图片 */
|
||||
|
||||
@@ -133,11 +133,12 @@ export class RedGreenModeManager {
|
||||
this.canvas.on("mouse:up", (event) => {
|
||||
// 可以在这里添加更多逻辑,比如生成图片或更新状态
|
||||
nextTick(() => {
|
||||
requestIdleCallback(async () => {
|
||||
setTimeout(async () => {
|
||||
if (!this.isInitialized) {
|
||||
console.warn("红绿图模式未初始化,无法处理鼠标事件");
|
||||
return;
|
||||
}
|
||||
console.log("鼠标抬起事件触发", this.onImageGenerated);
|
||||
if (this.onImageGenerated) {
|
||||
const imageData = await this.canvasManager.exportImage({
|
||||
restoreOpacityInRedGreen: true, // 恢复红绿图模式下的透明度
|
||||
|
||||
@@ -37,7 +37,6 @@ export class ThumbnailManager {
|
||||
|
||||
// 延迟执行,避免阻塞UI
|
||||
fabricObjects.length > 0 &&
|
||||
requestIdleCallback(() => {
|
||||
setTimeout(async () => {
|
||||
const base64 = await this._generateLayerThumbnailNow(fabricObjects, layer);
|
||||
// this.layerThumbnails.set(layerId, base64);
|
||||
@@ -55,7 +54,6 @@ export class ThumbnailManager {
|
||||
console.error("生成图层缩略图时出错:", error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +63,7 @@ export class ThumbnailManager {
|
||||
generateAllLayerThumbnails(layers) {
|
||||
if (!layers || !Array.isArray(layers)) return;
|
||||
|
||||
requestIdleCallback(() => {
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
layers.forEach((layer) => {
|
||||
if (layer && layer.id) {
|
||||
|
||||
@@ -180,7 +180,7 @@ export class CommandManager {
|
||||
this._recordPerformance("execute", command.constructor.name, duration);
|
||||
|
||||
// 通知状态变化
|
||||
this._notifyStateChange();
|
||||
this._notifyStateChange("execute");
|
||||
|
||||
console.log(`✅ 命令执行成功: ${command.constructor.name}`);
|
||||
return result;
|
||||
@@ -219,7 +219,7 @@ export class CommandManager {
|
||||
this._recordPerformance("undo", command.constructor.name, duration);
|
||||
|
||||
// 通知状态变化
|
||||
this._notifyStateChange();
|
||||
this._notifyStateChange("undo");
|
||||
|
||||
console.log(`✅ 命令撤销成功: ${command.constructor.name}`);
|
||||
return result;
|
||||
@@ -258,7 +258,7 @@ export class CommandManager {
|
||||
this._recordPerformance("redo", command.constructor.name, duration);
|
||||
|
||||
// 通知状态变化
|
||||
this._notifyStateChange();
|
||||
this._notifyStateChange("redo");
|
||||
|
||||
console.log(`✅ 命令重做成功: ${command.constructor.name}`);
|
||||
return result;
|
||||
@@ -298,7 +298,7 @@ export class CommandManager {
|
||||
|
||||
this.undoStack = [];
|
||||
this.redoStack = [];
|
||||
this._notifyStateChange();
|
||||
this._notifyStateChange("clear");
|
||||
// console.log("📝 命令历史已清空");
|
||||
}
|
||||
|
||||
@@ -417,10 +417,12 @@ export class CommandManager {
|
||||
* 通知状态变化
|
||||
* @private
|
||||
*/
|
||||
_notifyStateChange() {
|
||||
_notifyStateChange(type) {
|
||||
if (this.onStateChange) {
|
||||
try {
|
||||
this.onStateChange(this.getState());
|
||||
const obj = this.getState();
|
||||
obj.type = type;
|
||||
this.onStateChange(obj);
|
||||
} catch (error) {
|
||||
console.error("状态变化回调执行失败:", error);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ export class LiquifyRealTimeUpdater {
|
||||
|
||||
if (isDrawing && this.config.useDirectUpdate) {
|
||||
// 拖拽过程中使用快速更新(降低质量以提高性能)
|
||||
this._fastUpdate(imageData);
|
||||
await this._fastUpdate(imageData);
|
||||
} else {
|
||||
// 拖拽结束后使用完整更新(最高质量)
|
||||
await this._fullUpdate(imageData);
|
||||
@@ -124,7 +124,7 @@ export class LiquifyRealTimeUpdater {
|
||||
* @param {ImageData} imageData 图像数据
|
||||
* @private
|
||||
*/
|
||||
_fastUpdate(imageData) {
|
||||
async _fastUpdate(imageData) {
|
||||
if (!this.targetObject || !this.targetObject._element) {
|
||||
return;
|
||||
}
|
||||
@@ -138,12 +138,14 @@ export class LiquifyRealTimeUpdater {
|
||||
|
||||
// 直接更新fabric对象的图像源(使用PNG格式保持质量)
|
||||
const targetElement = this.targetObject._element;
|
||||
|
||||
// 方案1: 直接设置src属性(最高性能)
|
||||
const dataURL = this.tempCanvas.toDataURL("image/png", quality);
|
||||
|
||||
if (targetElement.src !== dataURL) {
|
||||
targetElement.src = dataURL;
|
||||
// targetElement.src = dataURL;
|
||||
const image = new Image();
|
||||
image.src = dataURL;
|
||||
await image.decode();
|
||||
this.targetObject.setElement(image);
|
||||
|
||||
// 关键优化:直接设置fabric对象为脏状态,但不立即渲染
|
||||
// this.targetObject.dirty = false; // 标记为不需要立即渲染
|
||||
@@ -153,7 +155,7 @@ export class LiquifyRealTimeUpdater {
|
||||
// 使用requestAnimationFrame进行批量渲染优化
|
||||
// if (!this.renderingScheduled && !this.config.skipRenderDuringDrag) {
|
||||
// this.renderingScheduled = true;
|
||||
// requestIdleCallback(() => {
|
||||
// setTimeout(() => {
|
||||
// this.canvas.renderAll();
|
||||
// this.renderingScheduled = false;
|
||||
// });
|
||||
|
||||
@@ -30,7 +30,8 @@ export class LayerSort {
|
||||
if (canvasObjects.length === 0) return;
|
||||
|
||||
// 使用画布渲染优化
|
||||
await optimizeCanvasRendering(this.canvas, () => {
|
||||
await new Promise((resolve) => {
|
||||
optimizeCanvasRendering(this.canvas, () => {
|
||||
// 计算每个对象应该在的 z-index 位置
|
||||
const objectZIndexMap = this.calculateObjectZIndexes();
|
||||
|
||||
@@ -51,6 +52,8 @@ export class LayerSort {
|
||||
this.canvas.moveTo(item.object, index);
|
||||
}
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -65,9 +65,10 @@ export async function restoreFabricObject(serializedObject, canvas) {
|
||||
* @param {ImageData} revData - 相反的ImageData,白通道的相同位置是否为透明,revData为白色为透明,黑色为不透明
|
||||
* @param {number} diff - 差值,默认 25
|
||||
* @param {Object} rgba - 自定义 rgba 值,默认 { r: 255, g: 255, b: 255, a: 255 }
|
||||
* @param {boolean} isMerge - 是否合并,true=合并revData,false=反转revData
|
||||
* @returns {HTMLCanvasElement|null} 包含黑白通道的画布,或 null 如果失败
|
||||
*/
|
||||
export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 255, g: 255, b: 255, a: 255 }) {
|
||||
export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 255, g: 255, b: 255, a: 255 }, isMerge = false) {
|
||||
const image = object.getElement();
|
||||
if (image.nodeName !== "IMG" && image.nodeName !== "CANVAS") {
|
||||
console.warn("对象不是图片");
|
||||
@@ -93,18 +94,20 @@ export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 2
|
||||
const revG = revData?.data[i + 1] || 0;
|
||||
const revB = revData?.data[i + 2] || 0;
|
||||
const revA = revData?.data[i + 3] || 0;
|
||||
let isHave = false;
|
||||
if (r || g || b || a) {
|
||||
if (revR > diff || revG > diff || revB > diff || revA > diff) {
|
||||
data.data[i + 0] = 0;
|
||||
data.data[i + 1] = 0;
|
||||
data.data[i + 2] = 0;
|
||||
data.data[i + 3] = 0;
|
||||
isHave = false;
|
||||
} else {
|
||||
isHave = true;
|
||||
}
|
||||
}
|
||||
if (isMerge && (revR || revG || revB || revA)) isHave = true;
|
||||
if (isHave) {
|
||||
data.data[i + 0] = rgba.r;
|
||||
data.data[i + 1] = rgba.g;
|
||||
data.data[i + 2] = rgba.b;
|
||||
data.data[i + 3] = rgba.a;
|
||||
}
|
||||
} else {
|
||||
data.data[i + 0] = 0;
|
||||
data.data[i + 1] = 0;
|
||||
|
||||
@@ -184,16 +184,17 @@ const createClippedDataURLByCanvas = async ({
|
||||
// console.log("🖼️ 使用图像遮罩裁剪方法生成DataURL");
|
||||
|
||||
// 使用优化后的边界计算,确保包含描边区域
|
||||
// const optimizedBounds = calculateOptimizedBounds(
|
||||
// clippingObject,
|
||||
// fabricObjects
|
||||
// );
|
||||
const optimizedBounds = {
|
||||
left: clippingObject.left - clippingObject.width / 2,
|
||||
top: clippingObject.top - clippingObject.height / 2,
|
||||
width: clippingObject.width,
|
||||
height: clippingObject.height,
|
||||
}
|
||||
const optimizedBounds = calculateOptimizedBounds(
|
||||
clippingObject,
|
||||
fabricObjects
|
||||
);
|
||||
console.log("📐 优化后的选区边界框:", optimizedBounds);
|
||||
// const optimizedBounds = {
|
||||
// left: clippingObject.left - clippingObject.width / 2,
|
||||
// top: clippingObject.top - clippingObject.height / 2,
|
||||
// width: clippingObject.width,
|
||||
// height: clippingObject.height,
|
||||
// }
|
||||
|
||||
// 使用高分辨率以保证质量
|
||||
const pixelRatio = window.devicePixelRatio || 1;
|
||||
|
||||
@@ -375,6 +375,7 @@ const confirm = ()=>{
|
||||
/* 图片网格 */
|
||||
.image-grid {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
||||
gap: 16px;
|
||||
min-height: 20rem;
|
||||
|
||||
@@ -333,6 +333,7 @@
|
||||
]);
|
||||
const canvasLoadJsonSuccess = () => {
|
||||
console.log("画布加载JSON成功");
|
||||
return;
|
||||
canvasEditor.value?.updateOtherLayers({
|
||||
color: { rgba: { r: 255, g: 0, b: 0, a: 1 } },
|
||||
printObject: {
|
||||
@@ -446,6 +447,7 @@
|
||||
</template>
|
||||
</CanvasEditor>
|
||||
</div>
|
||||
<img src="" alt="" id="canvas-test-dom">
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
@@ -457,6 +459,13 @@
|
||||
height: 600px !important;
|
||||
z-index: 99999999;
|
||||
}
|
||||
#canvas-test-dom{
|
||||
position: fixed;
|
||||
z-index: 9999999999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
* {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
:enabledRedGreenMode="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="btn">123
|
||||
<div class="btn">
|
||||
<div class="gallery_btn" @click="exportElement">Export</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -331,7 +331,6 @@ export default defineComponent({
|
||||
store.commit('DesignDetail/setCurrentDetailType',str)
|
||||
}
|
||||
const setClothes = async (list:any,str:string)=>{
|
||||
console.log(JSON.parse(JSON.stringify(list)))
|
||||
let clothesList:any = []
|
||||
if(detailData.isEditPattern.value == 'editSketch')await detailDom.canvasBox.submitBase64Data().then((rv)=>{
|
||||
detailData.selectDetail.sketchString = rv
|
||||
@@ -369,7 +368,6 @@ export default defineComponent({
|
||||
// }else if(isCurrent){
|
||||
|
||||
// }
|
||||
console.log(JSON.parse(JSON.stringify(detailData.selectDetail.color)),'=====')
|
||||
color = list[i].color?.rgba?.r != null?`${list[i].color.rgba.r} ${list[i].color.rgba.g} ${list[i].color.rgba.b}`:''
|
||||
gradient = list[i].gradient
|
||||
if((detailData.currentDetailType == 'sketch' && newData?.sketch) || detailData.isEditPattern.value == 'editSketch'){
|
||||
@@ -500,7 +498,7 @@ export default defineComponent({
|
||||
}
|
||||
const submit = async ()=>{
|
||||
detailData.loadingShow = true
|
||||
if(detailData.isEditPattern.value !== 'canvasEditor'){
|
||||
if(detailData.isEditPattern.value !== 'canvasEditor' && detailDom.canvasBox){
|
||||
if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail()
|
||||
let otherData = await updateOtherLayers('single')
|
||||
await detailDom.canvasBox.updateOtherLayers(otherData)
|
||||
@@ -565,11 +563,14 @@ export default defineComponent({
|
||||
}
|
||||
}else{
|
||||
//走画布合成图片并且直接分割
|
||||
if(detailData.isEditPattern.value !== 'canvasEditor' && detailData.isEditPattern.value !== 'redGreenExample'){
|
||||
if(detailData.isEditPattern.value !== 'canvasEditor'){
|
||||
if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail()
|
||||
}
|
||||
let otherData = await updateOtherLayers('single')
|
||||
await detailDom.canvasBox.updateOtherLayers(otherData)
|
||||
}
|
||||
|
||||
await detailDom.canvasBox.privewDetail()
|
||||
await upDateFrontBackSketch()
|
||||
await uploadSelectDetail()
|
||||
@@ -625,7 +626,7 @@ export default defineComponent({
|
||||
if(detailData.isEditPattern.value && detailData.isEditPattern.value == str){
|
||||
// await detailDom.canvasBox.saveCanvas()
|
||||
await (detailDom.canvasBox as any).privewDetail()
|
||||
if(detailData.isEditPattern.value == 'canvasEditor')await uploadSelectDetail()
|
||||
if(detailData.isEditPattern.value == 'canvasEditor' || detailData.isEditPattern.value == 'redGreenExample')await uploadSelectDetail()
|
||||
detailData.isEditPattern.value = ''
|
||||
}else{
|
||||
// if(detailData.isEditPattern.value && (str == 'canvasEditor' || str == 'redGreenExample')){
|
||||
@@ -759,7 +760,6 @@ export default defineComponent({
|
||||
const uploadSelectDetail = async ()=>{//更新选中的detail
|
||||
// await detailDom.canvasBox.saveCanvas()
|
||||
const allInfo = await (detailDom.canvasBox as any).getCanvasElement()
|
||||
console.log(allInfo)
|
||||
let color:any = {}
|
||||
if(allInfo.color?.color?.rgba || allInfo.color?.color?.gradient){
|
||||
let canvasColor = allInfo.color.color;
|
||||
@@ -781,8 +781,7 @@ export default defineComponent({
|
||||
color.gradient = canvasColor.gradient
|
||||
}
|
||||
}
|
||||
|
||||
if(detailData.isEditPattern.value == 'canvasEditor'){
|
||||
if(detailData.isEditPattern.value == 'canvasEditor' || detailData.isEditPattern.value == 'redGreenExample'){
|
||||
delete detailData.selectDetail.newDetail
|
||||
detailData.selectDetail.trims.prints = allInfo.trims || []
|
||||
detailData.selectDetail.printObject.prints = allInfo.prints || []
|
||||
@@ -805,7 +804,6 @@ export default defineComponent({
|
||||
if(detailData.currentDetailType == 'color'){
|
||||
detailData.detailLeftColorKey++
|
||||
}
|
||||
|
||||
}
|
||||
const canvasReload = async ()=>{
|
||||
if(detailData.isEditPattern.value){
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
is-edit
|
||||
:clothingImageUrl="selectDetail.path"
|
||||
:clothingImageUrl2="selectDetail.maskUrl || selectDetail.layersObject[0].maskUrl"
|
||||
:clothingMinIOPath="selectDetail.minIOPath"
|
||||
showFixedLayer
|
||||
:canvasJSON="canvasJSON"
|
||||
@canvasLoadJsonSuccess="canvasLoadJsonSuccess"
|
||||
@@ -52,9 +51,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mark_loading" v-show="isShowMark">
|
||||
<!-- <div class="mark_loading" v-show="isShowMark">
|
||||
<a-spin size="large" />
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
</template>
|
||||
@@ -164,7 +163,6 @@ export default defineComponent({
|
||||
const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{
|
||||
// if(!detailDom.editCanvas)return
|
||||
return new Promise(async (res,reject)=>{
|
||||
console.log(detailDom.editCanvas)
|
||||
await detailDom.editCanvas.exportImage({
|
||||
isContainFixed:true,
|
||||
width:props.sketchSize.width,
|
||||
@@ -246,17 +244,27 @@ export default defineComponent({
|
||||
|
||||
|
||||
const frontBackChange = async (value:any)=>{
|
||||
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
||||
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
||||
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
||||
await nextTick()
|
||||
if(!detailData.selectDetail.partialDesign.partialDesignPath && !detailData.selectDetail.partialDesign.partialDesignBase64){
|
||||
await privewDetail()
|
||||
}else{
|
||||
await detailDom.editCanvas.exportImage({
|
||||
isFrontBackUpdata: true,
|
||||
isContainFixed:true,
|
||||
width:props.sketchSize.width,
|
||||
height:props.sketchSize.height,
|
||||
}).then((rv)=>{
|
||||
if(detailData.selectDetail?.partialDesign)detailData.selectDetail.partialDesign.partialDesignBase64 = rv
|
||||
})
|
||||
}
|
||||
let full = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.partialDesign.partialDesignPath || detailData.selectDetail.path
|
||||
let size = {
|
||||
...detailData.canvasConfig,
|
||||
}
|
||||
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
||||
segmentImage(value,full,size).then(async (rv)=>{
|
||||
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
||||
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
||||
if(!front?.oldImageUrl)front.oldImageUrl = front.imageUrl
|
||||
if(!front?.oldMaskUrl)front.oldMaskUrl = front.maskUrl
|
||||
if(!back?.oldImageUrl)back.oldImageUrl = back.imageUrl
|
||||
@@ -268,7 +276,6 @@ export default defineComponent({
|
||||
back.imageUrl = rv.targetBackUrl
|
||||
// store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
||||
})
|
||||
|
||||
}
|
||||
const editSketchCanvasInit = async (value:any)=>{
|
||||
detailData.canvasInstance = value
|
||||
|
||||
@@ -40,11 +40,29 @@ export default defineComponent({
|
||||
setup(props,{emit}) {
|
||||
const {t} = useI18n();
|
||||
const store = useStore();
|
||||
const updateCatecory = (arr)=>{
|
||||
arr.forEach((v:any) => {
|
||||
if(props.catecoryList)props.catecoryList.forEach((item:any) => {
|
||||
if(v.level2Type == item.value && !v.category){
|
||||
v.category=item.name
|
||||
v.categoryValue=item.value
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
const detailData = reactive({
|
||||
allBoardData:computed(()=>store.state.UploadFilesModule.allBoardData),
|
||||
currentList:{
|
||||
sketch:computed(()=>store.state.UploadFilesModule.allBoardData.sketchboardFiles),
|
||||
print:computed(()=>store.state.UploadFilesModule.allBoardData.printboardFiles),
|
||||
sketch:computed(()=>{
|
||||
let sketch = store.state.UploadFilesModule.allBoardData.sketchboardFiles
|
||||
updateCatecory(sketch)
|
||||
return sketch
|
||||
}),
|
||||
print:computed(()=>{
|
||||
let print = store.state.UploadFilesModule.allBoardData.printboardFiles
|
||||
updateCatecory(print)
|
||||
return print
|
||||
}),
|
||||
color:computed(()=>store.state.UploadFilesModule.allBoardData.colorBoards),
|
||||
models:computed(()=>store.state.Workspace.probjects.model),
|
||||
},
|
||||
|
||||
@@ -76,6 +76,7 @@ export default defineComponent({
|
||||
selectImgItem(data)
|
||||
return
|
||||
}
|
||||
data.id = id
|
||||
if(data?.imgUrl)data.url = data.imgUrl
|
||||
let value = {
|
||||
data,
|
||||
|
||||
@@ -273,7 +273,7 @@ export default defineComponent({
|
||||
minIOPath:data.minIOPath || data.originalUrl,
|
||||
path:data.url,
|
||||
priority:printIndex,
|
||||
scale,
|
||||
scale:editPrintElementData.stateOverallSingle == 'single'?scale:[1,1],
|
||||
globalCompositeOperation:'',
|
||||
}
|
||||
getItemPosition(item)
|
||||
@@ -300,7 +300,7 @@ export default defineComponent({
|
||||
// location = [item.pattern.style.left,item.pattern.style.top]
|
||||
}
|
||||
let value ={
|
||||
angle : item.pattern.transform.rotateZ,
|
||||
angle:0,
|
||||
// angle : !this.overallSingle ? 0:item.pattern.transform.rotateZ,
|
||||
location : location,
|
||||
priority:item.priority,
|
||||
@@ -312,7 +312,9 @@ export default defineComponent({
|
||||
ifSingle:!!item.ifSingle,
|
||||
globalCompositeOperation:'',
|
||||
}
|
||||
if(item.object)value.object = item.object
|
||||
if(item.object)value.object = item.object;
|
||||
value.angle = value.ifSingle?item.pattern.transform.rotateZ:item.angle
|
||||
|
||||
return value
|
||||
}
|
||||
if(editPrintElementData.printStyleList[props.type].single.length>0){
|
||||
@@ -359,7 +361,7 @@ export default defineComponent({
|
||||
//overall
|
||||
left = item.location[0] / editPrintElementData.sketchWH.scale[0]
|
||||
top = item.location[1] / editPrintElementData.sketchWH.scale[1]
|
||||
item.scale = [1,1]
|
||||
item.scale = item.scale || [1,1]
|
||||
}
|
||||
let pattern = {
|
||||
centers:{left:0,top:0},
|
||||
@@ -391,8 +393,8 @@ export default defineComponent({
|
||||
angle: 0,
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
// blendMode: "multiply",
|
||||
blendMode: "source-over",
|
||||
blendMode: "multiply",
|
||||
// blendMode: "source-over",
|
||||
gapX: 0,
|
||||
gapY: 0,
|
||||
}
|
||||
@@ -915,6 +917,7 @@ export default defineComponent({
|
||||
}
|
||||
const inputFillAngle = (angle:any)=>{
|
||||
let arr = editPrintElementData.printStyleList[props.type].overall
|
||||
console.log(angle)
|
||||
arr[editPrintElementData.imgDomIndex].angle = angle
|
||||
editPrintElementDom.pingpuRef.updataList([
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
:max="1000"
|
||||
:step="1"
|
||||
is-input
|
||||
:tipFormatter="(v) => `${scale.toFixed(0)}%`"
|
||||
:tipFormatter="(v) => `${Number(scale)?.toFixed(0)}%`"
|
||||
:value="scale"
|
||||
@input="inputFillScale"
|
||||
/>
|
||||
@@ -25,7 +25,7 @@
|
||||
<div class="repeat-setting-item">
|
||||
<span class="label">Gap X</span>
|
||||
<slider
|
||||
:min="0"
|
||||
:min="1"
|
||||
:max="1000"
|
||||
:step="1"
|
||||
is-input
|
||||
@@ -39,7 +39,7 @@
|
||||
<div class="repeat-setting-item">
|
||||
<span class="label">Gap Y</span>
|
||||
<slider
|
||||
:min="0"
|
||||
:min="1"
|
||||
:max="1000"
|
||||
:step="1"
|
||||
is-input
|
||||
@@ -84,7 +84,7 @@
|
||||
const scale = computed(() => {
|
||||
// let scaleValue = props.object?.scale/10;
|
||||
// return props.object?.scale/10;
|
||||
return props.object?.scale[0] * 100;
|
||||
return (props.object?.scale[0] * 100).toFixed(0);
|
||||
});
|
||||
const scalePrint = computed(() => {
|
||||
let index = sketchWH.value[0] > sketchWH.value[1]?0:1;
|
||||
|
||||
@@ -124,7 +124,11 @@ export default defineComponent({
|
||||
const handleResize = ()=>{
|
||||
clearTimeout(time)
|
||||
time = setTimeout(()=>{
|
||||
store.commit('DesignDetail/setDesignDetail',getDetailListData.designDetail)
|
||||
let data = {
|
||||
...getDetailListData.designDetail,
|
||||
fromType:'resize',
|
||||
}
|
||||
store.commit('DesignDetail/setDesignDetail',data)
|
||||
getDetailListDom.position?.updataPosition?.()
|
||||
getDetailListDom.modelNav?.setItemPosition?.()
|
||||
getDetailListDom.position?.updateRect?.()
|
||||
|
||||
@@ -189,11 +189,11 @@ export default defineComponent({
|
||||
}
|
||||
return { scaleX, scaleY, rotate };
|
||||
}
|
||||
const initMoveableForSelected = () => {
|
||||
const initMoveableForSelected = async (isDestroy:boolean = false) => {
|
||||
// 销毁旧的实例
|
||||
if(selectItem.imgDomIndex == -1)return
|
||||
if (moveableInstance.value) {
|
||||
moveableInstance.value.destroy();
|
||||
if (moveableInstance?.value?.destroy && !isDestroy) {
|
||||
moveableInstance?.value?.destroy();
|
||||
}
|
||||
|
||||
const selectedEl = elementRefs.value[selectItem.imgDomIndex];
|
||||
@@ -509,7 +509,7 @@ export default defineComponent({
|
||||
watch(()=>detailData.frontBack.front.length,(newValue,oldValue)=>{
|
||||
if(selectItem.selectDetail?.id)selectItem.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == selectItem.selectDetail?.id)
|
||||
setTimeout(()=>{
|
||||
initMoveableForSelected()
|
||||
initMoveableForSelected(oldValue == 0)
|
||||
},100)
|
||||
})
|
||||
const setRevocation = async ()=>{
|
||||
|
||||
@@ -1,108 +1,152 @@
|
||||
<template>
|
||||
<div class="eventsDetail_page" :class="{active:isScroll}">
|
||||
<div class="eventsDetail_title ">
|
||||
<div class="eventsDetail_page" :class="{ active: isScroll }">
|
||||
<div class="eventsDetail_title">
|
||||
<div class="modal_title_text" @click="setBack">
|
||||
<i class="fi fi-sr-left"></i>
|
||||
<div class="eventsDetail_title_text">{{ $t('event.back') }}</div>
|
||||
<div class="eventsDetail_title_text">{{ $t("event.back") }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="eventsDetail_content">
|
||||
<div class="eventsDetail_content_left">
|
||||
<fullScreenImg :src="eventsDetail.imgUrl" width="100%" :center="true"></fullScreenImg>
|
||||
<fullScreenImg
|
||||
:src="eventsDetail.imgUrl"
|
||||
width="100%"
|
||||
:center="true"
|
||||
></fullScreenImg>
|
||||
</div>
|
||||
<div class="eventsDetail_content_right">
|
||||
<div class="modal_title_text">
|
||||
<div class="modal_title_text modal_title_text-header flex space-between">
|
||||
<div>{{ eventsDetail.title }}</div>
|
||||
<div class="detail-btn" v-if="eventsDetail.id === 3" @click="openDetail">
|
||||
{{ $t("event.detail") }}
|
||||
</div>
|
||||
<div class="modal_title_text" v-for="item in eventsDetail.textList">
|
||||
</div>
|
||||
<div
|
||||
class="modal_title_text content"
|
||||
v-for="item in eventsDetail.textList"
|
||||
:class="{ award: eventsDetail.id === 3 }"
|
||||
>
|
||||
<div class="eventsDetail_content_right_btn_box">
|
||||
<div class="eventsDetail_content_right_btn" v-for="buttonItem,buttonIndex in item?.button" @click="openButton(buttonItem,buttonIndex)">
|
||||
<div v-show="!loadingShow[buttonIndex]" class="started_btn">{{ buttonItem.text }}</div>
|
||||
<div v-show="loadingShow[buttonIndex]" class="started_btn"><i class="fi fi-br-loading"></i></div>
|
||||
<div
|
||||
class="eventsDetail_content_right_btn"
|
||||
v-for="(buttonItem, buttonIndex) in item?.button"
|
||||
@click="openButton(buttonItem, buttonIndex)"
|
||||
>
|
||||
<div v-show="!loadingShow[buttonIndex]" class="started_btn">
|
||||
{{ buttonItem.text }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal_title_text_intro" v-for="introItem in item?.paragraph" :class="{active:introItem.display == 'flex'}" v-detailText="introItem.text">
|
||||
<div v-show="loadingShow[buttonIndex]" class="started_btn">
|
||||
<i class="fi fi-br-loading"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="modal_title_text_intro"
|
||||
v-for="introItem in item?.paragraph"
|
||||
:class="{ active: introItem.display == 'flex' }"
|
||||
v-detailText="introItem.text"
|
||||
></div>
|
||||
</div>
|
||||
<div class="tips" v-if="eventsDetail.tips">{{ eventsDetail.tips }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { LoadingOutlined } from "@ant-design/icons-vue";
|
||||
import { defineComponent,h ,toRefs,ref,reactive,onMounted,nextTick,provide,computed} from 'vue'
|
||||
import { LoadingOutlined } from "@ant-design/icons-vue"
|
||||
import {
|
||||
defineComponent,
|
||||
h,
|
||||
toRefs,
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
nextTick,
|
||||
provide,
|
||||
computed
|
||||
} from "vue"
|
||||
// import RobotAssist from "@/component/HomePage/RobotAssist.vue";
|
||||
import { Https } from "@/tool/https";
|
||||
import { message, Upload, Modal } from "ant-design-vue";
|
||||
import fullScreenImg from '@/component/HomePage/fullScreenImg.vue'
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from "vue-i18n";
|
||||
import generalMenu from "@/component/HomePage/generalMenu.vue";
|
||||
import eventData from "@/assets/json/events.json";
|
||||
import eventDataCn from "@/assets/json/events_cn.json";
|
||||
import { useStore } from "vuex";
|
||||
import { Https } from "@/tool/https"
|
||||
import { message, Upload, Modal } from "ant-design-vue"
|
||||
import fullScreenImg from "@/component/HomePage/fullScreenImg.vue"
|
||||
import { useRouter } from "vue-router"
|
||||
import { useI18n } from "vue-i18n"
|
||||
import generalMenu from "@/component/HomePage/generalMenu.vue"
|
||||
import eventData from "@/assets/json/events.json"
|
||||
import eventDataCn from "@/assets/json/events_cn.json"
|
||||
import { useStore } from "vuex"
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
generalMenu,
|
||||
fullScreenImg,
|
||||
},
|
||||
props:{
|
||||
isScroll:{
|
||||
type:Boolean,
|
||||
default:true,
|
||||
fullScreenImg
|
||||
},
|
||||
props: {
|
||||
isScroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
let filter:any = reactive({
|
||||
eventsDetail: {
|
||||
const { t, locale } = useI18n()
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
let filter: any = reactive({
|
||||
eventsDetail: {},
|
||||
getListDate: {
|
||||
getLikePortfolio: 0,
|
||||
getMyPortfolio: 0,
|
||||
page: 1,
|
||||
size: 10
|
||||
},
|
||||
getListDate:{
|
||||
"getLikePortfolio": 0,
|
||||
"getMyPortfolio": 0,
|
||||
page:1,
|
||||
size:10,
|
||||
},
|
||||
isShowMark:false,
|
||||
isNoData:false,//如果数据为空就不加载
|
||||
loadingShow:{},
|
||||
isShowMark: false,
|
||||
isNoData: false, //如果数据为空就不加载
|
||||
loadingShow: {}
|
||||
})
|
||||
let likeFile = (item:any,type:string) => {
|
||||
}
|
||||
let setBack = ()=>{
|
||||
router.go(-1);
|
||||
let likeFile = (item: any, type: string) => {}
|
||||
let setBack = () => {
|
||||
router.go(-1)
|
||||
// router.push('/home/events')
|
||||
}
|
||||
let openButton = (data:any,index:number)=>{
|
||||
if(filter.loadingShow[index]){
|
||||
let openButton = (data: any, index: number) => {
|
||||
if (filter.loadingShow[index]) {
|
||||
return
|
||||
}
|
||||
filter.loadingShow[index] = true
|
||||
Https.axiosGet(data.https).then(
|
||||
(rv: any) => {
|
||||
if(rv){
|
||||
Https.axiosGet(data.https)
|
||||
.then((rv: any) => {
|
||||
if (rv) {
|
||||
message.success(data.success)
|
||||
filter.loadingShow[index] = false
|
||||
}
|
||||
}
|
||||
).catch(res=>{
|
||||
})
|
||||
.catch((res) => {
|
||||
filter.loadingShow[index] = false
|
||||
});
|
||||
})
|
||||
}
|
||||
onMounted (()=>{
|
||||
const { t, locale } = useI18n();
|
||||
const currentLocale = locale.value;
|
||||
let eventLangData:any
|
||||
if(currentLocale == 'ENGLISH'){
|
||||
const openDetail = () => {
|
||||
let language = locale.value === "ENGLISH" ? "en" : "cn"
|
||||
let url = `https://aida-global-design-awards.com.hk/${language}`
|
||||
// 如果是dev环境把域名换成http://192.168.31.198
|
||||
|
||||
if (import.meta.env.VITE_APP_BASE_URL === "https://develop.api.aida.com.hk") {
|
||||
url += "?env=dev"
|
||||
}
|
||||
window.open(url, "_blank")
|
||||
|
||||
// router.push("/award/index")
|
||||
}
|
||||
onMounted(() => {
|
||||
const currentLocale = locale.value
|
||||
let eventLangData: any
|
||||
if (currentLocale == "ENGLISH") {
|
||||
eventLangData = eventData
|
||||
}else{
|
||||
} else {
|
||||
eventLangData = eventDataCn
|
||||
}
|
||||
eventLangData.eventsItem.forEach((item:any)=>{
|
||||
if(item.id == router.currentRoute.value.query.eventId){
|
||||
filter.eventsDetail = item;
|
||||
eventLangData.eventsItem.forEach((item: any) => {
|
||||
if (item.id == router.currentRoute.value.query.eventId) {
|
||||
filter.eventsDetail = item
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -111,18 +155,17 @@ export default defineComponent({
|
||||
likeFile,
|
||||
setBack,
|
||||
openButton,
|
||||
openDetail
|
||||
}
|
||||
},
|
||||
directives:{
|
||||
detailText:{
|
||||
mounted (el,binding) {
|
||||
directives: {
|
||||
detailText: {
|
||||
mounted(el, binding) {
|
||||
el.innerHTML = binding.value
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted(){
|
||||
|
||||
},
|
||||
async mounted() {}
|
||||
})
|
||||
</script>
|
||||
<style lang="less">
|
||||
@@ -132,11 +175,11 @@ export default defineComponent({
|
||||
padding: 0 6rem;
|
||||
padding-top: 5rem;
|
||||
|
||||
&.active{
|
||||
&.active {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
.eventsDetail_content{
|
||||
.eventsDetail_content {
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -146,7 +189,7 @@ export default defineComponent({
|
||||
min-height: auto;
|
||||
padding-bottom: 10rem;
|
||||
}
|
||||
.eventsDetail_title{
|
||||
.eventsDetail_title {
|
||||
display: flex;
|
||||
padding: 2rem 0rem;
|
||||
align-items: center;
|
||||
@@ -154,21 +197,21 @@ export default defineComponent({
|
||||
top: 0;
|
||||
z-index: 222;
|
||||
background: #fff;
|
||||
.modal_title_text{
|
||||
.modal_title_text {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.modal_title_text:hover .eventsDetail_title_text{
|
||||
.modal_title_text:hover .eventsDetail_title_text {
|
||||
text-decoration: underline;
|
||||
}
|
||||
i{
|
||||
i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
.eventsDetail_content{
|
||||
.eventsDetail_content {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -176,65 +219,100 @@ export default defineComponent({
|
||||
@media (max-width: 768px) {
|
||||
flex-direction: column;
|
||||
}
|
||||
.eventsDetail_content_left,.eventsDetail_content_right{
|
||||
.eventsDetail_content_left,
|
||||
.eventsDetail_content_right {
|
||||
width: 50%;
|
||||
@media (max-width: 768px) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.eventsDetail_content_left{
|
||||
.eventsDetail_content_left {
|
||||
width: 40%;
|
||||
max-height: 60rem;
|
||||
@media (max-width: 768px) {
|
||||
width: 100%;
|
||||
}
|
||||
.ant-image{
|
||||
.ant-image {
|
||||
// height: auto;
|
||||
height: 100%;
|
||||
}
|
||||
.eventsDetail_content_left_img{
|
||||
.eventsDetail_content_left_img {
|
||||
width: 100%;
|
||||
cursor: zoom-in;
|
||||
}
|
||||
}
|
||||
.eventsDetail_content_right{
|
||||
.modal_title_text{
|
||||
letter-spacing: .4rem;
|
||||
.eventsDetail_content_right {
|
||||
.modal_title_text {
|
||||
letter-spacing: 0.3rem;
|
||||
font-weight: 600;
|
||||
.modal_title_text_intro{
|
||||
&-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
> div:first-child {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
.modal_title_text_intro {
|
||||
display: block;
|
||||
&.active{
|
||||
&.active {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
li{
|
||||
li {
|
||||
width: 48%;
|
||||
|
||||
}
|
||||
em{
|
||||
em {
|
||||
// font-family: auto;
|
||||
}
|
||||
a{
|
||||
a {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
.eventsDetail_content_right_btn_box{
|
||||
.eventsDetail_content_right_btn_box {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
.eventsDetail_content_right_btn{
|
||||
// .eventsDetail_content_right_btn {
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.modal_title_text:last-child{
|
||||
}
|
||||
.modal_title_text:last-child::after{
|
||||
// .modal_title_text:last-child {
|
||||
// }
|
||||
.modal_title_text:last-child::after {
|
||||
content: "";
|
||||
display: block;
|
||||
border-top: 3px solid;
|
||||
height: 6rem;
|
||||
}
|
||||
.modal_title_text.award:last-child:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail-btn {
|
||||
// width: 11rem;
|
||||
padding: 0 1.4rem;
|
||||
height: 4rem;
|
||||
line-height: 4rem;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 2rem;
|
||||
background-color: #000;
|
||||
font-size: 1.4rem;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tips{
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
font-size: var(--aida-fsize1-4);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.3rem;
|
||||
}
|
||||
.modal_title_text.content.award{
|
||||
line-height: 1.3;
|
||||
}
|
||||
</style>
|
||||
@@ -531,7 +531,7 @@ export default defineComponent({
|
||||
}
|
||||
)
|
||||
const setSpeed = (item: any) => {
|
||||
speed.speedData = item
|
||||
speed.speedData = {...item}
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.msg == 'Sketchboard') {
|
||||
@@ -734,6 +734,8 @@ export default defineComponent({
|
||||
let maxImg = 8
|
||||
if (this.type_.type2 == 'Sketchboard') {
|
||||
maxImg = 20
|
||||
}else if(this.type_.type2 == 'Printboard'){
|
||||
maxImg = 16
|
||||
}
|
||||
let parent: any = this.$parent
|
||||
if (parent.isUseGenerate) {
|
||||
@@ -853,9 +855,7 @@ export default defineComponent({
|
||||
level2Type = this.sketchboardList?.[0]?.categoryValue
|
||||
? this.sketchboardList[0].categoryValue
|
||||
: ''
|
||||
if (this.workspace.styleName) {
|
||||
sloganText = `${this.workspace.styleName},${sloganText}`
|
||||
}
|
||||
sloganText = `${this.workspace.styleName || 'all'},${sloganText}`
|
||||
} else if (this.upload.level1Type == 'Printboard') {
|
||||
level2Type = this.scene?.value
|
||||
if (level2Type == 'Slogan' && this.searchPictureName == '') {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
:get-container="() => $refs.upgradePlan"
|
||||
width="35%"
|
||||
height="auto"
|
||||
zIndex="9999999"
|
||||
:maskClosable="false"
|
||||
:centered="true"
|
||||
:closable="false"
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
</div>
|
||||
<div class="payment">
|
||||
<div class="allocation">
|
||||
<div class="selectType">
|
||||
<!-- <div class="selectType">
|
||||
<div class="text">{{ $t('Renew.Payment') }}:</div>
|
||||
<label>
|
||||
<input
|
||||
@@ -227,7 +227,7 @@
|
||||
/>
|
||||
{{ $t('Renew.Alipay') }}
|
||||
</label>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="gallery_btn gallery_btn_radius" @click="payment">
|
||||
{{ $t('upgradePlan.Continue') }}
|
||||
|
||||
@@ -77,17 +77,10 @@ export default defineComponent({
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
width: 80%;
|
||||
height: auto;
|
||||
max-height: 80vh;
|
||||
position: absolute;
|
||||
width: max-content;
|
||||
video{
|
||||
width: 100%;
|
||||
max-height: 80vh;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
width: max-content;
|
||||
max-height:80vh;
|
||||
max-width:80vw;
|
||||
}
|
||||
.general_video_btn{
|
||||
color: #fff;
|
||||
|
||||
@@ -517,6 +517,7 @@ defineExpose({
|
||||
/* 图片网格 */
|
||||
.image-grid {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
overflow-y: auto;
|
||||
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
||||
gap: 16px;
|
||||
|
||||
@@ -379,6 +379,7 @@ export default defineComponent({
|
||||
setup(props,{emit}) {
|
||||
const {t,locale} = useI18n()
|
||||
const store = useStore();
|
||||
const route = useRoute()
|
||||
const editDesignType = reactive({
|
||||
selectProbject:computed(()=>{
|
||||
return store.state.Workspace.probjects
|
||||
@@ -624,6 +625,7 @@ export default defineComponent({
|
||||
collItemSize.collTime = setTimeout(()=>{
|
||||
nextTick(()=>{
|
||||
let parentWidth = likeItemDom.value.parentElement.offsetWidth
|
||||
if(parentWidth == 0)return
|
||||
collItemSize.widthValue.value = collItemSize.widthValue.value == -1?100:collItemSize.widthValue.value
|
||||
collItemSize.widthValue.value = collItemSize.widthValue.value > parentWidth?parentWidth:collItemSize.widthValue.value
|
||||
collItemSize.collValue = Math.floor(parentWidth / collItemSize.widthValue.value)
|
||||
@@ -634,7 +636,6 @@ export default defineComponent({
|
||||
|
||||
collItemSize.collStyle.width = (collItemDom.value.offsetWidth - 30) / 3 * collItemSize.scale[0] + 'px'
|
||||
collItemSize.collStyle.height = (collItemDom.value.offsetWidth - 30) / 3 * collItemSize.scale[1] + 'px'
|
||||
|
||||
collItemSize.likeStyle.width = collItemSize.itemStyle.width + 'px'
|
||||
collItemSize.likeStyle.height = collItemSize.itemStyle.height + 'px'
|
||||
let elArr = likeItemDom.value.children
|
||||
@@ -744,6 +745,12 @@ export default defineComponent({
|
||||
"userLikeId": likeItem.id
|
||||
}
|
||||
arrData.push(obj)
|
||||
designData.selectLikeDesign.forEach((v:any)=>{
|
||||
if(v.id === likeItem.id){
|
||||
v.oldSort = v.sort
|
||||
v.sort = likeItem.sort
|
||||
}
|
||||
})
|
||||
})
|
||||
let data = {
|
||||
"userLikeGroupId": userGroupId.value,
|
||||
@@ -1303,9 +1310,9 @@ export default defineComponent({
|
||||
})
|
||||
return
|
||||
}
|
||||
const parents = designData.selectLikeDesign.filter((item:any) => item.resultType === 'Design');
|
||||
const parents = designData.selectLikeDesign.filter((item:any) => item.resultType === 'Design').filter((item:any) => likeDesignCollectionList.value.some((v:any) => (v.id === item.id)));
|
||||
parents.map((parent:any) => {
|
||||
parent.sort = parent.oldSort||parent.sort
|
||||
parent.sort = likeDesignCollectionList.value.find((v:any) => v.id === parent.id)?.sort || parent.oldSort||parent.sort
|
||||
delete parent.oldSort
|
||||
return {
|
||||
...parent,
|
||||
@@ -1532,7 +1539,7 @@ export default defineComponent({
|
||||
this.observerData.time = setTimeout(()=>{
|
||||
|
||||
this.setSystemDesigner(0)
|
||||
this.setDesignItemStyle()
|
||||
// this.setDesignItemStyle()
|
||||
},100)
|
||||
// const { width } = entry.contentRect;
|
||||
}
|
||||
@@ -1930,6 +1937,7 @@ export default defineComponent({
|
||||
this.disLikeLoading = true;
|
||||
Https.axiosPost(Https.httpUrls.designDislike, data)
|
||||
.then((rv: any) => {
|
||||
console.log(rv)
|
||||
if (rv) {
|
||||
this.recycleDomHidden = true
|
||||
this.store.commit("addDesignCollectionList", [design]);
|
||||
|
||||
@@ -271,7 +271,7 @@ export default defineComponent({
|
||||
allCollectionStr.forEach((itemStr:any)=>{
|
||||
let list = [] as any
|
||||
allCollection[itemStr.value].forEach((imgItem)=>{
|
||||
list.push({url:imgItem.url || imgItem.imgUrl})
|
||||
list.push({url:imgItem?.url || imgItem?.imgUrl})
|
||||
})
|
||||
let obj = {
|
||||
value:itemStr.value,
|
||||
|
||||
@@ -196,9 +196,9 @@ export default defineComponent({
|
||||
type:rv.process == 'SERIES_DESIGN'?'seriesDesign':'singleProductDesign',
|
||||
httpType:rv.process,//项目类型
|
||||
ageGroup:rv.workspaceVO?.ageGroup,
|
||||
style:rv.workspaceVO?.style,
|
||||
styleId:rv.workspaceVO?.styleId,
|
||||
styleName:rv.workspaceVO?.styleName,
|
||||
style:rv.workspaceVO?.style || '',
|
||||
styleId:rv.workspaceVO?.styleId || null,
|
||||
styleName:rv.workspaceVO?.styleName || '',
|
||||
sex:rv.workspaceVO?.sex,
|
||||
userBrandDnaImg:rv.workspaceVO?.userBrandDnaImg,
|
||||
userBrandDnaName:rv.workspaceVO?.userBrandDnaName,
|
||||
|
||||
@@ -94,9 +94,9 @@ export default defineComponent({
|
||||
type:rv.process == 'SERIES_DESIGN'?'seriesDesign':'singleProductDesign',
|
||||
httpType:rv.process,//项目类型
|
||||
ageGroup:rv.workspaceVO.ageGroup,
|
||||
style:rv.workspaceVO.style,
|
||||
styleId:rv.workspaceVO.styleId,
|
||||
styleName:rv.workspaceVO.styleName,
|
||||
style:rv.workspaceVO.style || '',
|
||||
styleId:rv.workspaceVO.styleId || null,
|
||||
styleName:rv.workspaceVO.styleName || '',
|
||||
sex:rv.workspaceVO.sex,
|
||||
userBrandDnaImg:rv.workspaceVO.userBrandDnaImg,
|
||||
userBrandDnaName:rv.workspaceVO.userBrandDnaName,
|
||||
|
||||
@@ -41,10 +41,10 @@
|
||||
<div class="center">{{ selectObject?.styleName?selectObject?.styleName:$t('Header.All') }}</div>
|
||||
<div class="gallery_btn" @click="setStyle">{{ $t('Habit.Select') }}</div>
|
||||
</div>
|
||||
<div class="style brand marginBottom">
|
||||
<!-- <div class="style brand marginBottom">
|
||||
<div class="text">{{$t('Habit.Brand')}}:</div>
|
||||
<div class="gallery_btn" @click="setBrandDNA">{{ $t('Habit.Select') }}</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="brandImg" v-if="selectObject.userBrandDna"><img :src="selectObject.userBrandDnaImg"></div>
|
||||
<div class="brandDNAStrenght marginBottom" v-if="selectObject.userBrandDna">
|
||||
<div class="text" style="font-size: 1.6rem;">
|
||||
@@ -179,9 +179,9 @@ export default defineComponent({
|
||||
dataDom.brandDNA.init(data.selectObject);
|
||||
}
|
||||
const setWorkspaceStyle = (value:any)=>{
|
||||
data.selectObject.styleName = value.name
|
||||
data.selectObject.style = value.value
|
||||
data.selectObject.styleId = value.id
|
||||
data.selectObject.styleName = value.name || ''
|
||||
data.selectObject.style = value.value || ''
|
||||
data.selectObject.styleId = value.id || null
|
||||
// store.commit('setProbject',data)
|
||||
}
|
||||
const setWorkspaceBrandDNA = (value:any)=>{
|
||||
@@ -238,9 +238,9 @@ export default defineComponent({
|
||||
// type:rv.process == 'SERIES_DESIGN'?'seriesDesign':'singleProductDesign',
|
||||
// httpType:rv.process,//项目类型
|
||||
ageGroup:rv.workspaceVO?.ageGroup,
|
||||
style:rv.workspaceVO?.style,
|
||||
styleId:rv.workspaceVO?.styleId,
|
||||
styleName:rv.workspaceVO?.styleName,
|
||||
style:rv.workspaceVO?.style || '',
|
||||
styleId:rv.workspaceVO?.styleId || null,
|
||||
styleName:rv.workspaceVO?.styleName || '',
|
||||
sex:rv.workspaceVO?.sex,
|
||||
userBrandDnaImg:rv.workspaceVO?.userBrandDnaImg,
|
||||
userBrandDnaName:rv.workspaceVO?.userBrandDnaName,
|
||||
|
||||
@@ -352,7 +352,8 @@ export default defineComponent({
|
||||
props: {
|
||||
isDesignPage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
required:false
|
||||
},
|
||||
source: {
|
||||
type: String,
|
||||
@@ -773,7 +774,7 @@ export default defineComponent({
|
||||
data.lastSelectImg = res.data
|
||||
}
|
||||
}
|
||||
// 同步尾帧文件列表到全局 store
|
||||
// 同步尾帧文件列表到全局 store(使用专门的 lastFrameList)
|
||||
store.commit('setPoseTransferLastFrameList', {
|
||||
str: 'set',
|
||||
list: [file]
|
||||
@@ -989,6 +990,7 @@ export default defineComponent({
|
||||
if (data.lastSelectImg?.id === item.id) {
|
||||
data.lastSelectImg = {}
|
||||
}
|
||||
// 使用专门的 lastFrameList mutation 清空列表
|
||||
store.commit('setPoseTransferLastFrameList')
|
||||
} else {
|
||||
// 如果删除的是当前选中的首帧,清空选中状态
|
||||
@@ -1176,10 +1178,10 @@ export default defineComponent({
|
||||
firstFrameList.value = store.state.HomeStoreModule.uploadElement.filter(
|
||||
item => item.frameType === 'first'
|
||||
)
|
||||
|
||||
lastFrameList.value = store.state.HomeStoreModule.uploadElement.filter(
|
||||
item => item.frameType === 'last'
|
||||
)
|
||||
// 注意:尾帧通过专门的 watch (lastFrameList) 监听,不需要从这里过滤
|
||||
// lastFrameList.value = store.state.HomeStoreModule.uploadElement.filter(
|
||||
// item => item.frameType === 'last'
|
||||
// )
|
||||
// 更新 showFirstFrameList 中项的选中状态
|
||||
showFirstFrameList.value.forEach((listItem: any) => {
|
||||
if (listItem.id == data.selectImg.id) {
|
||||
|
||||
@@ -102,9 +102,9 @@ setup(props,{emit}) {
|
||||
// if(habitSetStyleData.styleList.length == 0){
|
||||
// getStyleList()
|
||||
// }
|
||||
oldDataId = data.styleId
|
||||
habitSetStyleData.selectStyle.id = data.styleId
|
||||
habitSetStyleData.selectStyle.name = data.styleName
|
||||
oldDataId = data.styleId || null
|
||||
habitSetStyleData.selectStyle.id = data.styleId || null
|
||||
habitSetStyleData.selectStyle.name = data.styleName || ''
|
||||
// habitSetStyleData.selectStyleId = 'feng2'
|
||||
}
|
||||
let setCover = (item:any)=>{
|
||||
@@ -258,6 +258,7 @@ methods: {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.content_bottom_item:nth-child(4n){
|
||||
|
||||
@@ -1532,7 +1532,8 @@ export default {
|
||||
LiquefactionTool: '液化工具'
|
||||
},
|
||||
event: {
|
||||
back: '返回'
|
||||
back: '返回',
|
||||
detail:'查看详情'
|
||||
},
|
||||
admin: {
|
||||
allUser: '所有用户',
|
||||
|
||||
@@ -1184,7 +1184,7 @@ export default {
|
||||
CanvasTitle: {
|
||||
ModifySketch: 'Modify Sketch',
|
||||
ModifyItem: 'Modify Item',
|
||||
RedGreen: 'Edit Front and Back Section',
|
||||
RedGreen: 'Edit Front and Back Section'
|
||||
},
|
||||
Canvas: {
|
||||
Canvas: 'Canvas',
|
||||
@@ -1559,7 +1559,7 @@ export default {
|
||||
PointSelection: 'Point Selection',
|
||||
MarqueeSelection: 'Marquee Selection',
|
||||
BrushSelection: 'Brush Selection',
|
||||
Erase: 'Erase',
|
||||
Erase: 'Erase'
|
||||
},
|
||||
speedList: {
|
||||
High: 'High',
|
||||
@@ -1583,7 +1583,8 @@ export default {
|
||||
LiquefactionTool: 'Liquefaction Tool'
|
||||
},
|
||||
event: {
|
||||
back: 'Back'
|
||||
back: 'Back',
|
||||
detail: 'View Details'
|
||||
},
|
||||
admin: {
|
||||
allUser: 'All User',
|
||||
@@ -1657,7 +1658,7 @@ export default {
|
||||
Cancel: 'Cancel',
|
||||
SelectPlan: 'Select Plan',
|
||||
AllPlan: 'All',
|
||||
PlanStart:'This plan will be actived from',
|
||||
PlanStart: 'This plan will be actived from'
|
||||
},
|
||||
Login: {
|
||||
Login: 'Login',
|
||||
|
||||
@@ -53,6 +53,12 @@ const routes: Array<RouteRecordRaw> = [
|
||||
meta: { enter: "all" },
|
||||
component: () => import("@/views/Register.vue"),
|
||||
},
|
||||
{
|
||||
path: "/register/:lang",
|
||||
name: "registerLang",
|
||||
meta: { enter: "all" },
|
||||
component: () => import("@/views/Register.vue"),
|
||||
},
|
||||
{
|
||||
path: "/upgrade",
|
||||
name: "upgrade",
|
||||
@@ -172,6 +178,12 @@ const routes: Array<RouteRecordRaw> = [
|
||||
meta: { enter: "all" },
|
||||
component: () => import("@/views/HomeRecommend.vue"),
|
||||
},
|
||||
{
|
||||
path: "/Square/:lang",
|
||||
name: "HomeRecommendLang",
|
||||
meta: { enter: "all" },
|
||||
component: () => import("@/views/HomeRecommend.vue"),
|
||||
},
|
||||
{
|
||||
path: "/administrator",
|
||||
name: "administrator",
|
||||
@@ -325,6 +337,13 @@ const routes: Array<RouteRecordRaw> = [
|
||||
meta: { enter: 3 },
|
||||
component: () =>
|
||||
import("@/component/Administrator/SE/getGenerateFrequency/index.vue"),
|
||||
},
|
||||
{
|
||||
path: "globalAwardPopularity",
|
||||
name: "globalAwardPopularity",
|
||||
meta: { enter: 3 },
|
||||
component: () =>
|
||||
import("@/component/Administrator/globalAwardPopularity.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -87,8 +87,10 @@ const DesignDetail : Module<DesignDetail,RootState> = {
|
||||
left:0,
|
||||
top:0,
|
||||
}
|
||||
if(data?.fromType !== 'resize'){
|
||||
v.maskMinioUrl = v.layersObject?.[0]?.maskMinioUrl
|
||||
v.maskUrl = v.layersObject?.[0]?.maskUrl
|
||||
}
|
||||
v.layersObject[i].designOpenrtionBtn = false
|
||||
if(v.layersObject[i].imageCategory.indexOf("back") == -1){
|
||||
front[index] = v.layersObject[i]
|
||||
|
||||
@@ -74,7 +74,7 @@ const HomeStoreModule : Module<DesignDetail,RootState> = {
|
||||
},
|
||||
setPoseTransferLastFrameList(state,data){
|
||||
// 支持两种方式:set 替换整个列表;add/删除与 uploadElement 一致
|
||||
if(data.str === 'set'){
|
||||
if(data?.str === 'set'){
|
||||
state.lastFrameList = data.list || []
|
||||
return
|
||||
}else{
|
||||
|
||||
@@ -77,7 +77,7 @@ const userHabit : Module<UserHabit,RootState> = {
|
||||
followeeCount: '-',
|
||||
followerCount: '-',
|
||||
accountExtendList:null,
|
||||
systemList:[],
|
||||
systemList:[1],
|
||||
expireTime:null,
|
||||
language:'',
|
||||
organizationId: null,
|
||||
@@ -194,7 +194,7 @@ const userHabit : Module<UserHabit,RootState> = {
|
||||
followeeCount: '-',
|
||||
followerCount: '-',
|
||||
accountExtendList:null,
|
||||
systemList:[],
|
||||
systemList:[1],
|
||||
expireTime:null,
|
||||
language:'',
|
||||
organizationId: null,
|
||||
@@ -407,7 +407,7 @@ const userHabit : Module<UserHabit,RootState> = {
|
||||
item.name = name
|
||||
});
|
||||
// const {t} = useI18n()
|
||||
rv.unshift({name:t('Model.all'),value:'',id:''})
|
||||
rv.unshift({name:t('Model.all'),value:'',id:null})
|
||||
store.commit('setMannequinStyle',rv)
|
||||
resolve('')
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ const Workspace: Module<DesignDetail, RootState> = {
|
||||
},
|
||||
setProbject(state, data) {
|
||||
for (const key in data) {
|
||||
if (data[key] == undefined) continue
|
||||
let list = ['styleName','styleId','style']
|
||||
if (data[key] == undefined && !list.includes(key)) continue
|
||||
state.probjects[key] = data[key]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -198,6 +198,13 @@ const all = (t)=>{
|
||||
route: '/administrator/subscriptionPlan',
|
||||
key: 'sub14',
|
||||
isShow: true
|
||||
},
|
||||
{
|
||||
name: 'Global Award Popularity',
|
||||
icon: 'usetime',
|
||||
route: '/administrator/globalAwardPopularity',
|
||||
key: 'sub15',
|
||||
isShow: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -346,6 +346,7 @@ export const Https = {
|
||||
switchSubscribePlan: '/api/subscription_plan/switchSubscriptionPlan', // 切换管理员订阅计划
|
||||
switchSubAccountSubscribePlan:
|
||||
'/api/subscription_plan/switchSubAccSubscriptionPlan', // 切换子账号订阅计划
|
||||
getGlobalAwardPopularity: '/api/global-award/page/visit/count', // 获取global award流量
|
||||
|
||||
//云生成
|
||||
designCloud: `/api/design/designCloud`, //创建云生成
|
||||
|
||||
@@ -272,12 +272,12 @@ const navTypeList = (t)=>{
|
||||
// },
|
||||
|
||||
|
||||
{
|
||||
icon:'fi fi-rr-puzzle-alt',
|
||||
value:'deReconstruction',
|
||||
label:t('Header.toolsDeReconstruction'),
|
||||
router:'tools=deReconstruction'
|
||||
},
|
||||
// {
|
||||
// icon:'fi fi-rr-puzzle-alt',
|
||||
// value:'deReconstruction',
|
||||
// label:t('Header.toolsDeReconstruction'),
|
||||
// router:'tools=deReconstruction'
|
||||
// },
|
||||
{
|
||||
icon:'fi fi-ss-box-open',
|
||||
value:'toProduct',
|
||||
@@ -294,18 +294,18 @@ const navTypeList = (t)=>{
|
||||
label:t('Header.toolsToTransferPose'),
|
||||
router:'tools=poseTransfer'
|
||||
},
|
||||
{
|
||||
icon:'fi fi-rr-cubes',
|
||||
value:'patternMaking3D',
|
||||
label:t('Header.toolsPatternMaking'),
|
||||
router:'tools=patternMaking3D'
|
||||
},
|
||||
{
|
||||
icon:'fi fi-rr-pen-swirl',
|
||||
value:'canvasUpload',
|
||||
label:t('Header.toolsCanvas'),
|
||||
router:'tools=canvasUpload'
|
||||
},
|
||||
// {
|
||||
// icon:'fi fi-rr-cubes',
|
||||
// value:'patternMaking3D',
|
||||
// label:t('Header.toolsPatternMaking'),
|
||||
// router:'tools=patternMaking3D'
|
||||
// },
|
||||
// {
|
||||
// icon:'fi fi-rr-pen-swirl',
|
||||
// value:'canvasUpload',
|
||||
// label:t('Header.toolsCanvas'),
|
||||
// router:'tools=canvasUpload'
|
||||
// },
|
||||
]
|
||||
},
|
||||
library:{
|
||||
@@ -340,12 +340,12 @@ const navTypeList = (t)=>{
|
||||
value:'Models',
|
||||
router:'library=Models'
|
||||
},
|
||||
{
|
||||
icon:'fi-ss-gem',
|
||||
label:t('LibraryPage.brandDNA'),
|
||||
value:'MyBrand',
|
||||
router:'library=MyBrand'
|
||||
},
|
||||
// {
|
||||
// icon:'fi-ss-gem',
|
||||
// label:t('LibraryPage.brandDNA'),
|
||||
// value:'MyBrand',
|
||||
// router:'library=MyBrand'
|
||||
// },
|
||||
]
|
||||
},
|
||||
// history:{
|
||||
|
||||
@@ -672,6 +672,17 @@ function sketchToMask(sketchImage) {
|
||||
img.src = sketchImage;
|
||||
});
|
||||
}
|
||||
|
||||
function isValidUrl(string) {
|
||||
try {
|
||||
const url = new URL(string)
|
||||
// 通常我们只需要 http 或 https 协议
|
||||
return url.protocol === "http:" || url.protocol === "https:"
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
isEmail,
|
||||
getUploadUrl,
|
||||
@@ -695,5 +706,6 @@ export {
|
||||
calculateGradientCoordinate,
|
||||
segmentImage,
|
||||
UrlToFile,
|
||||
sketchToMask
|
||||
sketchToMask,
|
||||
isValidUrl
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,13 +8,13 @@
|
||||
class="title animation-element"
|
||||
ref="applyTitleRef"
|
||||
>
|
||||
How to Apply
|
||||
{{ $t('AwardsPage.howToApply') }}
|
||||
</div>
|
||||
<div
|
||||
class="sub-title animation-element"
|
||||
ref="applySubTitleRef"
|
||||
>
|
||||
Step by step
|
||||
{{ $t('AwardsPage.stepByStep') }}
|
||||
</div>
|
||||
<div
|
||||
class="requirments-list flex flex-col"
|
||||
@@ -29,26 +29,26 @@
|
||||
:style="{ background: item.background || '#fff' }"
|
||||
>
|
||||
<div class="item-header flex flex-center">
|
||||
<div class="item-title">{{ item.type }}</div>
|
||||
<div class="item-title">{{ $t(item.type) }}</div>
|
||||
</div>
|
||||
<div class="context-container flex flex-center">
|
||||
<div
|
||||
class="context"
|
||||
v-for="el in item.desc"
|
||||
>
|
||||
{{ el }}
|
||||
{{ $t(el) }}
|
||||
</div>
|
||||
<div
|
||||
class="list"
|
||||
v-if="item.listTitle"
|
||||
>
|
||||
<div class="list-title">{{ item.listTitle }}</div>
|
||||
<div class="list-title">{{ $t(item.listTitle) }}</div>
|
||||
<ul class="list-items">
|
||||
<li
|
||||
class="list-item"
|
||||
v-for="el in item.list"
|
||||
>
|
||||
{{ el }}
|
||||
{{ $t(el) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -57,43 +57,36 @@
|
||||
</div>
|
||||
<div class="bottom flex">
|
||||
<div class="step-3 flex flex-col animation-element" ref="step3Ref">
|
||||
<div class="header">Step 3. Prepare Your Submission</div>
|
||||
<div class="header">{{ $t('AwardsPage.step3Title') }}</div>
|
||||
<div class="content flex">
|
||||
<div class="content-left flex flex-col space-between">
|
||||
<div class="content-item">
|
||||
<div class="item-header flex align-center">
|
||||
<div class="point"></div>
|
||||
<div>Process Video</div>
|
||||
<div>{{ $t('AwardsPage.processVideo') }}</div>
|
||||
</div>
|
||||
<div class="desc-wrapper flex flex-col space-between">
|
||||
<div class="item-desc">
|
||||
Include a screen‑recorded video
|
||||
<br />
|
||||
your creative process
|
||||
<br />
|
||||
using AiDA.
|
||||
<br />
|
||||
{{ $t('AwardsPage.processVideoDesc') }}
|
||||
</div>
|
||||
<ul class="desc-lists">
|
||||
<div class="desc-lists-title">
|
||||
Video requirements:
|
||||
{{ $t('AwardsPage.videoRequirements') }}
|
||||
</div>
|
||||
<li>Format: MP4</li>
|
||||
<li>Resolution: 1080×1920 px</li>
|
||||
<li>Duration: Maximum 1 minute</li>
|
||||
<li>File size: Maximum 20MB</li>
|
||||
<li>{{ $t('AwardsPage.videoFormat') }}</li>
|
||||
<li>{{ $t('AwardsPage.videoResolution') }}</li>
|
||||
<li>{{ $t('AwardsPage.videoDuration') }}</li>
|
||||
<li>{{ $t('AwardsPage.videoSize') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-header flex align-center">
|
||||
<div class="point"></div>
|
||||
<div>File Name</div>
|
||||
<div>{{ $t('AwardsPage.fileName') }}</div>
|
||||
</div>
|
||||
<div class="item-desc indent">
|
||||
AiDAGlobalDesignAward
|
||||
<br />
|
||||
2026_[Your Full Name]
|
||||
{{ $t('AwardsPage.fileNameDesc') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -101,7 +94,7 @@
|
||||
<div class="content-item flex flex-col">
|
||||
<div class="item-header flex align-center">
|
||||
<div class="point"></div>
|
||||
<div>Design Portfolio(PDF)</div>
|
||||
<div>{{ $t('AwardsPage.designPortfolio') }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="desc-wrapper flex-1 flex flex-col space-between"
|
||||
@@ -109,25 +102,23 @@
|
||||
<ul class="desc-lists">
|
||||
<div class="desc-lists-title">
|
||||
<p>
|
||||
Submit one single PDF file that includes:
|
||||
{{ $t('AwardsPage.submitPdf') }}
|
||||
</p>
|
||||
<p>Required structure:</p>
|
||||
<p>{{ $t('AwardsPage.requiredStructure') }}</p>
|
||||
</div>
|
||||
<li>Design title</li>
|
||||
<li>Moodboard</li>
|
||||
<li>Concept explanation</li>
|
||||
<div>(How to used AiDA to develop design)</div>
|
||||
<li>{{ $t('AwardsPage.pdfDesignTitle') }}</li>
|
||||
<li>{{ $t('AwardsPage.pdfMoodboard') }}</li>
|
||||
<li>{{ $t('AwardsPage.pdfConcept') }}</li>
|
||||
<div>{{ $t('AwardsPage.pdfConceptDesc') }}</div>
|
||||
</ul>
|
||||
<ul class="desc-lists">
|
||||
<div class="desc-lists-title">
|
||||
<p>PDF requirements:</p>
|
||||
<p>{{ $t('AwardsPage.pdfRequirements') }}</p>
|
||||
</div>
|
||||
<li>Maximum 15 pages</li>
|
||||
<li>Maximum file size: 20MB</li>
|
||||
<li>{{ $t('AwardsPage.pdfMaxPages') }}</li>
|
||||
<li>{{ $t('AwardsPage.pdfMaxSize') }}</li>
|
||||
<li>
|
||||
Language: English or native language
|
||||
<br />
|
||||
with English translation
|
||||
{{ $t('AwardsPage.pdfLanguage') }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -137,31 +128,22 @@
|
||||
</div>
|
||||
<div class="step-4 animation-element" ref="step4Ref">
|
||||
<div class="header flex flex-col flex-center">
|
||||
<p>Step 4. Finalist Requirement</p>
|
||||
<p class="sub-title">(for top 20 Designers)</p>
|
||||
<p>{{ $t('AwardsPage.step4Title') }}</p>
|
||||
<p class="sub-title">{{ $t('AwardsPage.step4Subtitle') }}</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-item">
|
||||
<div class="desc-wrapper flex-1 flex flex-col space-between">
|
||||
<ul class="desc-lists">
|
||||
<div class="desc-lists-title">
|
||||
The 20 finalists will be required to
|
||||
<br />
|
||||
submit physical garments for final
|
||||
<br />
|
||||
evaluation
|
||||
{{ $t('AwardsPage.step4Desc') }}
|
||||
</div>
|
||||
<li>Number of pieces: 1</li>
|
||||
<li>{{ $t('AwardsPage.finalistPieces') }}</li>
|
||||
<li>
|
||||
Garments must be produced
|
||||
<br />
|
||||
based on the submitted
|
||||
<br />
|
||||
AiDA-generated designs
|
||||
{{ $t('AwardsPage.finalistBasedOn') }}
|
||||
</li>
|
||||
<li>
|
||||
Shipping instructions will be provided by
|
||||
Code-create
|
||||
{{ $t('AwardsPage.finalistShipping') }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -175,25 +157,24 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { gsap } from 'gsap'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const leftRequirment = ref([
|
||||
{
|
||||
type: 'Step 1. Become an\nAiDA Subscriber',
|
||||
desc: [
|
||||
'All applicants must be active\nAiDA subscribers at the time of\nsubmission. You may subscribe\nunder either a monthly or yearly plan.'
|
||||
]
|
||||
type: 'AwardsPage.step1Title',
|
||||
desc: ['AwardsPage.step1Desc']
|
||||
},
|
||||
{
|
||||
type: 'Step 2. Create Your Design Using AiDA',
|
||||
desc: [
|
||||
'Applicants must create their\ndesigns exclusively using the\nAiDA platform. '
|
||||
],
|
||||
listTitle: 'Your work shold clearly demonstrate:',
|
||||
type: 'AwardsPage.step2Title',
|
||||
desc: ['AwardsPage.step2Desc'],
|
||||
listTitle: 'AwardsPage.step2ListTitle',
|
||||
list: [
|
||||
'· How AiDA is used as a creative tool',
|
||||
'· Your design concept and creative direction',
|
||||
'· The intergration of AI and human creativity'
|
||||
'AwardsPage.step2List[0]',
|
||||
'AwardsPage.step2List[1]',
|
||||
'AwardsPage.step2List[2]'
|
||||
],
|
||||
background: '#F9F9F9'
|
||||
}
|
||||
|
||||
@@ -4,46 +4,44 @@
|
||||
class="title"
|
||||
ref="titleRef"
|
||||
>
|
||||
Bloom Your Creativity
|
||||
{{ $t('AwardsPage.bloomYourCreativity') }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="season"
|
||||
ref="subtitleRef"
|
||||
>
|
||||
Theme of 2026
|
||||
{{ $t('AwardsPage.themeOf2026') }}
|
||||
</div>
|
||||
<div
|
||||
class="desc"
|
||||
ref="textRef"
|
||||
>
|
||||
<p class="section-1">
|
||||
The
|
||||
<span class="arial-bold">AiDA Global Design Award 2026</span>
|
||||
is an
|
||||
<span class="arial-bold">international design competition</span>
|
||||
hosted by
|
||||
<span class="arial-bold">Code‑Create</span>
|
||||
, a globally leading
|
||||
<br />
|
||||
<span class="arial-bold">AI fashion solutions provider,</span>
|
||||
celebrating the future of creativity powered by artificial intelligence.
|
||||
<br />
|
||||
Bringing together designers from around the world, AiDA empowers AI as a
|
||||
creative partner—pushing fashion beyond
|
||||
<br />
|
||||
traditional boundaries and unlocking new possibilities where technology
|
||||
amplifies human imagination.
|
||||
{{ $t('AwardsPage.bloomText.desc1.regular1') }}
|
||||
<span class="arial-bold">
|
||||
{{ $t('AwardsPage.bloomText.desc1.bold1') }}
|
||||
</span>
|
||||
{{ $t('AwardsPage.bloomText.desc1.regular2') }}
|
||||
<span class="arial-bold">
|
||||
{{ $t('AwardsPage.bloomText.desc1.bold2') }}
|
||||
</span>
|
||||
{{ $t('AwardsPage.bloomText.desc1.regular3') }}
|
||||
<span class="arial-bold">
|
||||
{{ $t('AwardsPage.bloomText.desc1.bold3') }}
|
||||
</span>
|
||||
{{ $t('AwardsPage.bloomText.desc1.regular4') }}
|
||||
<span class="arial-bold">
|
||||
{{ $t('AwardsPage.bloomText.desc1.bold4') }}
|
||||
</span>
|
||||
{{ $t('AwardsPage.bloomText.desc1.regular5') }}
|
||||
</p>
|
||||
<p class="section-2">
|
||||
Under the theme “
|
||||
{{ $t('AwardsPage.bloomText.desc2.regular1') }}
|
||||
<span class="arial-bold">
|
||||
Where Imagination Meets Innovation, Creativity Blooms,
|
||||
{{ $t('AwardsPage.bloomText.desc2.bold1') }}
|
||||
</span>
|
||||
” participants are invited to transform bold ideas
|
||||
<br />
|
||||
into extraordinary designs, seamlessly merging human artistry with
|
||||
artificial intelligence to shape the next era of fashion.
|
||||
{{ $t('AwardsPage.bloomText.desc2.regular2') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -51,8 +49,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { gsap } from 'gsap'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const titleRef = ref<HTMLElement | null>(null)
|
||||
const subtitleRef = ref<HTMLElement | null>(null)
|
||||
const textRef = ref<HTMLElement | null>(null)
|
||||
@@ -192,7 +193,8 @@
|
||||
padding: 0 21.5rem;
|
||||
line-height: 4.5rem;
|
||||
margin-bottom: 12.3rem;
|
||||
.section-2{
|
||||
white-space: pre-line;
|
||||
.section-2 {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="judges-container flex flex-col align-center">
|
||||
<div class="title" ref="judgesTitleRef">Panel of Judges</div>
|
||||
<div class="title" ref="judgesTitleRef">{{ $t('AwardsPage.panelOfJudges') }}</div>
|
||||
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
|
||||
<div class="sub-title" ref="judgesSubTitleRef">Expertise</div>
|
||||
<div class="sub-title" ref="judgesSubTitleRef">{{ $t('AwardsPage.expertise') }}</div>
|
||||
<div class="judgement-list" ref="judgementListRef">
|
||||
<div
|
||||
class="judgement-item flex flex-col align-center"
|
||||
@@ -10,8 +10,8 @@
|
||||
:key="item.name"
|
||||
>
|
||||
<img :src="item.picture" class="picture" />
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div class="desc">{{ item.desc }}</div>
|
||||
<div class="name">{{ $t(item.name) }}</div>
|
||||
<div class="desc">{{ $t(item.desc) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, onMounted, nextTick, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { gsap } from 'gsap'
|
||||
import jae from '@/assets/images/award/jae.png'
|
||||
import diego from '@/assets/images/award/diego.png'
|
||||
@@ -27,36 +28,38 @@ import vincenzo from '@/assets/images/award/vincenzo.png'
|
||||
import tim from '@/assets/images/award/tim.png'
|
||||
import desmond from '@/assets/images/award/desmond.png'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const judgements = [
|
||||
{
|
||||
picture: jae,
|
||||
name: 'Jae Hyuk Lim',
|
||||
desc: 'Code-create\nKorea Branch Director\nBesfxxk creative director'
|
||||
desc: 'AwardsPage.judgesHat.jae'
|
||||
},
|
||||
{
|
||||
picture: diego,
|
||||
name: 'Diego Dultzin Lacoste',
|
||||
desc: 'Co-founder & Chief Father\nOfficer of OnTheList\n(Hong Kong)'
|
||||
desc: 'AwardsPage.judgesHat.diego'
|
||||
},
|
||||
{
|
||||
picture: gregory,
|
||||
name: 'Gregory de la Hogue Moran',
|
||||
desc: 'Senior Designer at\nGabriela Heasrst (Italy)'
|
||||
desc: 'AwardsPage.judgesHat.gregory'
|
||||
},
|
||||
{
|
||||
picture: vincenzo,
|
||||
name: 'Vincenzo La Torre',
|
||||
desc: 'Cheif Editor of SCMP Style\n(Hong Kong)'
|
||||
desc: 'AwardsPage.judgesHat.vincenzo'
|
||||
},
|
||||
{
|
||||
picture: tim,
|
||||
name: 'Tim Lim',
|
||||
desc: 'Group Fashion Direction of\n Modern Media Group\n(Shanghai)'
|
||||
desc: 'AwardsPage.judgesHat.tim'
|
||||
},
|
||||
{
|
||||
picture: desmond,
|
||||
name: 'Desmond Lim',
|
||||
desc: 'Cheif Editor of Vogue\n(Singapore)'
|
||||
desc: 'AwardsPage.judgesHat.desmond'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -199,6 +202,9 @@ onBeforeUnmount(() => {
|
||||
column-gap: 23.22rem;
|
||||
row-gap: 8rem;
|
||||
padding: 0 25rem 0 26.6rem;
|
||||
div{
|
||||
text-align: center;
|
||||
}
|
||||
.judgement-item {
|
||||
overflow: hidden;
|
||||
.picture {
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
class="title"
|
||||
ref="prizesTitleRef"
|
||||
>
|
||||
Award & Prizes
|
||||
{{ $t('AwardsPage.awardPrizes') }}
|
||||
</div>
|
||||
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
|
||||
<div
|
||||
class="desc"
|
||||
ref="prizesSubTitleRef"
|
||||
>
|
||||
Recongnition
|
||||
{{ $t('AwardsPage.recognition') }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -29,15 +29,15 @@
|
||||
:key="item.name"
|
||||
>
|
||||
<div class="prize-money">
|
||||
{{ item.money }}
|
||||
{{ $t(item.money) }}
|
||||
</div>
|
||||
<div class="prize-name">{{ item.name }}</div>
|
||||
<div class="prize-name">{{ $t(item.name) }}</div>
|
||||
<div class="prize-desc flex flex-col flex-center">
|
||||
<div
|
||||
class="desc-item"
|
||||
v-for="el in item.desc"
|
||||
>
|
||||
{{ el }}
|
||||
{{ $t(el) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,29 +47,51 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { gsap } from 'gsap'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
isZh: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const prizes = [
|
||||
{
|
||||
money: 'US$5000',
|
||||
name: 'Grand Awards',
|
||||
desc: ['Cash Award', 'Award Ceritificate', 'Global Media Exposure']
|
||||
money: 'AwardsPage.grandMoney',
|
||||
name: 'AwardsPage.grandAwards',
|
||||
desc: [
|
||||
'AwardsPage.cashAward',
|
||||
'AwardsPage.awardCertificate',
|
||||
'AwardsPage.globalMediaExposure'
|
||||
]
|
||||
},
|
||||
{
|
||||
money: 'US$3000',
|
||||
name: 'Gold Awards',
|
||||
desc: ['Cash Award', 'Award Ceritificate', 'Global Media Exposure']
|
||||
money: 'AwardsPage.goldMoney',
|
||||
name: 'AwardsPage.goldAwards',
|
||||
desc: [
|
||||
'AwardsPage.cashAward',
|
||||
'AwardsPage.awardCertificate',
|
||||
'AwardsPage.globalMediaExposure'
|
||||
]
|
||||
},
|
||||
{
|
||||
money: 'US$2000',
|
||||
name: 'Silver Awards',
|
||||
desc: ['Cash Award', 'Award Ceritificate', 'Global Media Exposure']
|
||||
money: 'AwardsPage.silverMoney',
|
||||
name: 'AwardsPage.silverAwards',
|
||||
desc: [
|
||||
'AwardsPage.cashAward',
|
||||
'AwardsPage.awardCertificate',
|
||||
'AwardsPage.globalMediaExposure'
|
||||
]
|
||||
},
|
||||
{
|
||||
money: 'Award\nCertification',
|
||||
name: 'Finalists',
|
||||
desc: ['Award Ceritificate', 'Global Media Exposure'],
|
||||
smaller: true
|
||||
money: 'AwardsPage.awardCertification',
|
||||
name: 'AwardsPage.finalists',
|
||||
desc: ['AwardsPage.TravelAllowance', 'AwardsPage.globalMediaExposure'],
|
||||
smaller: !props.isZh
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
class="selection-container container flex flex-col align-center"
|
||||
ref="selectionRef"
|
||||
>
|
||||
<div class="title">Selection Criteria</div>
|
||||
<div class="title">{{ $t('AwardsPage.selectionCriteria') }}</div>
|
||||
<!-- <img src="@/assets/images/award/bloom_logo.png" class="logo" /> -->
|
||||
<div class="sub-title">Evaluation</div>
|
||||
<div class="sub-title">{{ $t('AwardsPage.evaluation') }}</div>
|
||||
<div class="criteria-list flex" ref="criteriaListRef">
|
||||
<div
|
||||
class="item flex flex-col align-center"
|
||||
@@ -13,8 +13,8 @@
|
||||
:key="item.name"
|
||||
>
|
||||
<img :src="item.icon" class="icon" :style="item.style" />
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div class="desc">{{ item.desc }}</div>
|
||||
<div class="name">{{ $t(item.name) }}</div>
|
||||
<div class="desc">{{ $t(item.desc) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -22,35 +22,38 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { gsap } from 'gsap'
|
||||
import criteria1 from '@/assets/images/award/criteria_1.png'
|
||||
import criteria2 from '@/assets/images/award/criteria_2.png'
|
||||
import criteria3 from '@/assets/images/award/criteria_3.png'
|
||||
import criteria4 from '@/assets/images/award/criteria_4.png'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const criteriaList = ref([
|
||||
{
|
||||
icon: criteria1,
|
||||
name: 'Originality',
|
||||
desc: 'Unique perspective and\ninnovative approach to\nfashion design',
|
||||
name: 'AwardsPage.originality',
|
||||
desc: 'AwardsPage.originalityDesc',
|
||||
style: { width: '13rem', height: '17rem' }
|
||||
},
|
||||
{
|
||||
icon: criteria2,
|
||||
name: 'Creativity',
|
||||
desc: 'Artistic vision and exceptional\ndesign excellence',
|
||||
name: 'AwardsPage.creativity',
|
||||
desc: 'AwardsPage.creativityDesc',
|
||||
style: { width: '16rem', height: '18rem' }
|
||||
},
|
||||
{
|
||||
icon: criteria3,
|
||||
name: 'AiDA Integration',
|
||||
desc: 'Effective application of\nAiDA functions',
|
||||
name: 'AwardsPage.aidaIntegration',
|
||||
desc: 'AwardsPage.aidaIntegrationDesc',
|
||||
style: { width: '16rem', height: '18rem' }
|
||||
},
|
||||
{
|
||||
icon: criteria4,
|
||||
name: 'Execution',
|
||||
desc: 'Quality of presentation and\ntechnical craftsmanship',
|
||||
name: 'AwardsPage.execution',
|
||||
desc: 'AwardsPage.executionDesc',
|
||||
style: { width: '18.8rem', height: '18rem' }
|
||||
}
|
||||
])
|
||||
|
||||
@@ -10,32 +10,35 @@
|
||||
:key="item.number"
|
||||
:style="{ '--delay': `${idx * 0.18}s` }"
|
||||
>
|
||||
<div class="number">{{ item.number }}</div>
|
||||
<div class="label">{{ item.label }}</div>
|
||||
<div class="number">{{ $t(item.number) }}</div>
|
||||
<div class="label">{{ $t(item.label) }}</div>
|
||||
<div class="line"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { computed, ref, onMounted, onUnmounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const blocksList = ref([
|
||||
{
|
||||
number: 'UP TO\nUS$9000',
|
||||
label: 'In total cash prizes'
|
||||
number: 'AwardsPage.totalCashPrizes',
|
||||
label: 'AwardsPage.totalCashPrizesLabel'
|
||||
},
|
||||
{
|
||||
number: 'GLOBAL MEDIA EXPOSE',
|
||||
label: 'Showcased by top\ninternational media platforms'
|
||||
number: 'AwardsPage.globalMediaExpose',
|
||||
label: 'AwardsPage.globalMediaExposeLabel'
|
||||
},
|
||||
{
|
||||
number: 'NETWORKING\n OPPORTUNITIES',
|
||||
label: 'Build connections with\ndesigners and industry leaders'
|
||||
number: 'AwardsPage.networkingOpportunities',
|
||||
label: 'AwardsPage.networkingOpportunitiesLabel'
|
||||
},
|
||||
{
|
||||
number: 'AWARD CEREMONY\nIN HONG KONG',
|
||||
label: 'Travel allowance\nprovided for finalists'
|
||||
number: 'AwardsPage.awardCeremonyHongKong',
|
||||
label: 'AwardsPage.awardCeremonyLabel'
|
||||
}
|
||||
])
|
||||
const root = ref<HTMLElement | null>(null)
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
alt=""
|
||||
class="icon-img"
|
||||
/>
|
||||
<div class="title">{{ info.title }}</div>
|
||||
<div class="title">{{ $t(info.title) }}</div>
|
||||
<div class="desc">
|
||||
{{ info.desc }}
|
||||
{{ $t(info.desc) }}
|
||||
<!-- <div>
|
||||
Please review your submitted information in the AiDA in-platform message.
|
||||
</div>
|
||||
@@ -21,8 +21,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import successIcon from '@/assets/images/award/successful.png'
|
||||
import expiredIcon from '@/assets/images/award/expired.png'
|
||||
|
||||
const { t } = useI18n()
|
||||
const props = defineProps({
|
||||
isExpired: {
|
||||
type: Boolean,
|
||||
@@ -34,14 +37,14 @@
|
||||
if (props.isExpired) {
|
||||
return {
|
||||
icon: expiredIcon,
|
||||
title: 'Application Deadline Passed',
|
||||
desc: 'The submission deadline for AiDA Global Fashion Award 2026 has ended.\nWe are no longer accepting new applications. '
|
||||
title: 'AwardsPage.deadlinePassed',
|
||||
desc: 'AwardsPage.deadlinePassedDesc'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
icon: successIcon,
|
||||
title: 'Submission Successful',
|
||||
desc: 'Please review your submitted information in the AiDA in-platform message.\nYou may edit it if needed. Competition updates and results will be sent via email.'
|
||||
title: 'AwardsPage.submissionSuccessful',
|
||||
desc: 'AwardsPage.submissionSuccessfulDesc'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
ref="containerRef"
|
||||
class="timeline-container container flex flex-col align-center"
|
||||
>
|
||||
<div class="timeline-title">Competition Timeline</div>
|
||||
<div class="desc">Shaping the Future</div>
|
||||
<div class="timeline-title">{{ $t('AwardsPage.competitionTimeline') }}</div>
|
||||
<div class="desc">{{ $t('AwardsPage.shapingTheFuture') }}</div>
|
||||
<div
|
||||
class="timeline-point"
|
||||
ref="timelineRef"
|
||||
@@ -16,12 +16,12 @@
|
||||
v-for="item in points"
|
||||
:key="'label-' + item.time"
|
||||
>
|
||||
<div class="main-label">{{ item.label }}</div>
|
||||
<div class="main-label">{{ $t(item.label) }}</div>
|
||||
<div
|
||||
class="sub-label"
|
||||
v-if="item.subLabel"
|
||||
>
|
||||
{{ item.subLabel }}
|
||||
{{ $t(item.subLabel) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,7 +46,7 @@
|
||||
v-for="item in points"
|
||||
:key="'time-' + item.time"
|
||||
>
|
||||
{{ item.time }}
|
||||
{{ $t(item.time) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
:key="'desc-' + item.time"
|
||||
>
|
||||
<div class="txt">
|
||||
{{ item.desc }}
|
||||
{{ $t(item.desc) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -67,43 +67,46 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { nextTick, onBeforeUnmount, onMounted, ref, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { gsap } from 'gsap'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
const timelineRef = ref<HTMLElement | null>(null)
|
||||
const hasAnimated = ref(false)
|
||||
|
||||
const points = ref([
|
||||
{
|
||||
label: 'Application',
|
||||
subLabel: 'Deadline',
|
||||
time: 'Jul 15',
|
||||
desc: 'Application deadline and\nentry review process\nbegins.'
|
||||
label: 'AwardsPage.timelineApplicationLabel',
|
||||
subLabel: 'AwardsPage.timelineDeadlineLabel',
|
||||
time: 'AwardsPage.timeJul15',
|
||||
desc: 'AwardsPage.applicationDeadlineDesc'
|
||||
},
|
||||
{
|
||||
label: `20 Finallists`,
|
||||
subLabel: 'Announced',
|
||||
time: 'Aug 30',
|
||||
desc: 'Announcement of 20\nfinalists entering final\nevaluation stage.'
|
||||
label: 'AwardsPage.twentyFinalistsAnnounced',
|
||||
subLabel: 'AwardsPage.announcedLabel',
|
||||
time: 'AwardsPage.timeAug30',
|
||||
desc: 'AwardsPage.twentyFinalistsDesc'
|
||||
},
|
||||
{
|
||||
label: `Finallist\nSubmission`,
|
||||
subLabel: 'Deadline',
|
||||
time: 'Sept 30',
|
||||
desc: 'Finalists submit\ncompleted outfits for\nfinal assessment.'
|
||||
label: 'AwardsPage.finalistSubmission',
|
||||
subLabel: 'AwardsPage.submissionLabel',
|
||||
time: 'AwardsPage.timeSept30',
|
||||
desc: 'AwardsPage.finalistSubmissionDesc'
|
||||
},
|
||||
{
|
||||
label: 'Receiving Outfits',
|
||||
subLabel: 'from Finallists',
|
||||
time: 'October',
|
||||
desc: 'AiDA receives physical\noutfits from all 20\nfinalists.'
|
||||
label: 'AwardsPage.receivingOutfits',
|
||||
subLabel: 'AwardsPage.fromFinalistsLabel',
|
||||
time: 'AwardsPage.timeOctober',
|
||||
desc: 'AwardsPage.receivingOutfitsDesc'
|
||||
},
|
||||
{
|
||||
label: 'Award',
|
||||
subLabel: 'Ceremony',
|
||||
time: 'Nov 12',
|
||||
desc: 'Award Ceremony &\nCommunity Gathering\n– Soho House.'
|
||||
label: 'AwardsPage.awardCeremony',
|
||||
subLabel: 'AwardsPage.ceremonyLabel',
|
||||
time: 'AwardsPage.timeNov12',
|
||||
desc: 'AwardsPage.awardCeremonyDesc'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
class="progress-icon successful-icon"
|
||||
/>
|
||||
</div>
|
||||
<div class="text">{{ text }}</div>
|
||||
<div class="tips">{{ tips }}</div>
|
||||
<div class="text">{{ $t(text) }}</div>
|
||||
<div class="tips">{{ $t(tips) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
const props = defineProps<{
|
||||
status: string
|
||||
type: 'pdf' | 'video'
|
||||
@@ -29,16 +32,16 @@
|
||||
|
||||
const textMap: Record<string, string> = {
|
||||
idle: '',
|
||||
uploading: 'Upload in progress…',
|
||||
success: 'Uploaded Successfully',
|
||||
error: 'Upload failed'
|
||||
uploading: 'AwardsPage.uploadInProgress',
|
||||
success:'AwardsPage.uploadSuccess',
|
||||
error: 'AwardsPage.fileUploadFailed'
|
||||
}
|
||||
|
||||
const tips = computed(() => {
|
||||
if (props.type === 'pdf') {
|
||||
return 'PDF file, max 20MB'
|
||||
return 'AwardsPage.pdfFileTip'
|
||||
} else if (props.type === 'video') {
|
||||
return 'Video file (MP4, MOV), 1080p, max 100MB'
|
||||
return 'AwardsPage.videoFileTip'
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
@@ -83,23 +83,39 @@
|
||||
class="close-icon"
|
||||
@click="handleCloseQRcode"
|
||||
/>
|
||||
<div class="code-title">WeChat Official Account</div>
|
||||
<div class="code-title">{{ $t('AwardsPage.wechatTitle') }}</div>
|
||||
<img
|
||||
src="@/assets/images/award/qrcode.jpg"
|
||||
class="qrcode"
|
||||
/>
|
||||
<div class="tips">Scan the QR code in WeChat</div>
|
||||
<div class="tips">{{ $t('AwardsPage.wechatDesc') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { getCookie } from '@/tool/cookie'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { locale } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
// 初始化语言设置
|
||||
const loginLanguage = localStorage.getItem('loginLanguage')
|
||||
if (loginLanguage) {
|
||||
locale.value = loginLanguage
|
||||
} else {
|
||||
const userLanguage = getCookie('language')
|
||||
if (userLanguage) {
|
||||
locale.value = userLanguage
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const showQRcode = ref(false)
|
||||
const handleCloseQRcode = () => {
|
||||
@@ -110,10 +126,10 @@
|
||||
const btnType = ref<BtnType>('index')
|
||||
const btnText = computed(() => {
|
||||
if (btnType.value === 'index') {
|
||||
return 'Submit your Application'
|
||||
return locale.value === 'CHINESE_SIMPLIFIED' ? '提交申请' : 'Submit your Application'
|
||||
}
|
||||
if (btnType.value === 'form') {
|
||||
return 'Back to Introduction'
|
||||
return locale.value === 'CHINESE_SIMPLIFIED' ? '赛事介绍' : 'Back to Introduction'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<template>
|
||||
<div class="award-page">
|
||||
<div
|
||||
class="award-page"
|
||||
:class="{ 'is-zh': isZh }"
|
||||
>
|
||||
<div class="banner">
|
||||
<video
|
||||
src="@/assets/images/award/banner.mp4"
|
||||
:src="bannerUrl"
|
||||
autoplay
|
||||
muted
|
||||
loop
|
||||
@@ -15,13 +18,13 @@
|
||||
class="submit-btn flex flex-center"
|
||||
@click="handleSubmitApplication"
|
||||
>
|
||||
<div>Submit your Application</div>
|
||||
<div>{{ $t('AwardsPage.submitApplication') }}</div>
|
||||
<img
|
||||
src="@/assets/images/award/arrow_right.png"
|
||||
alt=""
|
||||
class="arrow"
|
||||
/>
|
||||
<div class="ddl">Application Deadline:15th March 2026</div>
|
||||
<div class="ddl">{{ $t('AwardsPage.applicationDeadline') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,14 +32,15 @@
|
||||
<Bloom />
|
||||
<TimeLine />
|
||||
<JudgesSection />
|
||||
<PrizesSection />
|
||||
<PrizesSection :is-zh="isZh" />
|
||||
<ApplySection />
|
||||
<SelectionSection />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import JudgesSection from './components/JudgesSection.vue'
|
||||
import SelectionSection from './components/SelectionSection.vue'
|
||||
@@ -46,7 +50,19 @@
|
||||
import Bloom from './components/Bloom.vue'
|
||||
import Slogan from './components/Slogan.vue'
|
||||
|
||||
import banner from '@/assets/images/award/banner.mp4'
|
||||
import bannerZh from '@/assets/images/award/banner_chinese.mp4'
|
||||
|
||||
const router = useRouter()
|
||||
const { locale } = useI18n()
|
||||
|
||||
const isZh = computed(() => {
|
||||
return locale.value === 'CHINESE_SIMPLIFIED'
|
||||
})
|
||||
|
||||
const bannerUrl = computed(() => {
|
||||
return isZh.value ? bannerZh : banner
|
||||
})
|
||||
|
||||
const handleSubmitApplication = () => {
|
||||
router.push('/award/contestants')
|
||||
@@ -102,12 +118,26 @@
|
||||
left: 0;
|
||||
text-align: center;
|
||||
width: 41rem;
|
||||
font-family: 'Arial';
|
||||
font-weight: 400;
|
||||
font-family: 'ArialBold';
|
||||
font-weight: 700;
|
||||
font-size: 2rem;
|
||||
line-height: 2.2rem;
|
||||
color: #232323e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-zh {
|
||||
.submit-btn {
|
||||
padding: 0 7.5rem;
|
||||
height: 7.8rem;
|
||||
border-radius: 7.74rem;
|
||||
column-gap: 3.8rem;
|
||||
// justify-content: space-between;
|
||||
&,
|
||||
.ddl {
|
||||
width: 35.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -400,7 +400,7 @@
|
||||
<a href="https://www.facebook.com/CodeCreateAI" target="_blank" >
|
||||
<img src="@/assets/images/socialMediaLogo/faceBookIcon.svg" alt="">
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@AiDA-3.1" target="_blank" >
|
||||
<a href="https://www.youtube.com/@Code-Create_AiDA" target="_blank" >
|
||||
<img src="@/assets/images/socialMediaLogo/socialIcons.svg" alt="">
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/company/code-create-limited" target="_blank" >
|
||||
|
||||
@@ -62,7 +62,7 @@ import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { setLang } from '@/tool/guide'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { gsap, TweenMax } from 'gsap'
|
||||
import { ScrollTrigger } from 'gsap/ScrollTrigger'
|
||||
export default defineComponent({
|
||||
@@ -71,6 +71,7 @@ export default defineComponent({
|
||||
const {t, locale} = useI18n()
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
let registerModel = ref()
|
||||
let data = reactive({})
|
||||
|
||||
@@ -117,7 +118,14 @@ export default defineComponent({
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', updataIsMoblie)
|
||||
// 初始化语言设置
|
||||
const savedLang = localStorage.getItem('loginLanguage')
|
||||
let savedLang = localStorage.getItem('loginLanguage')
|
||||
if(route?.params?.lang == 'cn'){
|
||||
savedLang = 'CHINESE_SIMPLIFIED'
|
||||
localStorage.setItem('loginLanguage', savedLang)
|
||||
}{
|
||||
savedLang = 'ENGLISH'
|
||||
localStorage.setItem('loginLanguage', savedLang)
|
||||
}
|
||||
if (savedLang) {
|
||||
isChinese.value = savedLang === 'CHINESE_SIMPLIFIED'
|
||||
locale.value = savedLang
|
||||
|
||||
@@ -1721,9 +1721,8 @@ export default defineComponent({
|
||||
sloganText = this.captionGeneration
|
||||
if(this.selectCode == "Sketchboard"){
|
||||
level2Type = this.selectGenerateList?.[0]?.categoryValue?this.selectGenerateList[0].categoryValue:''
|
||||
if(this.workspace.styleName){
|
||||
sloganText = `${this.workspace.styleName},${sloganText}`
|
||||
}
|
||||
// sloganText = `${this.workspace.styleName || 'all'},${sloganText}`
|
||||
sloganText = `'all',${sloganText}`
|
||||
}else if(this.selectCode == "Printboard"){
|
||||
level2Type = this.scene?.value
|
||||
if(level2Type == 'Slogan' && this.captionGeneration == ''){
|
||||
|
||||
@@ -85,7 +85,7 @@ import {
|
||||
import { setCookie, getCookie, WriteCookie, clonAllCookie } from '@/tool/cookie'
|
||||
import { Https } from '@/tool/https'
|
||||
import { useStore } from 'vuex'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import signUp from '@/component/mainPage/signUp/index.vue'
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -93,6 +93,7 @@ export default defineComponent({
|
||||
},
|
||||
setup() {
|
||||
const store = useStore()
|
||||
const route = useRoute();
|
||||
const router = useRouter()
|
||||
let data = reactive({
|
||||
homeRecommendMax: null,
|
||||
@@ -148,7 +149,14 @@ export default defineComponent({
|
||||
|
||||
onMounted(() => {
|
||||
updataIsMoblie()
|
||||
const savedLang = localStorage.getItem('loginLanguage')
|
||||
let savedLang = localStorage.getItem('loginLanguage') || 'ENGLISH'
|
||||
if(route?.params?.lang == 'cn'){
|
||||
savedLang = 'CHINESE_SIMPLIFIED'
|
||||
localStorage.setItem('loginLanguage', savedLang)
|
||||
}else if(route?.params?.lang == 'en'){
|
||||
savedLang = 'ENGLISH'
|
||||
localStorage.setItem('loginLanguage', savedLang)
|
||||
}
|
||||
if (savedLang) {
|
||||
data.isSelectSuccessively = savedLang === 'CHINESE_SIMPLIFIED'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user