Compare commits
90 Commits
b04bcb5918
...
dev_vite
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eaa77596e | ||
|
|
848e7b4692 | ||
|
|
fd140ebc56 | ||
|
|
34094c8c92 | ||
|
|
e4dc2bf729 | ||
|
|
7f226179d9 | ||
|
|
3edff6b05c | ||
|
|
6fd1212298 | ||
| e093cccb8d | |||
| b2c6c61515 | |||
| 0219b1a2f4 | |||
| 133433a260 | |||
| 90a59a3dc5 | |||
| c8a65ee2cb | |||
| 226918e941 | |||
|
|
494bfd68ca | ||
|
|
95b70792ba | ||
|
|
a0fffa5896 | ||
|
|
06eaabc742 | ||
|
|
27da4739a6 | ||
| 52576aa0a1 | |||
| 22aa7c37cd | |||
| 752b33f196 | |||
| f3b873b7ae | |||
| 006c2e3f9c | |||
|
|
1f413b36ca | ||
|
|
e7b052f100 | ||
|
|
19bb412470 | ||
|
|
a1e071f7bc | ||
|
|
5388b2df4c | ||
|
|
76e507cae3 | ||
|
|
d4e9462d39 | ||
|
|
4a11d172d2 | ||
|
|
e20092c77f | ||
|
|
5f4656c629 | ||
|
|
14eca9aff2 | ||
|
|
88f0528553 | ||
|
|
afbea289fb | ||
| eb2baa26a7 | |||
|
|
62829395ce | ||
|
|
16532ce44b | ||
|
|
27de720137 | ||
|
|
acf2029efe | ||
|
|
49398aac48 | ||
|
|
b3d9bce440 | ||
|
|
596bc75b83 | ||
|
|
c673948dd3 | ||
|
|
1f8ee2e48e | ||
| e5ae549a3d | |||
| 88c2ae8583 | |||
|
|
f4897e2c92 | ||
| aab96bbe70 | |||
| 4004fa2703 | |||
|
|
4a078186a9 | ||
| fafccf0352 | |||
| 64844105b5 | |||
| d6a07e7fc7 | |||
| 7eff1b0506 | |||
| 2dc98e5dd8 | |||
|
|
3e7a90bd2d | ||
|
|
d42a1bef8d | ||
| 5d184bf1f9 | |||
| 56825fcbb1 | |||
| 7cf37e2da6 | |||
| 59a7c169ad | |||
| fc997a1cce | |||
|
|
8abcdb151d | ||
|
|
55481c6d51 | ||
| ca39910f4c | |||
| 646b48ca6b | |||
| 45f150769e | |||
|
|
7115feb20c | ||
| 00d488cbc2 | |||
| 12233b952b | |||
| 4b8554f41e | |||
| f30a749f65 | |||
|
|
af544d2da8 | ||
| aedd633f8e | |||
| 1e4134f8b9 | |||
|
|
27da8f6680 | ||
|
|
88c66c634f | ||
| 5cfccabcd7 | |||
| 04ad920590 | |||
| 05178c4cb0 | |||
| a385aba49f | |||
|
|
813918eb39 | ||
|
|
f77a2f2e01 | ||
|
|
9dc25ddced | ||
|
|
e453d1efd4 | ||
|
|
78922a5b91 |
5
.env.dev
5
.env.dev
@@ -3,12 +3,13 @@ VITE_USER_NODE_ENV = 'development'
|
|||||||
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
|
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
|
||||||
|
|
||||||
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
|
# VITE_APP_BASE_URL = 'http://18.167.251.121:10086'
|
||||||
VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
|
# VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
|
||||||
|
VITE_APP_BASE_URL = 'http://18.167.251.121:10094'
|
||||||
# VITE_APP_BASE_URL = 'https://www.api.aida.com.hk'
|
# VITE_APP_BASE_URL = 'https://www.api.aida.com.hk'
|
||||||
# 徐佩
|
# 徐佩
|
||||||
# VITE_APP_BASE_URL = 'http://192.168.31.118:5567'
|
# VITE_APP_BASE_URL = 'http://192.168.31.118:5567'
|
||||||
# 李天祥
|
# 李天祥
|
||||||
# VITE_APP_BASE_URL = 'http://192.168.31.82:5567'
|
# VITE_APP_BASE_URL = 'http://192.168.31.82:5567'
|
||||||
VITE_APP_BASE_URL = 'http://192.168.31.82:5569'
|
# VITE_APP_BASE_URL = 'http://192.168.31.82:5569'
|
||||||
# 海波
|
# 海波
|
||||||
# VITE_APP_BASE_URL = 'http://192.168.31.34:5567'
|
# VITE_APP_BASE_URL = 'http://192.168.31.34:5567'
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ VITE_USER_NODE_ENV = 'development_cloud'
|
|||||||
# VITE_APP_BASE_URL = 'https://aida.com.hk/test'
|
# VITE_APP_BASE_URL = 'https://aida.com.hk/test'
|
||||||
# VITE_APP_BASE_URL = 'http://18.167.251.121:10088'
|
# VITE_APP_BASE_URL = 'http://18.167.251.121:10088'
|
||||||
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
|
# VITE_APP_BASE_URL = 'https://api.aida.com.hk'
|
||||||
VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
|
# VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
|
||||||
|
VITE_APP_BASE_URL = 'https://www.develop-ms.api.aida.com.hk'
|
||||||
|
|
||||||
# VITE_APP_BASE_URL = 'http://localhost:22170'
|
# VITE_APP_BASE_URL = 'http://localhost:22170'
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -25,3 +25,5 @@ dist.rar
|
|||||||
.eslintrc-auto-import.json
|
.eslintrc-auto-import.json
|
||||||
components.d.ts
|
components.d.ts
|
||||||
.cursor
|
.cursor
|
||||||
|
*.zip
|
||||||
|
*.7z
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/** @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',
|
|
||||||
};
|
|
||||||
17
.prettierrc.json
Normal file
17
.prettierrc.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": true,
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"jsxSingleQuote": false,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"arrowParens": "always",
|
||||||
|
"htmlWhitespaceSensitivity": "css",
|
||||||
|
"vueIndentScriptAndStyle": true,
|
||||||
|
"proseWrap": "preserve",
|
||||||
|
"embeddedLanguageFormatting": "auto"
|
||||||
|
}
|
||||||
@@ -167,8 +167,7 @@ li {
|
|||||||
padding: 0.6rem 0.5rem;
|
padding: 0.6rem 0.5rem;
|
||||||
}
|
}
|
||||||
.ant-modal-mask {
|
.ant-modal-mask {
|
||||||
background-color: #666666;
|
background-color: rgba(102, 102, 102, 0.5);
|
||||||
opacity: 0.5;
|
|
||||||
}
|
}
|
||||||
.select_block {
|
.select_block {
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
@@ -1251,8 +1250,8 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte
|
|||||||
border-color: #000 !important;
|
border-color: #000 !important;
|
||||||
}
|
}
|
||||||
.ant-spin .ant-spin-dot {
|
.ant-spin .ant-spin-dot {
|
||||||
width: 1.5em;
|
width: 4.5rem;
|
||||||
height: 1.5em;
|
height: 4.5rem;
|
||||||
}
|
}
|
||||||
.ant-spin-dot-item {
|
.ant-spin-dot-item {
|
||||||
background-color: #000000 !important;
|
background-color: #000000 !important;
|
||||||
|
|||||||
3
src/assets/icons/home.svg
Normal file
3
src/assets/icons/home.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M13.4872 5.28094L9.06266 0.853126C8.51506 0.306793 7.7733 0 7 0C6.2267 0 5.48494 0.306793 4.93734 0.853126L0.512757 5.28094C0.349671 5.44308 0.220373 5.636 0.132355 5.84851C0.0443375 6.06102 -0.000647733 6.2889 7.04636e-06 6.51894V12.249C7.04636e-06 12.7134 0.184381 13.1587 0.51257 13.4871C0.840758 13.8155 1.28588 14 1.75001 14H12.25C12.7141 14 13.1592 13.8155 13.4874 13.4871C13.8156 13.1587 14 12.7134 14 12.249V6.51894C14.0006 6.2889 13.9557 6.06102 13.8676 5.84851C13.7796 5.636 13.6503 5.44308 13.4872 5.28094ZM8.75 12.8326H5.25V10.5364C5.25 10.072 5.43438 9.62663 5.76256 9.29825C6.09075 8.96986 6.53587 8.78538 7 8.78538C7.46413 8.78538 7.90925 8.96986 8.23744 9.29825C8.56562 9.62663 8.75 10.072 8.75 10.5364V12.8326ZM12.8333 12.249C12.8333 12.4038 12.7719 12.5522 12.6625 12.6617C12.5531 12.7711 12.4047 12.8326 12.25 12.8326H9.91666V10.5364C9.91666 9.76241 9.60937 9.0201 9.06239 8.47279C8.51541 7.92549 7.77355 7.61801 7 7.61801C6.22645 7.61801 5.48459 7.92549 4.93761 8.47279C4.39063 9.0201 4.08334 9.76241 4.08334 10.5364V12.8326H1.75001C1.5953 12.8326 1.44692 12.7711 1.33753 12.6617C1.22813 12.5522 1.16667 12.4038 1.16667 12.249V6.51894C1.16721 6.36425 1.22862 6.216 1.33759 6.10627L5.76217 1.6802C6.09099 1.35272 6.53605 1.16887 7 1.16887C7.46394 1.16887 7.90901 1.35272 8.23783 1.6802L12.6624 6.10802C12.771 6.21732 12.8323 6.36486 12.8333 6.51894V12.249Z" fill="#585858"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/images/seller/selectCollectionNullStatus.png
Normal file
BIN
src/assets/images/seller/selectCollectionNullStatus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 73 KiB |
@@ -172,8 +172,9 @@ input:focus{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-modal-mask{
|
.ant-modal-mask{
|
||||||
background-color: #666666;
|
background-color: rgba(102,102,102,0.5);
|
||||||
opacity: .5;
|
// background-color: #666666;
|
||||||
|
// opacity: .5;
|
||||||
}
|
}
|
||||||
.select_block{
|
.select_block{
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="admin_page">
|
<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">
|
||||||
<div class="admin_state_item">
|
<div class="admin_state_item">
|
||||||
<span>Create Time:</span>
|
<span>Create Time:</span>
|
||||||
@@ -8,16 +8,11 @@
|
|||||||
style="width: 250px"
|
style="width: 250px"
|
||||||
class="range_picker"
|
class="range_picker"
|
||||||
v-model:value="rangePickerValue"
|
v-model:value="rangePickerValue"
|
||||||
:placeholder="[
|
:placeholder="[$t('HistoryPage.StartDate'), $t('HistoryPage.EndDate')]"
|
||||||
$t('HistoryPage.StartDate'),
|
|
||||||
$t('HistoryPage.EndDate'),
|
|
||||||
]"
|
|
||||||
valueFormat="YYYY-MM-DD"
|
valueFormat="YYYY-MM-DD"
|
||||||
>
|
>
|
||||||
<template #suffixIcon>
|
<template #suffixIcon>
|
||||||
<span
|
<span class="icon iconfont range_picker_icon icon-rili"></span>
|
||||||
class="icon iconfont range_picker_icon icon-rili"
|
|
||||||
></span>
|
|
||||||
</template>
|
</template>
|
||||||
</a-range-picker>
|
</a-range-picker>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,38 +58,50 @@
|
|||||||
show-search
|
show-search
|
||||||
></a-select>
|
></a-select>
|
||||||
</div>
|
</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>
|
||||||
<div class="admin_search">
|
<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
|
Search
|
||||||
</div>
|
</div>
|
||||||
<div class="admin_search_item" @click="addhHistoryList">
|
<div class="admin_search_item" @click="addhHistoryList">Add</div>
|
||||||
Add
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="admin_state_list">
|
<div class="admin_state_list">
|
||||||
<div
|
<div class="admin_state_list_item" @click="lastGeTrialList('year')">
|
||||||
class="admin_state_list_item"
|
|
||||||
@click="lastGeTrialList('year')"
|
|
||||||
>
|
|
||||||
Nearly a year
|
Nearly a year
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="admin_state_list_item" @click="lastGeTrialList('month')">
|
||||||
class="admin_state_list_item"
|
|
||||||
@click="lastGeTrialList('month')"
|
|
||||||
>
|
|
||||||
Last month
|
Last month
|
||||||
</div>
|
</div>
|
||||||
<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>
|
<div class="awayOrUnfold" :class="{ active: isAwayOrUnfold }">
|
||||||
<div class="awayOrUnfold" :class="{active:isAwayOrUnfold}">
|
<span
|
||||||
<span class="icon iconfont menu_icon icon-xiala" @click="()=>isAwayOrUnfold = !isAwayOrUnfold"></span>
|
class="icon iconfont menu_icon icon-xiala"
|
||||||
|
@click="() => (isAwayOrUnfold = !isAwayOrUnfold)"
|
||||||
|
></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="admin_table_content" ref="historyTable">
|
<div class="admin_table_content" ref="historyTable">
|
||||||
<a-table
|
<a-table
|
||||||
@@ -104,24 +111,19 @@
|
|||||||
:data-source="dataList"
|
:data-source="dataList"
|
||||||
:scroll="{ y: historyTableHeight }"
|
:scroll="{ y: historyTableHeight }"
|
||||||
@change="changePage"
|
@change="changePage"
|
||||||
:showSorterTooltip='false'
|
:showSorterTooltip="false"
|
||||||
:pagination="{
|
:pagination="{
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
current: currentPage,
|
current: currentPage,
|
||||||
pageSize: pageSize,
|
pageSize: pageSize,
|
||||||
total: total,
|
total: total,
|
||||||
showQuickJumper: true,
|
showQuickJumper: true,
|
||||||
bordered: false,
|
bordered: false
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, text, record, index }">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<div class="operate_list" v-if="column?.Operations">
|
<div class="operate_list" v-if="column?.Operations">
|
||||||
<div
|
<div class="operate_item" @click="setAagree(record)">Edit</div>
|
||||||
class="operate_item"
|
|
||||||
@click="setAagree(record)"
|
|
||||||
>
|
|
||||||
Edit
|
|
||||||
</div>
|
|
||||||
<!-- <div
|
<!-- <div
|
||||||
class="operate_item"
|
class="operate_item"
|
||||||
@click="deleteGroup(record, index)"
|
@click="deleteGroup(record, index)"
|
||||||
@@ -132,34 +134,29 @@
|
|||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</div>
|
</div>
|
||||||
<allUserPoerationsVue ref="allUserPoerationsVue" @searchHistoryList="searchHistoryList"></allUserPoerationsVue>
|
<allUserPoerationsVue
|
||||||
|
ref="allUserPoerationsVue"
|
||||||
|
@searchHistoryList="searchHistoryList"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { defineComponent, ref, createVNode, computed, reactive, toRefs, onMounted } from "vue"
|
||||||
defineComponent,
|
import { formatTime } from "@/tool/util"
|
||||||
ref,
|
import { useStore } from "vuex"
|
||||||
createVNode,
|
import { Https } from "@/tool/https"
|
||||||
computed,
|
import allUserPoerationsVue from "./allUserPoerations.vue"
|
||||||
reactive,
|
import SelectUser from "@/component/common/SelectUser.vue"
|
||||||
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({
|
export default defineComponent({
|
||||||
components: {allUserPoerationsVue,SelectUser},
|
components: { allUserPoerationsVue, SelectUser },
|
||||||
setup() {
|
setup() {
|
||||||
const store:any = useStore()
|
const store: any = useStore()
|
||||||
let filter: any = reactive({
|
let filter: any = reactive({
|
||||||
dataList: [],
|
dataList: [],
|
||||||
tableLoading: false,
|
tableLoading: false,
|
||||||
allCountry:[],
|
allCountry: [],
|
||||||
isAwayOrUnfold:false
|
isAwayOrUnfold: false
|
||||||
});
|
})
|
||||||
let filterData: any = reactive({
|
let filterData: any = reactive({
|
||||||
rangePickerValue: [],
|
rangePickerValue: [],
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
@@ -172,40 +169,41 @@ export default defineComponent({
|
|||||||
occupation: "",
|
occupation: "",
|
||||||
systemUser: "",
|
systemUser: "",
|
||||||
order: "", //'Ascending 升序 Descending 降序'
|
order: "", //'Ascending 升序 Descending 降序'
|
||||||
orderBy:'',
|
orderBy: "",
|
||||||
userName: "",
|
userName: "",
|
||||||
});
|
organizationId: null
|
||||||
|
})
|
||||||
let state: any = ref([
|
let state: any = ref([
|
||||||
{
|
{
|
||||||
label: "all",
|
label: "all",
|
||||||
value: "",
|
value: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'visitor',
|
label: "visitor",
|
||||||
value:'0',
|
value: "0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'yearly',
|
label: "yearly",
|
||||||
value:'1',
|
value: "1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'monthly',
|
label: "monthly",
|
||||||
value:'2',
|
value: "2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'trial',
|
label: "trial",
|
||||||
value:'3',
|
value: "3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "userInEvent",
|
label: "userInEvent",
|
||||||
value: "4",
|
value: "4"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Edu Admin",
|
label: "Edu Admin",
|
||||||
value: "7",
|
value: "7"
|
||||||
},
|
}
|
||||||
]);
|
])
|
||||||
let renameData: any = ref({}); //修改名字选中的数据
|
let renameData: any = ref({}) //修改名字选中的数据
|
||||||
const columns: any = computed(() => {
|
const columns: any = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -213,25 +211,25 @@ export default defineComponent({
|
|||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
key: "id",
|
key: "id",
|
||||||
width:100,
|
width: 100,
|
||||||
fixed: "left",
|
fixed: "left",
|
||||||
sorter: true,
|
sorter: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Email",
|
title: "Email",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "userEmail",
|
dataIndex: "userEmail",
|
||||||
key: "userEmail",
|
key: "userEmail",
|
||||||
width:200,
|
width: 200,
|
||||||
ellipsis:true
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "User Name",
|
title: "User Name",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "userName",
|
dataIndex: "userName",
|
||||||
key: "userName",
|
key: "userName",
|
||||||
width:150,
|
width: 150,
|
||||||
ellipsis:true
|
ellipsis: true
|
||||||
// customRender: (record: any) => {
|
// customRender: (record: any) => {
|
||||||
// let time = formatTime(
|
// let time = formatTime(
|
||||||
// record.text / 1000,
|
// record.text / 1000,
|
||||||
@@ -245,77 +243,77 @@ export default defineComponent({
|
|||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "language",
|
dataIndex: "language",
|
||||||
key: "language",
|
key: "language",
|
||||||
width:100,
|
width: 100,
|
||||||
ellipsis:true,
|
ellipsis: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Valid Start Time",
|
title: "Valid Start Time",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "validStartTime",
|
dataIndex: "validStartTime",
|
||||||
key: "validstartTime",
|
key: "validstartTime",
|
||||||
width:200,
|
width: 200,
|
||||||
ellipsis:true,
|
ellipsis: true,
|
||||||
customRender: (record: any) => {
|
customRender: (record: any) => {
|
||||||
let time = ''
|
let time = ""
|
||||||
if(record.text){
|
if (record.text) {
|
||||||
time = formatTime(record.text / 1000, 'YYYY-MM-DD hh:mm:ss')
|
time = formatTime(record.text / 1000, "YYYY-MM-DD hh:mm:ss")
|
||||||
}
|
}
|
||||||
return time
|
return time
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Valid End Time",
|
title: "Valid End Time",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "validEndTime",
|
dataIndex: "validEndTime",
|
||||||
key: "validendTime",
|
key: "validendTime",
|
||||||
width:200,
|
width: 200,
|
||||||
ellipsis:true,
|
ellipsis: true,
|
||||||
customRender: (record: any) => {
|
customRender: (record: any) => {
|
||||||
let time = ''
|
let time = ""
|
||||||
if(record.text){
|
if (record.text) {
|
||||||
time = formatTime(record.text / 1000, 'YYYY-MM-DD hh:mm:ss')
|
time = formatTime(record.text / 1000, "YYYY-MM-DD hh:mm:ss")
|
||||||
}
|
}
|
||||||
return time
|
return time
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Country or Region",
|
title: "Country or Region",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "country",
|
dataIndex: "country",
|
||||||
key: "country",
|
key: "country",
|
||||||
width:200,
|
width: 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Create Date",
|
title: "Create Date",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "createDate",
|
dataIndex: "createDate",
|
||||||
key: "createDate",
|
key: "createDate",
|
||||||
width:200,
|
width: 200,
|
||||||
sorter: true,
|
sorter: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Is Beginner",
|
title: "Is Beginner",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "isBeginner",
|
dataIndex: "isBeginner",
|
||||||
key: "isBeginner",
|
key: "isBeginner",
|
||||||
width:80,
|
width: 80,
|
||||||
ellipsis:true,
|
ellipsis: true,
|
||||||
customRender: (record: any) => {
|
customRender: (record: any) => {
|
||||||
let str;
|
let str
|
||||||
if (record.value == 1) {
|
if (record.value == 1) {
|
||||||
str = "Yes";
|
str = "Yes"
|
||||||
} else {
|
} else {
|
||||||
str = "No";
|
str = "No"
|
||||||
|
}
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
return str;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Machine Room Ip',
|
title: "Machine Room Ip",
|
||||||
align: "center",
|
align: "center",
|
||||||
dataIndex: "browserIdentifiers",
|
dataIndex: "browserIdentifiers",
|
||||||
key: "browserIdentifiers",
|
key: "browserIdentifiers",
|
||||||
width:200,
|
width: 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Credits",
|
title: "Credits",
|
||||||
@@ -326,11 +324,11 @@ export default defineComponent({
|
|||||||
// resizable: true,
|
// resizable: true,
|
||||||
dataIndex: "credits",
|
dataIndex: "credits",
|
||||||
key: "credits",
|
key: "credits",
|
||||||
width:100,
|
width: 100,
|
||||||
sorter: true,
|
sorter: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'User Type',
|
title: "User Type",
|
||||||
align: "center",
|
align: "center",
|
||||||
// width: 150,
|
// width: 150,
|
||||||
// minWidth: 100,
|
// minWidth: 100,
|
||||||
@@ -338,84 +336,84 @@ export default defineComponent({
|
|||||||
// resizable: true,
|
// resizable: true,
|
||||||
dataIndex: "systemUser",
|
dataIndex: "systemUser",
|
||||||
key: "systemUser",
|
key: "systemUser",
|
||||||
width:100,
|
width: 100,
|
||||||
customRender: (record: any) => {
|
customRender: (record: any) => {
|
||||||
let str;
|
let str
|
||||||
if (record.value == 0) {
|
if (record.value == 0) {
|
||||||
str = "visitor";
|
str = "visitor"
|
||||||
} else if (record.value == 1) {
|
} else if (record.value == 1) {
|
||||||
str = "yearly";
|
str = "yearly"
|
||||||
} else if (record.value == 2) {
|
} else if (record.value == 2) {
|
||||||
str = "monthly";
|
str = "monthly"
|
||||||
} else if (record.value == 3) {
|
} else if (record.value == 3) {
|
||||||
str = "trial";
|
str = "trial"
|
||||||
} else if (record.value == 4) {
|
} else if (record.value == 4) {
|
||||||
str = "userInEvent";
|
str = "userInEvent"
|
||||||
} else if (record.value == 7) {
|
} else if (record.value == 7) {
|
||||||
str = "Edu Admin";
|
str = "Edu Admin"
|
||||||
|
}
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
return str;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Operations",
|
title: "Operations",
|
||||||
key: "operation",
|
key: "operation",
|
||||||
width:120,
|
width: 120,
|
||||||
align: "center",
|
align: "center",
|
||||||
fixed: "right",
|
fixed: "right",
|
||||||
// slots:{customRender:'action'}
|
// slots:{customRender:'action'}
|
||||||
Operations: true,
|
Operations: true
|
||||||
},
|
}
|
||||||
];
|
]
|
||||||
});
|
})
|
||||||
//改变页码
|
//改变页码
|
||||||
let changePage = (e: any, filters:any, sorter:any) => {
|
let changePage = (e: any, filters: any, sorter: any) => {
|
||||||
filterData.currentPage = e.current;
|
filterData.currentPage = e.current
|
||||||
filterData.pageSize = e.pageSize;
|
filterData.pageSize = e.pageSize
|
||||||
if(sorter.order){
|
if (sorter.order) {
|
||||||
if(sorter.columnKey == 'id'){
|
if (sorter.columnKey == "id") {
|
||||||
filterData.orderBy = 'id'
|
filterData.orderBy = "id"
|
||||||
}else if(sorter.columnKey == "createDate"){
|
} else if (sorter.columnKey == "createDate") {
|
||||||
filterData.orderBy = 'time'
|
filterData.orderBy = "time"
|
||||||
}else if(sorter.columnKey == "credits"){
|
} else if (sorter.columnKey == "credits") {
|
||||||
filterData.orderBy = 'credits'
|
filterData.orderBy = "credits"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(sorter.order){
|
if (sorter.order) {
|
||||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending"
|
||||||
}else{
|
} else {
|
||||||
filterData.order = ''
|
filterData.order = ""
|
||||||
|
}
|
||||||
|
gettrialList()
|
||||||
}
|
}
|
||||||
gettrialList();
|
|
||||||
};
|
|
||||||
|
|
||||||
//查询列表
|
//查询列表
|
||||||
let searchHistoryList = () => {
|
let searchHistoryList = () => {
|
||||||
filterData.currentPage = 1;
|
filterData.currentPage = 1
|
||||||
gettrialList();
|
gettrialList()
|
||||||
};
|
}
|
||||||
let clearHistoryList = () => {
|
let clearHistoryList = () => {
|
||||||
filterData.rangePickerValue = [],
|
;((filterData.rangePickerValue = []),
|
||||||
filterData.currentPage = 1,
|
(filterData.currentPage = 1),
|
||||||
filterData.pageSize = 10,
|
(filterData.pageSize = 10),
|
||||||
filterData.total = 0,
|
(filterData.total = 0),
|
||||||
filterData.country = "",
|
(filterData.country = ""),
|
||||||
filterData.email = "",
|
(filterData.email = ""),
|
||||||
filterData.userType = "",
|
(filterData.userType = ""),
|
||||||
filterData.ids = [],
|
(filterData.ids = []),
|
||||||
filterData.occupation = "",
|
(filterData.occupation = ""),
|
||||||
filterData.order = "", //'Ascending 升序 Descending 降序'
|
(filterData.order = ""), //'Ascending 升序 Descending 降序'
|
||||||
filterData.orderBy = "", //'Ascending 升序 Descending 降序'
|
(filterData.orderBy = ""), //'Ascending 升序 Descending 降序'
|
||||||
filterData.systemUser = "",
|
(filterData.systemUser = ""),
|
||||||
filterData.userName = "";
|
(filterData.userName = ""))
|
||||||
};
|
}
|
||||||
let setHistoryListData = () => {
|
let setHistoryListData = () => {
|
||||||
let startDate: any = filterData.rangePickerValue?.[0]
|
let startDate: any = filterData.rangePickerValue?.[0]
|
||||||
? filterData.rangePickerValue[0] + " " + "00:00:00"
|
? filterData.rangePickerValue[0] + " " + "00:00:00"
|
||||||
: "";
|
: ""
|
||||||
let endDate: any = filterData.rangePickerValue?.[1]
|
let endDate: any = filterData.rangePickerValue?.[1]
|
||||||
? filterData.rangePickerValue[1] + " " + "23:59:59"
|
? filterData.rangePickerValue[1] + " " + "23:59:59"
|
||||||
: "";
|
: ""
|
||||||
let data = {
|
let data = {
|
||||||
endTime: endDate,
|
endTime: endDate,
|
||||||
startTime: startDate,
|
startTime: startDate,
|
||||||
@@ -430,63 +428,118 @@ export default defineComponent({
|
|||||||
order: filterData.order,
|
order: filterData.order,
|
||||||
orderBy: filterData.orderBy,
|
orderBy: filterData.orderBy,
|
||||||
userName: filterData.userName,
|
userName: filterData.userName,
|
||||||
};
|
organizationId: filterData.organizationId
|
||||||
return data;
|
}
|
||||||
};
|
return data
|
||||||
|
}
|
||||||
//获取列表
|
//获取列表
|
||||||
let gettrialList = () => {
|
let gettrialList = () => {
|
||||||
filter.tableLoading = true;
|
filter.tableLoading = true
|
||||||
let data = setHistoryListData();
|
let data = setHistoryListData()
|
||||||
Https.axiosPost(Https.httpUrls.getUserInfo, data).then(
|
Https.axiosPost(Https.httpUrls.getUserInfo, data).then((rv: any) => {
|
||||||
(rv: any) => {
|
|
||||||
if (rv) {
|
if (rv) {
|
||||||
// this.dataList = rv
|
// this.dataList = rv
|
||||||
filter.dataList = rv.records;
|
filter.dataList = rv.records
|
||||||
filterData.total = rv.total;
|
filterData.total = rv.total
|
||||||
filter.tableLoading = false;
|
filter.tableLoading = false
|
||||||
|
|
||||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
);
|
|
||||||
};
|
|
||||||
let lastGeTrialList = (str: string) => {
|
let lastGeTrialList = (str: string) => {
|
||||||
clearHistoryList();
|
clearHistoryList()
|
||||||
let currentDate = new Date();
|
let currentDate = new Date()
|
||||||
let currentTimestamp = Math.floor(currentDate.getTime() / 1000);
|
let currentTimestamp = Math.floor(currentDate.getTime() / 1000)
|
||||||
// 计算30天前的时间戳
|
// 计算30天前的时间戳
|
||||||
let thirtyDaysAgoTimestamp;
|
let thirtyDaysAgoTimestamp
|
||||||
if (str == "year") {
|
if (str == "year") {
|
||||||
thirtyDaysAgoTimestamp = currentTimestamp - 360 * 24 * 60 * 60;
|
thirtyDaysAgoTimestamp = currentTimestamp - 360 * 24 * 60 * 60
|
||||||
} else if (str == "month") {
|
} else if (str == "month") {
|
||||||
thirtyDaysAgoTimestamp = currentTimestamp - 30 * 24 * 60 * 60;
|
thirtyDaysAgoTimestamp = currentTimestamp - 30 * 24 * 60 * 60
|
||||||
} else if (str == "week") {
|
} 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) => {
|
let filterOption = (input: any, option: any) => {
|
||||||
// 使用 option.label 进行搜索
|
// 使用 option.label 进行搜索
|
||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
};
|
}
|
||||||
let addhHistoryList = () => {
|
let addhHistoryList = () => {
|
||||||
allUserPoerationsVue.value.init('Add','')
|
allUserPoerationsVue.value.init("Add", "")
|
||||||
};
|
}
|
||||||
let allUserPoerationsVue = ref()
|
let allUserPoerationsVue = ref()
|
||||||
let setAagree = (data:any) =>{
|
let setAagree = (data: any) => {
|
||||||
allUserPoerationsVue.value.init('Edit',data)
|
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(() => {
|
onMounted(() => {
|
||||||
let allCountry: any = sessionStorage.getItem("allCountry");
|
let allCountry: any = sessionStorage.getItem("allCountry")
|
||||||
if (allCountry) {
|
if (allCountry) {
|
||||||
filter.allCountry = JSON.parse(allCountry);
|
filter.allCountry = JSON.parse(allCountry)
|
||||||
}
|
}
|
||||||
gettrialList();
|
gettrialList()
|
||||||
});
|
getOrganizationList()
|
||||||
|
})
|
||||||
return {
|
return {
|
||||||
...toRefs(filter),
|
...toRefs(filter),
|
||||||
...toRefs(filterData),
|
...toRefs(filterData),
|
||||||
@@ -501,29 +554,32 @@ export default defineComponent({
|
|||||||
filterOption,
|
filterOption,
|
||||||
allUserPoerationsVue,
|
allUserPoerationsVue,
|
||||||
setAagree,
|
setAagree,
|
||||||
};
|
handleOrganizationScroll,
|
||||||
|
getOrganizationList,
|
||||||
|
organizationOptions,
|
||||||
|
organizationParams
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
historyTableHeight: 0,
|
historyTableHeight: 0,
|
||||||
handleResizeColumn: (w: any, col: any) => {
|
handleResizeColumn: (w: any, col: any) => {
|
||||||
col.width = w;
|
col.width = w
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let historyTable: any = this.$refs.historyTable;
|
let historyTable: any = this.$refs.historyTable
|
||||||
this.historyTableHeight = historyTable.clientHeight - 200;
|
this.historyTableHeight = historyTable.clientHeight - 200
|
||||||
},
|
},
|
||||||
methods: {},
|
methods: {}
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.admin_page .admin_table_search .admin_state {
|
.admin_page .admin_table_search .admin_state {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.admin_page{
|
.admin_page {
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
|||||||
<div class="upload_item">
|
<div class="upload_item">
|
||||||
<div class="upload_file_item upload_component">
|
<div class="upload_file_item upload_component">
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + (upLoadHttpsUrl?upLoadHttpsUrl:'/api/element/upload')"
|
:action="uploadUrl + (upLoadHttpsUrl?upLoadHttpsUrl:'/aida/api/element/upload')"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
class="search_upImg"
|
class="search_upImg"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
...upload
|
...upload
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
class="search_upImg"
|
class="search_upImg"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
...upload
|
...upload
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<div class="upload_file_item upload_component" v-show="fileList.length < 15">
|
<div class="upload_file_item upload_component" v-show="fileList.length < 15">
|
||||||
<a-upload
|
<a-upload
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
...upload
|
...upload
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="upload_file_item upload_component" v-show="fileList.length < 10">
|
<div class="upload_file_item upload_component" v-show="fileList.length < 10">
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<a-upload
|
<a-upload
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
...upload,
|
...upload,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<div class="upload_item" v-show="uploadList.length < 1">
|
<div class="upload_item" v-show="uploadList.length < 1">
|
||||||
<div class="upload_file_item upload_component">
|
<div class="upload_file_item upload_component">
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + '/api/history/brandLogoUpload'"
|
:action="uploadUrl + '/aida/api/history/brandLogoUpload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:headers="{ Authorization: token }"
|
:headers="{ Authorization: token }"
|
||||||
|
|||||||
@@ -213,10 +213,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="upload_file_item upload_component">
|
<div class="upload_file_item upload_component">
|
||||||
<!-- :action="uploadUrl + '/api/history/toProductImageElementUpload'" -->
|
<!-- :action="uploadUrl + '/aida/api/history/toProductImageElementUpload'" -->
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="
|
:action="
|
||||||
getUploadUrl() + '/api/history/toProductImageElementUpload'
|
getUploadUrl() + '/aida/api/history/toProductImageElementUpload'
|
||||||
"
|
"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
>
|
>
|
||||||
|
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:data="{
|
:data="{
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="upload_file_item upload_component" v-show="printboardList.length < 16">
|
<div class="upload_file_item upload_component" v-show="printboardList.length < 16">
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
@@ -415,7 +415,7 @@ export default defineComponent({
|
|||||||
file:data.originFileObj
|
file:data.originFileObj
|
||||||
}
|
}
|
||||||
let fileUid = data.uid
|
let fileUid = data.uid
|
||||||
Https.axiosPost('/api/element/upload', new_data,{headers:{'Content-Type': 'multipart/form-data'}}).then(
|
Https.axiosPost('/aida/api/element/upload', new_data,{headers:{'Content-Type': 'multipart/form-data'}}).then(
|
||||||
(rv: any) => {
|
(rv: any) => {
|
||||||
if (rv) {
|
if (rv) {
|
||||||
for(let file of this.fileList){
|
for(let file of this.fileList){
|
||||||
@@ -491,7 +491,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
this.isUpload = true
|
this.isUpload = true
|
||||||
const hide = message.loading('loading', 0);
|
const hide = message.loading('loading', 0);
|
||||||
Https.axiosPost('/api/element/upload', new_data,{headers:{'Content-Type': 'multipart/form-data'}}).then(
|
Https.axiosPost('/aida/api/element/upload', new_data,{headers:{'Content-Type': 'multipart/form-data'}}).then(
|
||||||
(rv: any) => {
|
(rv: any) => {
|
||||||
for(let file of this.fileList){
|
for(let file of this.fileList){
|
||||||
if(fileData.uid === file.uid){
|
if(fileData.uid === file.uid){
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
v-show="sketchboardList.length < 20"
|
v-show="sketchboardList.length < 20"
|
||||||
>
|
>
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<keep-alive :include="cachedRoutes">
|
<keep-alive :include="cachedRoutes">
|
||||||
<component
|
<component
|
||||||
:is="Component"
|
:is="Component"
|
||||||
:key="route.name"
|
:cachedRoutes="cachedRoutes"
|
||||||
/>
|
/>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</router-view>
|
</router-view>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
:options="[{value:'product',label:'product'},{value:'sketch',label:'sketch'}]"
|
:options="[{value:'product',label:'product'},{value:'sketch',label:'sketch'}]"
|
||||||
></a-select>
|
></a-select>
|
||||||
</div> -->
|
</div> -->
|
||||||
<selectList @selectImgItem="selectImgItem" :deReconstructionList="segmentationTypeList" :isSegmentation="true" upLoadHttpsUrl="/api/element/imageSegmentation" level1Type="Sketchboard" :randomId="false" type="sketch" :catecoryList="sketchCatecoryList">
|
<selectList @selectImgItem="selectImgItem" :deReconstructionList="segmentationTypeList" :isSegmentation="true" upLoadHttpsUrl="/aida/api/element/imageSegmentation" level1Type="Sketchboard" :randomId="false" type="sketch" :catecoryList="sketchCatecoryList">
|
||||||
<template v-slot:selectSex>
|
<template v-slot:selectSex>
|
||||||
<div class="generalModel_state" style="margin-left: auto">
|
<div class="generalModel_state" style="margin-left: auto">
|
||||||
<div class="generalModel_state_item smail" style="margin-right: 0">
|
<div class="generalModel_state_item smail" style="margin-right: 0">
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ export default defineComponent({
|
|||||||
// //fetch get请求携带token
|
// //fetch get请求携带token
|
||||||
|
|
||||||
|
|
||||||
// fetch("https://develop.api.aida.com.hk/api/project/getThreeDGlb?threeDSimpleId=1", {
|
// fetch("https://develop.api.aida.com.hk/aida/api/project/getThreeDGlb?threeDSimpleId=1", {
|
||||||
// headers:{
|
// headers:{
|
||||||
// authorization:'Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4OCIsInN1YiI6IntcImNvdW50cnlcIjpcIkNoaW5hXCIsXCJpZFwiOjg4LFwibGFuZ3VhZ2VcIjpcIkVOR0xJU0hcIixcInVzZXJuYW1lXCI6XCJzaGJcIn0iLCJpYXQiOjE3NDMzNDkwNjQsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE3NTE5ODkwNjR9.gmL0JufYy9wd23qCY-ibwhgpXZ2X68WAiHSeC99I4x7cipWyxLaQmuIBk2SJSdWBm0tTN2Mx-etXO9a7MtQmpw',
|
// authorization:'Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiI4OCIsInN1YiI6IntcImNvdW50cnlcIjpcIkNoaW5hXCIsXCJpZFwiOjg4LFwibGFuZ3VhZ2VcIjpcIkVOR0xJU0hcIixcInVzZXJuYW1lXCI6XCJzaGJcIn0iLCJpYXQiOjE3NDMzNDkwNjQsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE3NTE5ODkwNjR9.gmL0JufYy9wd23qCY-ibwhgpXZ2X68WAiHSeC99I4x7cipWyxLaQmuIBk2SJSdWBm0tTN2Mx-etXO9a7MtQmpw',
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<div class="upload_file_item">
|
<div class="upload_file_item">
|
||||||
<a-upload
|
<a-upload
|
||||||
key="common"
|
key="common"
|
||||||
:action="getUploadUrl() + '/api/history/toProductImageElementUpload'"
|
:action="getUploadUrl() + '/aida/api/history/toProductImageElementUpload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:data="{
|
:data="{
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
key="lastframes"
|
key="lastframes"
|
||||||
:action="
|
:action="
|
||||||
getUploadUrl() + '/api/history/toProductImageElementUpload'
|
getUploadUrl() + '/aida/api/history/toProductImageElementUpload'
|
||||||
"
|
"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<div class="upload_item item" v-show="!isDesignPage">
|
<div class="upload_item item" v-show="!isDesignPage">
|
||||||
<div class="upload_file_item">
|
<div class="upload_file_item">
|
||||||
<a-upload
|
<a-upload
|
||||||
:action="uploadUrl + '/api/history/toProductImageElementUpload'"
|
:action="uploadUrl + '/aida/api/history/toProductImageElementUpload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:data="{
|
:data="{
|
||||||
|
|||||||
167
src/lang/cn.ts
167
src/lang/cn.ts
@@ -24,6 +24,7 @@ export default {
|
|||||||
SubscribeNow: '立即订阅',
|
SubscribeNow: '立即订阅',
|
||||||
TaskList: '任务列表',
|
TaskList: '任务列表',
|
||||||
ViewOrders: '查询订单',
|
ViewOrders: '查询订单',
|
||||||
|
PersonalCenter: '个人中心',
|
||||||
BecomeSeller: '成为卖家',
|
BecomeSeller: '成为卖家',
|
||||||
SellerDashboard: '卖家中心',
|
SellerDashboard: '卖家中心',
|
||||||
toolsToProduct: '转产品图',
|
toolsToProduct: '转产品图',
|
||||||
@@ -1535,7 +1536,7 @@ export default {
|
|||||||
},
|
},
|
||||||
event: {
|
event: {
|
||||||
back: '返回',
|
back: '返回',
|
||||||
detail:'查看详情'
|
detail: '查看详情'
|
||||||
},
|
},
|
||||||
admin: {
|
admin: {
|
||||||
allUser: '所有用户',
|
allUser: '所有用户',
|
||||||
@@ -1609,7 +1610,7 @@ export default {
|
|||||||
Cancel: '取消',
|
Cancel: '取消',
|
||||||
SelectPlan: '选择计划',
|
SelectPlan: '选择计划',
|
||||||
AllPlan: '全部',
|
AllPlan: '全部',
|
||||||
PlanStart:'订阅计划生效时间:'
|
PlanStart: '订阅计划生效时间:'
|
||||||
},
|
},
|
||||||
Login: {
|
Login: {
|
||||||
Login: '登录',
|
Login: '登录',
|
||||||
@@ -1736,29 +1737,155 @@ export default {
|
|||||||
showAgain: '不再提示',
|
showAgain: '不再提示',
|
||||||
GetStarted: '开始体验',
|
GetStarted: '开始体验',
|
||||||
},
|
},
|
||||||
SellerListEdit:{
|
SellerListEdit: {
|
||||||
saveDraft: "保存草稿",
|
saveDraft: "全部保存",
|
||||||
publish: "发布",
|
publish: "发布",
|
||||||
sketch: "线稿图",
|
sketch: "线稿图",
|
||||||
mainProductImage: "产品主图",
|
mainProductImage: "产品主图",
|
||||||
cover: "封面",
|
cover: "封面",
|
||||||
productImageDesc:'从产品图中选取',
|
productImageDesc: '从产品图中选取',
|
||||||
cropDesc:'从主产品图或线稿图中裁剪',
|
cropDesc: '从主产品图或线稿图中裁剪',
|
||||||
productImageMainTitle:'产品图 ',
|
productImageMainTitle: '产品图/视频',
|
||||||
productImageSubTitle:' (来自设计集)',
|
productImageSubTitle: ' (来自设计集)',
|
||||||
apparelSketchTitle:'服装线稿图 ',
|
apparelSketchTitle: '服装线稿图 ',
|
||||||
apparelSketchSubTitle:' (来自设计集)',
|
apparelSketchSubTitle: ' (来自设计集)',
|
||||||
productName:'商品名称',
|
productName: '商品名称',
|
||||||
price:'价格',
|
price: '价格',
|
||||||
productDescription:'商品描述',
|
productDescription: '商品描述',
|
||||||
designFor:'目标人群',
|
designFor: '目标人群',
|
||||||
productCategory:'商品类别',
|
productCategory: '商品类别',
|
||||||
categoryTips:'请选择所有适用选项',
|
categoryTips: '请选择所有适用选项',
|
||||||
policy:'默认情况下,所有销售均遵循平台的许可政策——买家在下载后将获得使用许可',
|
policy: '默认情况下,所有销售均遵循平台的许可政策——买家在下载后将获得使用许可',
|
||||||
learnMore:'了解更多',
|
learnMore: '了解更多',
|
||||||
|
requiredFieldTips: '请填写{field}',
|
||||||
|
requiredFieldTipsWithPage: '第 {index} 个商品:请填写{field}',
|
||||||
draftSaved: '草稿已保存',
|
draftSaved: '草稿已保存',
|
||||||
draftDesc: '您的商品已保存为草稿。\n您可以继续编辑,或稍后在“我的商品”中发布。',
|
draftDesc: '您的商品已保存为草稿。\n您可以继续编辑,或稍后在“我的商品”中发布。',
|
||||||
listingLive:'商品已上架',
|
listingLive: '商品已上架',
|
||||||
publishDesc:'您的商品现已上架。\n买家可以浏览并购买您的设计。'
|
publishDesc: '您的商品现已上架。\n买家可以浏览并购买您的设计。'
|
||||||
|
},
|
||||||
|
Seller: {
|
||||||
|
// Brand Profile
|
||||||
|
brandProfile: "店铺详情",
|
||||||
|
myListings: "我的商品",
|
||||||
|
myOrders: "我的订单",
|
||||||
|
settings: "设置",
|
||||||
|
brandProfileBgNullTip: "您的店铺横幅尚未设置。",
|
||||||
|
changeBrandBanner: "更改店铺横幅",
|
||||||
|
edit: "编辑",
|
||||||
|
cancel: "取消",
|
||||||
|
confirm: "确认",
|
||||||
|
saveChange: "保存更改",
|
||||||
|
brandProfileEditTip: "这些更改将会在您的“Stylish Parade”品牌页面上得到体现。",
|
||||||
|
storeName: "店铺名称",
|
||||||
|
storeNameDesc: "请输入您的店铺名称",
|
||||||
|
ownerName: "姓名",
|
||||||
|
ownerNameDesc: "请输入姓名",
|
||||||
|
email: "邮箱",
|
||||||
|
emailDesc: "请输入邮箱",
|
||||||
|
mobile: "手机号",
|
||||||
|
mobileDesc: "请输入手机号",
|
||||||
|
link: "链接{index}",
|
||||||
|
links: "投资组合/社交媒体链接",
|
||||||
|
storeDescription: "店铺描述",
|
||||||
|
storeDescriptionDesc: "请输入店铺描述",
|
||||||
|
storeDescriptionErr: "请输入店铺描述",
|
||||||
|
cropBrandBanner: "裁剪店铺横幅",
|
||||||
|
cropAvatar: "裁剪头像",
|
||||||
|
cropFrom: "裁剪来源:",
|
||||||
|
sketch: "线稿图",
|
||||||
|
mainProductImage: "产品主图",
|
||||||
|
cropPreview: "裁剪预览",
|
||||||
|
imageClipCoverTip: "将封面图片裁剪为正方形,保持比例。",
|
||||||
|
imageClipMainProductImageTip: "将产品主图裁剪为正方形,保持比例。",
|
||||||
|
imageClipSketchTip: "将线稿图裁剪为正方形,保持比例。",
|
||||||
|
imageClipApparelTip: "将服装线稿图裁剪为正方形,保持比例。",
|
||||||
|
// 我的订单
|
||||||
|
totalRevenue: "总销售额",
|
||||||
|
totalPurchases: "总购买量",
|
||||||
|
totalViews: "总浏览量",
|
||||||
|
allInvoice: "所有订单",
|
||||||
|
myOrdersTip: "所有已完成交易的摘要",
|
||||||
|
myOrdersSearchPlaceholder: "按项目名称或订单ID搜索",
|
||||||
|
orderId: "订单ID",
|
||||||
|
item: "项目",
|
||||||
|
price: "价格",
|
||||||
|
buyerUsername: "买家用户名",
|
||||||
|
date: "日期",
|
||||||
|
// 设置
|
||||||
|
notifications: "通知",
|
||||||
|
notificationsTitle: "新订单通知",
|
||||||
|
notificationsTip: "当有新订单时收到通知。",
|
||||||
|
unbound: "未绑定",
|
||||||
|
manage: "管理",
|
||||||
|
bindNow: "立即绑定",
|
||||||
|
paymentCurrency: "支付货币",
|
||||||
|
HKD: "HKD - 香港元",
|
||||||
|
fixed: "固定",
|
||||||
|
dataPrivacy: "数据与隐私",
|
||||||
|
dataPrivacyTitle: "版权许可",
|
||||||
|
dataPrivacyTip1: "每笔购买下载都会自动附带一份许可证证书。请查看适用于您商品列表的默认许可条款。",
|
||||||
|
dataPrivacyTip2: "此许可证由 Code-Create 颁发,购买时即具有法律约束力。它证明购买者有权按照以下条款使用所购买的设计资产。",
|
||||||
|
dataPrivacyTip3: "对于定制的许可安排,请<span onclick='{click}()'>联系我们</span>。",
|
||||||
|
downloadToView: "下载以查看",
|
||||||
|
stopSelling: "停止销售",
|
||||||
|
stopSellingTitle: "停用卖家账户",
|
||||||
|
stopSellingTip: "永久停用您的卖家账户。所有商品列表和发票记录将被删除。您以后可以重新注册为卖家,但您的先前销售数据无法恢复。",
|
||||||
|
deactivate: "停用卖家账户",
|
||||||
|
newListing: "新建商品",
|
||||||
|
draftMessage: '商品已保存为草稿。您可以继续编辑,或稍后在“我的商品”中发布。',
|
||||||
|
publishMessage: '商品现已上架。买家可以浏览并购买您的设计。',
|
||||||
|
ActiveListings: '已发布商品',
|
||||||
|
Praka: '线稿',
|
||||||
|
Drafts: '草稿',
|
||||||
|
Cancel: '取消',
|
||||||
|
Delete: '删除',
|
||||||
|
DeleteConfirm: '确认删除吗?',
|
||||||
|
DeleteDesc: '删除后,商品将无法恢复。',
|
||||||
|
Edit: '编辑',
|
||||||
|
Draft: '草稿',
|
||||||
|
Publish: '发布',
|
||||||
|
sketchesSelected: '已选择的线稿图',
|
||||||
|
Next: '下一步',
|
||||||
|
All: '全部',
|
||||||
|
SeriesDesign: '系列设计',
|
||||||
|
SingleDesign: '单设计商品',
|
||||||
|
sketchs: '线稿图',
|
||||||
|
MyListings: '我的商品',
|
||||||
|
MyListingsInfo: '已发布商品和未发布库存',
|
||||||
|
SelectCollection: '选择商品',
|
||||||
|
SelectSketch: '选择线稿图',
|
||||||
|
EditListingDetails: '编辑商品详情',
|
||||||
|
VideoWarning: '首次选中的图片素材会作为产品主图,视频不可作为产品主图',
|
||||||
|
selectSketchMaxNum: '最多选择9个线稿图',
|
||||||
|
},
|
||||||
|
ApplySeller: {
|
||||||
|
applySellerTitle: '申请成为卖家',
|
||||||
|
applySellerDesc: '加入Stylish Parade,开始销售您的设计作品',
|
||||||
|
formTitle: '店铺信息',
|
||||||
|
formTip: '请提供一些详细信息来创建您的卖家资料。',
|
||||||
|
termsTitle: '服务条款',
|
||||||
|
termsTip: '请阅读并同意服务条款。',
|
||||||
|
agreementTitle: 'AiDA 卖家协议',
|
||||||
|
agreementTip: '请阅读并同意卖家协议。',
|
||||||
|
agreementItem1: '提供准确和真实的个人信息和店铺信息',
|
||||||
|
agreementItem2: '仅销售原创设计或内容,获得必要的许可证',
|
||||||
|
agreementItem3: '维护所有产品的高质量标准',
|
||||||
|
agreementItem4: '在48小时内回复客户咨询',
|
||||||
|
agreementItem5: '在承诺的时间内发货',
|
||||||
|
agreementItem6: '遵守AiDA的服务条款和社区指南',
|
||||||
|
agreementItem7: '支付适用的平台费用和交易费用',
|
||||||
|
agreementItem8: '专业和公平地处理客户纠纷',
|
||||||
|
agreementAgreement: '我已经阅读并同意了卖家协议,清楚地了解了自己在 AiDA 平台上作为卖家所应承担的责任和义务。',
|
||||||
|
submitApplication: '提交申请',
|
||||||
|
applicationSubmitted: '申请已提交',
|
||||||
|
applicationSubmittedTip: '预计很快就会批准。收到批准后,请在发布任何商品前,确保在 <span>卖家控制面板 > 设置</span> 中关联您的收款账户。',
|
||||||
|
auditStatus1_title: "步骤 1:提交申请",
|
||||||
|
auditStatus1_tip: "请填写店铺信息并同意服务条款。",
|
||||||
|
auditStatus2_title: "步骤 2:审核验证",
|
||||||
|
auditStatus2_tip: "我们的团队将在审核您的申请后,1-3个工作日审核您的店铺信息。",
|
||||||
|
auditStatus3_title: "步骤 3:开始销售",
|
||||||
|
auditStatus3_tip: "审核通过后,您可以开始销售您的商品。",
|
||||||
|
backToHomepage: "返回首页",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
134
src/lang/en.ts
134
src/lang/en.ts
@@ -24,6 +24,7 @@ export default {
|
|||||||
SubscribeNow: 'Subscribe now',
|
SubscribeNow: 'Subscribe now',
|
||||||
TaskList: 'Task List',
|
TaskList: 'Task List',
|
||||||
ViewOrders: 'View Orders',
|
ViewOrders: 'View Orders',
|
||||||
|
PersonalCenter: 'Personal Center',
|
||||||
BecomeSeller: 'Become a Seller',
|
BecomeSeller: 'Become a Seller',
|
||||||
SellerDashboard: 'Seller Dashboard',
|
SellerDashboard: 'Seller Dashboard',
|
||||||
toolsToProduct: 'To product image',
|
toolsToProduct: 'To product image',
|
||||||
@@ -1788,14 +1789,14 @@ export default {
|
|||||||
GetStarted: 'Get Started',
|
GetStarted: 'Get Started',
|
||||||
},
|
},
|
||||||
SellerListEdit:{
|
SellerListEdit:{
|
||||||
saveDraft:'Save Draft',
|
saveDraft:'Save All New',
|
||||||
publish:'Publish',
|
publish:'Publish',
|
||||||
sketch:'Sketch',
|
sketch:'Sketch',
|
||||||
mainProductImage:'Main Product Image',
|
mainProductImage:'Main Product Image',
|
||||||
cover:'Cover',
|
cover:'Cover',
|
||||||
productImageDesc:'Choose from product image',
|
productImageDesc:'Choose from product image',
|
||||||
cropDesc:'Crop from main product image or sketch',
|
cropDesc:'Crop from main product image or sketch',
|
||||||
productImageMainTitle:'Product Image ',
|
productImageMainTitle:'Product Media ',
|
||||||
productImageSubTitle:'(from design collection)',
|
productImageSubTitle:'(from design collection)',
|
||||||
apparelSketchTitle:'Apparel Sketch ',
|
apparelSketchTitle:'Apparel Sketch ',
|
||||||
apparelSketchSubTitle:'(from design collection)',
|
apparelSketchSubTitle:'(from design collection)',
|
||||||
@@ -1807,9 +1808,138 @@ export default {
|
|||||||
categoryTips:'select all that apply',
|
categoryTips:'select all that apply',
|
||||||
policy:'By default, all sales follow the platform\'s licensing policy — buyers will receive a usage license upon download.',
|
policy:'By default, all sales follow the platform\'s licensing policy — buyers will receive a usage license upon download.',
|
||||||
learnMore:'Learn more',
|
learnMore:'Learn more',
|
||||||
|
requiredFieldTips:'Please fill in {field}',
|
||||||
|
requiredFieldTipsWithPage:'Listing {index}: Please fill in {field}',
|
||||||
draftSaved: 'Draft Saved',
|
draftSaved: 'Draft Saved',
|
||||||
draftDesc: 'Your listing has been saved as a draft. \nYou can continue editing or publish it later from My Listings.',
|
draftDesc: 'Your listing has been saved as a draft. \nYou can continue editing or publish it later from My Listings.',
|
||||||
listingLive:'Listing Live',
|
listingLive:'Listing Live',
|
||||||
publishDesc:'Your listing is now live on the marketplace.\nBuyers can discover and purchase your design.'
|
publishDesc:'Your listing is now live on the marketplace.\nBuyers can discover and purchase your design.'
|
||||||
|
},
|
||||||
|
Seller: {
|
||||||
|
brandProfile: "Brand Profile",
|
||||||
|
myListings: "My Listings",
|
||||||
|
myOrders: "My Orders",
|
||||||
|
settings: "Settings",
|
||||||
|
// Brand Profile
|
||||||
|
brandProfileBgNullTip: "Your brand banner has not been set up yet.",
|
||||||
|
changeBrandBanner: "Change Brand Banner",
|
||||||
|
edit: "Edit",
|
||||||
|
cancel: "Cancel",
|
||||||
|
confirm: "Confirm",
|
||||||
|
saveChange: "Save Change",
|
||||||
|
brandProfileEditTip: "Changes will be reflected on your Stylish Parade brand page.",
|
||||||
|
storeName: "Store Name",
|
||||||
|
storeNameDesc: "Enter your store name",
|
||||||
|
ownerName: "Owner’s Full Name",
|
||||||
|
ownerNameDesc: "Enter store owner's full name",
|
||||||
|
email: "Email",
|
||||||
|
emailDesc: "Enter email",
|
||||||
|
mobile: "Phone Number",
|
||||||
|
mobileDesc: "Enter phone number",
|
||||||
|
link: "Link {index}",
|
||||||
|
links: "Portfoilo/Social Media Links",
|
||||||
|
storeDescription: "Store Description",
|
||||||
|
storeDescriptionDesc: "Briefly describe your design style and store features...",
|
||||||
|
storeDescriptionErr: "Please enter store description",
|
||||||
|
cropBrandBanner: "Crop Brand Banner",
|
||||||
|
cropAvatar: "Crop Avatar",
|
||||||
|
cropFrom: "Crop from:",
|
||||||
|
sketch: "Sketch",
|
||||||
|
mainProductImage: "Main Product Image",
|
||||||
|
cropPreview: "Crop Preview",
|
||||||
|
imageClipCoverTip: "Align crown to top, mid-thigh to bottom for best results.",
|
||||||
|
imageClipMainProductImageTip: "Align crown to top, foot base to bottom for best results.",
|
||||||
|
imageClipSketchTip: "Align crown to top, foot base to bottom for best results.",
|
||||||
|
imageClipApparelTip: "Trim whitespace and center your apparel sketch.",
|
||||||
|
// 我的订单
|
||||||
|
totalRevenue: "Total Revenue",
|
||||||
|
totalPurchases: "Total Purchases",
|
||||||
|
totalViews: "Total Views",
|
||||||
|
allInvoice: "All Invoice",
|
||||||
|
myOrdersTip: "A summary of all completed transactions.",
|
||||||
|
myOrdersSearchPlaceholder: "Search by item name or order ID",
|
||||||
|
orderId: "Order ID",
|
||||||
|
item: "Item",
|
||||||
|
price: "Price",
|
||||||
|
buyerUsername: "Buyer Username",
|
||||||
|
date: "Date",
|
||||||
|
// 设置
|
||||||
|
notifications: "Notifications",
|
||||||
|
notificationsTitle: "New order notification",
|
||||||
|
notificationsTip: "Receive an inbox message when a new order is placed.",
|
||||||
|
payout: "Payout",
|
||||||
|
payoutTitle: "Payment Providers",
|
||||||
|
payoutTip: "Select how you want to receive payments.",
|
||||||
|
unbound: "Unbound",
|
||||||
|
manage: "Manage",
|
||||||
|
bindNow: "Bind Now",
|
||||||
|
paymentCurrency: "Payment Currency",
|
||||||
|
HKD: "HKD - Hong Kong Dollar",
|
||||||
|
fixed: "Fixed",
|
||||||
|
dataPrivacy: "Data & Privacy",
|
||||||
|
dataPrivacyTitle: "Copyright licence",
|
||||||
|
dataPrivacyTip1: "A licence certificate is automatically included with every purchase download. View the default licensing terms applied to your listings.",
|
||||||
|
dataPrivacyTip2: "BThis licence is issued by Code-Create and is legally binding upon purchase. It certifies the buyer's right to use the purchased design asset in accordance with the terms below.",
|
||||||
|
dataPrivacyTip3: "For custom licensing arrangements, <span onclick='{click}()'>contact us</span>.",
|
||||||
|
downloadToView: "Download to View",
|
||||||
|
stopSelling: "Stop Selling",
|
||||||
|
stopSellingTitle: "Deactivate seller account",
|
||||||
|
stopSellingTip: "Permanently deactivate your seller account. All listings and invoice records will be deleted. You may re-register as a seller in the future, but your previous sales data cannot be recovered.",
|
||||||
|
deactivate: "Deactivate",
|
||||||
|
newListing: "New Listing",
|
||||||
|
draftMessage: 'Product moved to drafts and stats reset.',
|
||||||
|
publishMessage: 'Item is now live on the Marketplace.',
|
||||||
|
ActiveListings: 'Active Listings',
|
||||||
|
Praka: 'Praka',
|
||||||
|
Drafts: 'Drafts',
|
||||||
|
Cancel: 'Cancel',
|
||||||
|
Delete: 'Delete',
|
||||||
|
DeleteConfirm: 'Delete this listing?',
|
||||||
|
DeleteDesc: 'Your listing and its details will be permanently removed.',
|
||||||
|
Edit: 'Edit',
|
||||||
|
Draft: 'Draft',
|
||||||
|
Publish: 'Publish',
|
||||||
|
sketchesSelected: 'Sketches selected',
|
||||||
|
Next: 'Next',
|
||||||
|
All: 'All',
|
||||||
|
SeriesDesign: 'Series Design',
|
||||||
|
SingleDesign: 'Single Design',
|
||||||
|
sketchs: 'sketches',
|
||||||
|
MyListings: 'My Listings',
|
||||||
|
MyListingsInfo: 'Active listings and unpublished inventory',
|
||||||
|
SelectCollection: 'Select Collection',
|
||||||
|
SelectSketch: 'Select Sketch',
|
||||||
|
EditListingDetails: 'Edit Listing Details',
|
||||||
|
VideoWarning:'The first selected item is the main product image. Videos cannot be used.',
|
||||||
|
selectSketchMaxNum: 'Select up to 9 sketches',
|
||||||
|
},
|
||||||
|
ApplySeller: {
|
||||||
|
applySellerTitle: 'Apply to Become a Seller',
|
||||||
|
applySellerDesc: 'Join the Stylish Parade and start selling your design work',
|
||||||
|
formTitle: 'Brand Information',
|
||||||
|
formTip: 'Share a few details to set up your seller profile',
|
||||||
|
termsTitle: 'Seller Terms',
|
||||||
|
termsTip: 'Please carefully read and agree to the following terms',
|
||||||
|
agreementTitle: 'AiDA Seller Agreement',
|
||||||
|
agreementTip: 'Please read and agree to the following agreement',
|
||||||
|
agreementItem1: "Provide accurate and truthful personal and store information",
|
||||||
|
agreementItem2: "Only sell original designs or content with proper licensing",
|
||||||
|
agreementItem3: "Maintain high quality standards for all products",
|
||||||
|
agreementItem4: "Respond to customer inquiries within 48 hours",
|
||||||
|
agreementItem5: "Ship orders within promised timeframes",
|
||||||
|
agreementItem6: "Comply with AiDA's terms of service and community guidelines",
|
||||||
|
agreementItem7: "Pay applicable platform fees and transaction charges",
|
||||||
|
agreementItem8: "Handle customer disputes professionally and fairly",
|
||||||
|
agreementAgreement: "I have read and agree to the Seller Agreement, understanding my responsibilities and obligations as a seller on the AiDA platform.",
|
||||||
|
submitApplication: "Submit Application",
|
||||||
|
applicationSubmitted: "Application Submitted",
|
||||||
|
applicationSubmittedTip: "Approval is expected shortly. Upon receipt, please ensure your payout account is linked under <span>Seller Dashboard > Settings</span> prior to listing any items.",
|
||||||
|
auditStatus1_title: "Step 1: Submit Application",
|
||||||
|
auditStatus1_tip: "Fill out the seller information form and agree to our terms",
|
||||||
|
auditStatus2_title: "Step 2: Review & Verification",
|
||||||
|
auditStatus2_tip: "Our team will review your application (typically 1-3 business days)",
|
||||||
|
auditStatus3_title: "Step 3: Start Selling",
|
||||||
|
auditStatus3_tip: "Once approved, access your seller dashboard and start listing products",
|
||||||
|
backToHomepage: "Back to Homepage",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,63 @@
|
|||||||
import { createRouter, createWebHistory, RouteRecordRaw, createWebHashHistory } from "vue-router"
|
import { createRouter, createWebHistory, RouteRecordRaw, createWebHashHistory } from "vue-router"
|
||||||
|
import type { RouteLocationNormalizedLoaded, RouteLocationRaw } from "vue-router"
|
||||||
import store from "@/store"
|
import store from "@/store"
|
||||||
import { Https } from "@/tool/https"
|
import { Https } from "@/tool/https"
|
||||||
import { getCookie, setCookie } from "@/tool/cookie"
|
import { getCookie, setCookie } from "@/tool/cookie"
|
||||||
|
|
||||||
|
type SellerRouteMetaValue<T> = T | ((route: RouteLocationNormalizedLoaded) => T)
|
||||||
|
type SellerBreadcrumbItem = {
|
||||||
|
title?: SellerRouteMetaValue<string>
|
||||||
|
titleKey?: SellerRouteMetaValue<string>
|
||||||
|
to?: SellerRouteMetaValue<RouteLocationRaw | undefined>
|
||||||
|
}
|
||||||
|
type SellerBreadcrumbList = SellerRouteMetaValue<SellerBreadcrumbItem[]>
|
||||||
|
|
||||||
|
const myListingsBreadcrumb: SellerBreadcrumbItem = {
|
||||||
|
titleKey: "Seller.MyListings",
|
||||||
|
to: { name: "myListingsIndex" }
|
||||||
|
}
|
||||||
|
const selectCollectionBreadcrumb: SellerBreadcrumbItem = {
|
||||||
|
titleKey: "Seller.SelectCollection",
|
||||||
|
to: { name: "myListingsSelect" }
|
||||||
|
}
|
||||||
|
const selectSketchBreadcrumb: SellerBreadcrumbItem = {
|
||||||
|
titleKey: "Seller.SelectSketch",
|
||||||
|
to: (route) => {
|
||||||
|
const collectionId =
|
||||||
|
route.params.collectionId ||
|
||||||
|
(typeof history !== "undefined" ? history.state?.collectionId : "")
|
||||||
|
|
||||||
|
return collectionId
|
||||||
|
? { name: "myListingsSelectItem", params: { collectionId } }
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const editListingBreadcrumb: SellerBreadcrumbItem = {
|
||||||
|
titleKey: "Seller.EditListingDetails"
|
||||||
|
}
|
||||||
|
const statusBreadcrumb: SellerBreadcrumbItem = {
|
||||||
|
titleKey: (route) =>
|
||||||
|
route.params.status === "publish"
|
||||||
|
? "SellerListEdit.listingLive"
|
||||||
|
: "SellerListEdit.draftSaved"
|
||||||
|
}
|
||||||
|
const createListingBreadcrumbs: SellerBreadcrumbItem[] = [
|
||||||
|
myListingsBreadcrumb,
|
||||||
|
selectCollectionBreadcrumb,
|
||||||
|
selectSketchBreadcrumb,
|
||||||
|
editListingBreadcrumb
|
||||||
|
]
|
||||||
|
const isEditingListingFromList = () =>
|
||||||
|
typeof history !== "undefined" && history.state?.type === "edit"
|
||||||
|
const editListingBreadcrumbs: SellerBreadcrumbList = () =>
|
||||||
|
isEditingListingFromList()
|
||||||
|
? [myListingsBreadcrumb, editListingBreadcrumb]
|
||||||
|
: createListingBreadcrumbs
|
||||||
|
const listingStatusBreadcrumbs: SellerBreadcrumbList = () =>
|
||||||
|
isEditingListingFromList()
|
||||||
|
? [myListingsBreadcrumb, editListingBreadcrumb, statusBreadcrumb]
|
||||||
|
: [...createListingBreadcrumbs, statusBreadcrumb]
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
@@ -167,7 +222,11 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: "becomeSeller",
|
path: "becomeSeller",
|
||||||
name: "becomeSeller",
|
name: "becomeSeller",
|
||||||
meta: { enter: "all" },
|
meta: {
|
||||||
|
enter: "all",
|
||||||
|
sellerHeaderTitle: "ApplySeller.applySellerTitle",
|
||||||
|
sellerHeaderTip: "ApplySeller.applySellerDesc"
|
||||||
|
},
|
||||||
component: () => import("@/views/SellerDashboard/BecomeSeller/index.vue")
|
component: () => import("@/views/SellerDashboard/BecomeSeller/index.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -176,6 +235,11 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
meta: { enter: "all" },
|
meta: { enter: "all" },
|
||||||
component: () => import("@/views/SellerDashboard/index.vue"),
|
component: () => import("@/views/SellerDashboard/index.vue"),
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
meta: { enter: "all" },
|
||||||
|
redirect: "/home/seller/brandProfile"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "brandProfile",
|
path: "brandProfile",
|
||||||
name: "brandProfile",
|
name: "brandProfile",
|
||||||
@@ -185,7 +249,7 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: "myListings",
|
path: "myListings",
|
||||||
name: "myListings",
|
name: "myListings",
|
||||||
meta: { enter: "all" },
|
meta: { enter: "all", sellerBreadcrumb: myListingsBreadcrumb },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
@@ -196,35 +260,63 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: "index",
|
path: "index",
|
||||||
name: "myListingsIndex",
|
name: "myListingsIndex",
|
||||||
meta: { enter: "all" },
|
meta: {
|
||||||
|
enter: "all",
|
||||||
|
sellerHeaderTitleKey: "Seller.MyListings",
|
||||||
|
sellerHeaderTipKey: "Seller.MyListingsInfo",
|
||||||
|
sellerBreadcrumbs: [myListingsBreadcrumb]
|
||||||
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/views/SellerDashboard/MyListings/main/index.vue")
|
import("@/views/SellerDashboard/MyListings/main/index.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "select",
|
path: "select",
|
||||||
name: "myListingsSelect",
|
name: "myListingsSelect",
|
||||||
meta: { enter: "all" },
|
meta: {
|
||||||
|
enter: "all",
|
||||||
|
sellerHeaderTitleKey: "Seller.SelectCollection",
|
||||||
|
sellerBreadcrumbs: [
|
||||||
|
myListingsBreadcrumb,
|
||||||
|
selectCollectionBreadcrumb
|
||||||
|
]
|
||||||
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/views/SellerDashboard/MyListings/createSelect/index.vue")
|
import("@/views/SellerDashboard/MyListings/createSelect/index.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "select/:collectionId",
|
path: "select/:collectionId",
|
||||||
name: "myListingsSelectItem",
|
name: "myListingsSelectItem",
|
||||||
meta: { enter: "all" },
|
meta: {
|
||||||
|
enter: "all",
|
||||||
|
sellerHeaderTitleKey: "Seller.SelectSketch",
|
||||||
|
sellerBreadcrumbs: [
|
||||||
|
myListingsBreadcrumb,
|
||||||
|
selectCollectionBreadcrumb,
|
||||||
|
selectSketchBreadcrumb
|
||||||
|
]
|
||||||
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/views/SellerDashboard/MyListings/createSelectItem/index.vue")
|
import("@/views/SellerDashboard/MyListings/createSelectItem/index.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "edit",
|
path: "edit",
|
||||||
name: "EditDetail",
|
name: "EditDetail",
|
||||||
meta: { enter: "all" },
|
meta: {
|
||||||
|
enter: "all",
|
||||||
|
sellerHeaderTitleKey: "Seller.EditListingDetails",
|
||||||
|
sellerBreadcrumbs: editListingBreadcrumbs
|
||||||
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/views/SellerDashboard/MyListings/EditDetail/index.vue")
|
import("@/views/SellerDashboard/MyListings/EditDetail/index.vue")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path:'edit/status/:status',
|
path: "edit/status/:status",
|
||||||
name:'Status',
|
name: "Status",
|
||||||
meta:{enter:'all'},
|
meta: {
|
||||||
|
enter: "all",
|
||||||
|
sellerHeaderTitleKey: "Seller.EditListingDetails",
|
||||||
|
sellerBreadcrumbs: listingStatusBreadcrumbs
|
||||||
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import("@/views/SellerDashboard/MyListings/EditDetail/Status.vue")
|
import("@/views/SellerDashboard/MyListings/EditDetail/Status.vue")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ interface DesignerInfo {
|
|||||||
ownerName: string,
|
ownerName: string,
|
||||||
email: string,
|
email: string,
|
||||||
mobile: string,
|
mobile: string,
|
||||||
socialLinks: string,
|
socialLinks: string[] | string,
|
||||||
description: string,
|
description: string,
|
||||||
}
|
}
|
||||||
interface Seller {
|
interface Seller {
|
||||||
isSeller: boolean,
|
isSeller: boolean,
|
||||||
applyStatus: number,
|
applyStatus: number | null,
|
||||||
designerInfo: DesignerInfo,
|
designerInfo: DesignerInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +49,27 @@ const seller: Module<Seller, RootState> = {
|
|||||||
},
|
},
|
||||||
set_designerInfo(state: Seller, value: DesignerInfo) {
|
set_designerInfo(state: Seller, value: DesignerInfo) {
|
||||||
state.designerInfo = {
|
state.designerInfo = {
|
||||||
|
...state.designerInfo,
|
||||||
...value,
|
...value,
|
||||||
socialLinks: JSON.parse(value.socialLinks)
|
}
|
||||||
|
if (typeof value.socialLinks === "string") {
|
||||||
|
state.designerInfo.socialLinks = JSON.parse(value.socialLinks)
|
||||||
|
} else if (Array.isArray(value.socialLinks)) {
|
||||||
|
state.designerInfo.socialLinks = value.socialLinks
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clear_state(state: Seller) {
|
||||||
|
state.isSeller = false
|
||||||
|
state.applyStatus = null
|
||||||
|
state.designerInfo = {
|
||||||
|
shopName: "--",
|
||||||
|
avatar: "",
|
||||||
|
brandBanner: "",
|
||||||
|
ownerName: "--",
|
||||||
|
email: "--",
|
||||||
|
mobile: "--",
|
||||||
|
socialLinks: ["--"],
|
||||||
|
description: "--"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,21 +13,13 @@ axios.defaults.headers.post['lang'] = 'en' //配置语言请求头
|
|||||||
axios.defaults.withCredentials = true //跨域携带cookie
|
axios.defaults.withCredentials = true //跨域携带cookie
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
// if(import.meta.env.VITE_USER_NODE_ENV == "development"){
|
const baseURL = import.meta.env.VITE_APP_BASE_URL
|
||||||
// axios.defaults.baseURL = ""; //配置接口地址
|
console.log(baseURL)
|
||||||
// }else{
|
if (import.meta.env.VITE_USER_NODE_ENV == "development") {
|
||||||
// axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_URL; //配置接口地址
|
axios.defaults.baseURL = "";
|
||||||
// }
|
} else {
|
||||||
// let httpIp
|
axios.defaults.baseURL = baseURL;
|
||||||
// if(import.meta.env.VITE_USER_NODE_ENV == 'development'){
|
}
|
||||||
// httpIp = 'http://192.168.1.12:10086'
|
|
||||||
// }else{
|
|
||||||
// httpIp = ''
|
|
||||||
// }
|
|
||||||
const isDev = import.meta.env.VITE_USER_NODE_ENV == 'development'
|
|
||||||
const baseURL = isDev ? '' : import.meta.env.VITE_APP_BASE_URL
|
|
||||||
axios.defaults.baseURL = baseURL; // isDev ? '' : import.meta.env.VITE_APP_BASE_URL; //配置接口地址
|
|
||||||
console.log(import.meta.env.VITE_APP_BASE_URL, baseURL)
|
|
||||||
|
|
||||||
// 创建取消令牌
|
// 创建取消令牌
|
||||||
const CancelToken = axios.CancelToken
|
const CancelToken = axios.CancelToken
|
||||||
@@ -146,349 +138,352 @@ axios.interceptors.response.use(
|
|||||||
export const Https = {
|
export const Https = {
|
||||||
httpUrls: {
|
httpUrls: {
|
||||||
interfaceUrl: '',
|
interfaceUrl: '',
|
||||||
parseGoogleCredential: '/api/third/party/parseGoogleCredential', //谷歌登录注册
|
parseGoogleCredential: '/aida/api/third/party/parseGoogleCredential', //谷歌登录注册
|
||||||
parseWeChatCode: '/api/third/party/parseWeChatCode', //微信登录
|
parseWeChatCode: '/aida/api/third/party/parseWeChatCode', //微信登录
|
||||||
accountIsLogin: '/api/account/isLogin', //判断用户是否登录
|
accountIsLogin: '/aida/api/account/isLogin', //判断用户是否登录
|
||||||
accountLogin: `/api/account/login`, //账号密码登录接口
|
accountLogin: `/aida/api/account/login`, //账号密码登录接口
|
||||||
organizationNameSearch: `/api/account/organizationNameSearch`, //查询学校或者企业版名字
|
organizationNameSearch: `/aida/api/account/organizationNameSearch`, //查询学校或者企业版名字
|
||||||
getUserLanguage: `/api/account/getUserLanguage`, //获取当前用户语言
|
getUserLanguage: `/aida/api/account/getUserLanguage`, //获取当前用户语言
|
||||||
changeUserLanguage: `/api/account/changeUserLanguage`, //切换用户当前语言
|
changeUserLanguage: `/aida/api/account/changeUserLanguage`, //切换用户当前语言
|
||||||
uploadAvatar: `/api/account/uploadAvatar`, //修改头像
|
uploadAvatar: `/aida/api/account/uploadAvatar`, //修改头像
|
||||||
editUserName: `/api/account/editUserName`, //修改用户名
|
editUserName: `/aida/api/account/editUserName`, //修改用户名
|
||||||
updateUserInfo: `/api/account/updateUserInfo`, //修改国家职业
|
updateUserInfo: `/aida/api/account/updateUserInfo`, //修改国家职业
|
||||||
accountDetail: `/api/account/getAccountDetail`, //用户详细信息
|
accountDetail: `/aida/api/account/getAccountDetail`, //用户详细信息
|
||||||
|
|
||||||
trialUserLogout: `/api/account/trialUserLogout`, //试用用户退出登录接口
|
trialUserLogout: `/aida/api/account/trialUserLogout`, //试用用户退出登录接口
|
||||||
completeGuidancet: `/api/account/completeGuidance`, //用户指引结束
|
completeGuidancet: `/aida/api/account/completeGuidance`, //用户指引结束
|
||||||
|
|
||||||
getExpiredTime: `/api/account/getExpiredTime`, //获取用户到期时间
|
getExpiredTime: `/aida/api/account/getExpiredTime`, //获取用户到期时间
|
||||||
|
|
||||||
addNoLoginRequired: `/api/third/party/addNoLoginRequired`, //机房用户注册
|
addNoLoginRequired: `/aida/api/third/party/addNoLoginRequired`, //机房用户注册
|
||||||
deleteNoLoginRequired: `/api/third/party/deleteNoLoginRequired`, //机房用户注销
|
deleteNoLoginRequired: `/aida/api/third/party/deleteNoLoginRequired`, //机房用户注销
|
||||||
noLoginRequired: `api/account/noLoginRequired`, //机房用户登录
|
noLoginRequired: `/aida/api/account/noLoginRequired`, //机房用户登录
|
||||||
existNoLoginRequired: `/api/third/party/existNoLoginRequired`, //获取唯一标识是否存在
|
existNoLoginRequired: `/aida/api/third/party/existNoLoginRequired`, //获取唯一标识是否存在
|
||||||
|
|
||||||
deleteNoLoginRequiredNew: `/api/third/party/deleteNoLoginRequiredNew`, //机房用户注销
|
deleteNoLoginRequiredNew: `/aida/api/third/party/deleteNoLoginRequiredNew`, //机房用户注销
|
||||||
addNoLoginRequiredNew: `api/third/party/addNoLoginRequiredNew`, //机房用户注册
|
addNoLoginRequiredNew: `/aida/api/third/party/addNoLoginRequiredNew`, //机房用户注册
|
||||||
updateNoLoginRequiredNew: `api/third/party/updateNoLoginRequiredNew`, //机房用户更新
|
updateNoLoginRequiredNew: `/aida/api/third/party/updateNoLoginRequiredNew`, //机房用户更新
|
||||||
|
|
||||||
endpoint: `api/third/party/your-secured-endpoint`, //获取唯一标识是否存在
|
endpoint: `/aida/api/third/party/your-secured-endpoint`, //获取唯一标识是否存在
|
||||||
|
|
||||||
designWorksRegister: '/api/account/designWorksRegister', //注册
|
designWorksRegister: '/aida/api/account/designWorksRegister', //注册
|
||||||
designWorksRegisterCode: '/api/account/designWorksRegisterCode', //注册
|
designWorksRegisterCode: '/aida/api/account/designWorksRegisterCode', //注册
|
||||||
|
|
||||||
preLogin: '/api/account/preLogin', //预先登入
|
preLogin: '/aida/api/account/preLogin', //预先登入
|
||||||
schoolLogin: '/api/account/schoolLogin', //学校管理员登录
|
schoolLogin: '/aida/api/account/schoolLogin', //学校管理员登录
|
||||||
enterpriseLogin: '/api/account/enterpriseLogin', //企业管理员登录
|
enterpriseLogin: '/aida/api/account/enterpriseLogin', //企业管理员登录
|
||||||
accountSendEmail: `/api/account/sendEmail`, //发送邮件
|
accountSendEmail: `/aida/api/account/sendEmail`, //发送邮件
|
||||||
accountResetPwd: '/api/account/resetPwd', //忘记密码修改
|
accountResetPwd: '/aida/api/account/resetPwd', //忘记密码修改
|
||||||
accountLogout: '/api/account/logout', //登出
|
accountLogout: '/aida/api/account/logout', //登出
|
||||||
accountBindEmail: '/api/account/bindEmail', //绑定邮箱
|
accountBindEmail: '/aida/api/account/bindEmail', //绑定邮箱
|
||||||
bindGoogle: '/api/account/bindGoogle', //绑定谷歌
|
bindGoogle: '/aida/api/account/bindGoogle', //绑定谷歌
|
||||||
bindWeChat: '/api/account/bindWeChat', //绑定微信
|
bindWeChat: '/aida/api/account/bindWeChat', //绑定微信
|
||||||
unbindGoogle: `/api/account/unbindGoogle`, //取消绑定谷歌
|
unbindGoogle: `/aida/api/account/unbindGoogle`, //取消绑定谷歌
|
||||||
unbindWeChat: '/api/account/unbindWeChat', //取消绑定微信
|
unbindWeChat: '/aida/api/account/unbindWeChat', //取消绑定微信
|
||||||
elementGeneratePrint: '/api/element/generatePrint', //生成印花
|
elementGeneratePrint: '/aida/api/element/generatePrint', //生成印花
|
||||||
elementSavePrint: '/api/element/savePrint', //保存印花
|
elementSavePrint: '/aida/api/element/savePrint', //保存印花
|
||||||
getRgbByTcx: '/api/element/getRgbByTcx', // 通过hsv值获取潘通信息
|
getRgbByTcx: '/aida/api/element/getRgbByTcx', // 通过hsv值获取潘通信息
|
||||||
getRgbByHsv: '/api/element/getRgbByHsv', //通过hsv值获取潘通信息
|
getRgbByHsv: '/aida/api/element/getRgbByHsv', //通过hsv值获取潘通信息
|
||||||
elementDelete: '/api/element/delete', //删除上传的图片
|
elementDelete: '/aida/api/element/delete', //删除上传的图片
|
||||||
designCollection: `/api/design/designCollection`, //设计 Conllection
|
designCollection: `/aida/api/design/designCollection`, //设计 Conllection
|
||||||
reDesignCollection: `/api/design/reDesignCollection`, //重新设计 Conllection
|
reDesignCollection: `/aida/api/design/reDesignCollection`, //重新设计 Conllection
|
||||||
countDesignProcess: '/api/design/countDesignProcess', //统计design进度
|
countDesignProcess: '/aida/api/design/countDesignProcess', //统计design进度
|
||||||
getDesignResult: '/api/design/getDesignResult', //查询design结果
|
getDesignResult: '/aida/api/design/getDesignResult', //查询design结果
|
||||||
designSort: `/api/design/sort`, //design排序
|
designSort: `/aida/api/design/sort`, //design排序
|
||||||
collectionLikeUpdate: `/api/history/collectionLikeUpdate`, //赋值排序
|
collectionLikeUpdate: `/aida/api/history/collectionLikeUpdate`, //赋值排序
|
||||||
|
|
||||||
designProcess: `/api/design/designProcess`, //统计design进度
|
designProcess: `/aida/api/design/designProcess`, //统计design进度
|
||||||
designGetModel: `/api/design/getModel`, //导出获取模特链接
|
designGetModel: `/aida/api/design/getModel`, //导出获取模特链接
|
||||||
|
|
||||||
//充值相关
|
//充值相关
|
||||||
productList: `/api/product/list`, //获取商品列表
|
productList: `/aida/api/product/list`, //获取商品列表
|
||||||
payAlipay: `/api/ali-pay/trade/page/pay`, //支付宝确认支付
|
payAlipay: `/aida/api/ali-pay/trade/page/pay`, //支付宝确认支付
|
||||||
payAlipayHK: `/api/alipay-hk/createOrder`, //香港支付宝确认支付
|
payAlipayHK: `/aida/api/alipay-hk/createOrder`, //香港支付宝确认支付
|
||||||
payStripe: `/api/stripe/createOrder`, //Stripe支付
|
payStripe: `/aida/api/stripe/createOrder`, //Stripe支付
|
||||||
payPaypal: `/api/paypal/trade`, //paypal确认支付
|
payPaypal: `/aida/api/paypal/trade`, //paypal确认支付
|
||||||
getCredits: `/api/credits/getCredits`, //查询用户积分
|
getCredits: `/aida/api/credits/getCredits`, //查询用户积分
|
||||||
|
|
||||||
cancelSubscription: `/api/stripe/cancelSubscription`, //取消订阅
|
cancelSubscription: `/aida/api/stripe/cancelSubscription`, //取消订阅
|
||||||
|
|
||||||
orderInfoList: `/api/order-info/list`, //查询订单列表
|
orderInfoList: `/aida/api/order-info/list`, //查询订单列表
|
||||||
getCreditsDetail: `/api/credits/getCreditsDetail`, //查询积分列表
|
getCreditsDetail: `/aida/api/credits/getCreditsDetail`, //查询积分列表
|
||||||
tradeRefundAlipay: `/api/ali-pay/trade/refund`, //支付宝退款
|
tradeRefundAlipay: `/aida/api/ali-pay/trade/refund`, //支付宝退款
|
||||||
tradeRefundPaypal: `/api/paypal/trade/refund`, //paypal退款
|
tradeRefundPaypal: `/aida/api/paypal/trade/refund`, //paypal退款
|
||||||
|
|
||||||
tradeQuery: `/api/ali-pay/trade/query/{orderNo}`, //查询订单状态
|
tradeQuery: `/aida/api/ali-pay/trade/query/{orderNo}`, //查询订单状态
|
||||||
|
|
||||||
getRgbByHsvBatch: `/api/element/getRgbByHsvBatch`, //通过hsv值数组批量获取潘通信息
|
getRgbByHsvBatch: `/aida/api/element/getRgbByHsvBatch`, //通过hsv值数组批量获取潘通信息
|
||||||
designLike: `/api/design/like`, //Design Like
|
designLike: `/aida/api/design/like`, //Design Like
|
||||||
designDislike: `/api/design/dislike`, //Design Dislike
|
designDislike: `/aida/api/design/dislike`, //Design Dislike
|
||||||
queryUserGroup: `/api/history/queryUserGroup`, //History用户分页分组列表
|
queryUserGroup: `/aida/api/history/queryUserGroup`, //History用户分页分组列表
|
||||||
deleteUserGroup: `/api/history/deleteUserGroup`, //History删除用户分组
|
deleteUserGroup: `/aida/api/history/deleteUserGroup`, //History删除用户分组
|
||||||
updateUserGroupName: `/api/history/updateUserGroupName`, //History修改用户分组名
|
updateUserGroupName: `/aida/api/history/updateUserGroupName`, //History修改用户分组名
|
||||||
projectSaveOrUpdate: `/api/project/saveOrUpdate`, //History修改用户分组名
|
projectSaveOrUpdate: `/aida/api/project/saveOrUpdate`, //History修改用户分组名
|
||||||
historyChoose: `/api/history/choose`, //History choose
|
historyChoose: `/aida/api/history/choose`, //History choose
|
||||||
getDesignDetail: `/api/design/detail/getDetail`, //查询design详情
|
getDesignDetail: `/aida/api/design/detail/getDetail`, //查询design详情
|
||||||
addSysSketchToLibrary: `/api/library/addSysSketchToLibrary`, //把系统衣服添加的library
|
addSysSketchToLibrary: `/aida/api/library/addSysSketchToLibrary`, //把系统衣服添加的library
|
||||||
designSingleWithGradient: `/api/design/detail/designSingleWithGradient`, //查询需要更新mask列表
|
designSingleWithGradient: `/aida/api/design/detail/designSingleWithGradient`, //查询需要更新mask列表
|
||||||
getNextSysElement: '/api/design/detail/getNextSysElement', //切换系统的element
|
getNextSysElement: '/aida/api/design/detail/getNextSysElement', //切换系统的element
|
||||||
detailPrintDot: '/api/design/detail/printDot', //print打点预览
|
detailPrintDot: '/aida/api/design/detail/printDot', //print打点预览
|
||||||
designSingle: `/api/design/detail/designSingle`, //单个design
|
designSingle: `/aida/api/design/detail/designSingle`, //单个design
|
||||||
queryLibraryPage: `/api/library/queryLibraryPage`, //Library分页列表
|
queryLibraryPage: `/aida/api/library/queryLibraryPage`, //Library分页列表
|
||||||
libraryUpload: `/api/library/upload`, // Library文件上传
|
libraryUpload: `/aida/api/library/upload`, // Library文件上传
|
||||||
setSketchLibrary: `/api/library/updateLibraryLevel2Type`, // 修改图片类型
|
setSketchLibrary: `/aida/api/library/updateLibraryLevel2Type`, // 修改图片类型
|
||||||
updateElementLevel2Type: `/api/element/updateElementLevel2Type`, // 修改拼贴上传的衣服类型
|
updateElementLevel2Type: `/aida/api/element/updateElementLevel2Type`, // 修改拼贴上传的衣服类型
|
||||||
|
|
||||||
queryClassification: `/api/classification/queryClassification`, //标签类别查询
|
queryClassification: `/aida/api/classification/queryClassification`, //标签类别查询
|
||||||
classificationSaveOrUpdate: `/api/classification/saveOrUpdate`, //标签类别新增修改
|
classificationSaveOrUpdate: `/aida/api/classification/saveOrUpdate`, //标签类别新增修改
|
||||||
classificationDelete: `/api/classification/delete`, //标签类别新增修改
|
classificationDelete: `/aida/api/classification/delete`, //标签类别新增修改
|
||||||
relationLibrary: `/api/classification/relationLibrary`, //标签类别新增修改
|
relationLibrary: `/aida/api/classification/relationLibrary`, //标签类别新增修改
|
||||||
getRelClassificationIdList: `/api/classification/getRelClassificationIdList`, //标签类别新增修改
|
getRelClassificationIdList: `/aida/api/classification/getRelClassificationIdList`, //标签类别新增修改
|
||||||
getRelPublicClassificationIdList: `/api/classification/getRelPublicClassificationIdList`, //多选获取公共标签
|
getRelPublicClassificationIdList: `/aida/api/classification/getRelPublicClassificationIdList`, //多选获取公共标签
|
||||||
editRelPublicClassificationIdList: `/api/classification/editRelPublicClassificationIdList`, //多选修改公共标签
|
editRelPublicClassificationIdList: `/aida/api/classification/editRelPublicClassificationIdList`, //多选修改公共标签
|
||||||
|
|
||||||
//模块化
|
//模块化
|
||||||
llmStream: `/api/llm/streamNew`, //聊天
|
llmStream: `/aida/api/llm/streamNew`, //聊天
|
||||||
// llmStream:`/api/llm/stream`,//聊天
|
// llmStream:`/aida/api/llm/stream`,//聊天
|
||||||
chatCreateProject: `/api/llm/chatCreateProject`, //聊天创建项目
|
chatCreateProject: `/aida/api/llm/chatCreateProject`, //聊天创建项目
|
||||||
getChatHistory: `/api/llm/getChatHistory`, //获取聊天历史记录
|
getChatHistory: `/aida/api/llm/getChatHistory`, //获取聊天历史记录
|
||||||
llmUploadFile: `/api/llm/uploadFile`, //聊天上传文件
|
llmUploadFile: `/aida/api/llm/uploadFile`, //聊天上传文件
|
||||||
|
|
||||||
saveOrUpdate: `/api/project/saveOrUpdate`, //模块化新增修改
|
saveOrUpdate: `/aida/api/project/saveOrUpdate`, //模块化新增修改
|
||||||
getModuleContent: `/api/project/getModuleContent`, //获取模块内容
|
getModuleContent: `/aida/api/project/getModuleContent`, //获取模块内容
|
||||||
saveModuleContent: `/api/project/saveModuleContent`, //储存模块内容
|
saveModuleContent: `/aida/api/project/saveModuleContent`, //储存模块内容
|
||||||
historyProject: `/api/project/page`, //项目记录
|
historyProject: `/aida/api/project/page`, //项目记录
|
||||||
projectDetail: `/api/project/delete`, //删除项目
|
projectDetail: `/aida/api/project/delete`, //删除项目
|
||||||
//3d
|
//3d
|
||||||
threeDPage: `/api/project/threeDPage`,
|
threeDPage: `/aida/api/project/threeDPage`,
|
||||||
downloadZip: `/api/project/downloadZip`, //下载zip
|
downloadZip: `/aida/api/project/downloadZip`, //下载zip
|
||||||
getThreeDSize: `/api/project/getThreeDSize`, //下载列表
|
getThreeDSize: `/aida/api/project/getThreeDSize`, //下载列表
|
||||||
getLayoutDetail: `/api/project/getLayoutDetail`, //获取3d详情
|
getLayoutDetail: `/aida/api/project/getLayoutDetail`, //获取3d详情
|
||||||
getThreeDGlb: `/api/project/getThreeDGlb`,
|
getThreeDGlb: `/aida/api/project/getThreeDGlb`,
|
||||||
selectHistoryProject: `/api/project/choose`, //选择项目
|
selectHistoryProject: `/aida/api/project/choose`, //选择项目
|
||||||
getMannequinDetail: `/api/project/getMannequinDetail`, //模块化查看模特点位
|
getMannequinDetail: `/aida/api/project/getMannequinDetail`, //模块化查看模特点位
|
||||||
modifyProportion: `/api/generate/modifyProportion`, //模特拉伸
|
modifyProportion: `/aida/api/generate/modifyProportion`, //模特拉伸
|
||||||
addSysModelToLib: `/api/library/addSysModelToLib`,
|
addSysModelToLib: `/aida/api/library/addSysModelToLib`,
|
||||||
poselikeOrDisike: `/api/generate/likeOrDislike`, //postTransform like
|
poselikeOrDisike: `/aida/api/generate/likeOrDislike`, //postTransform like
|
||||||
getAllPose: `/api/generate/getAllPose`, //获取动作
|
getAllPose: `/aida/api/generate/getAllPose`, //获取动作
|
||||||
|
|
||||||
//拼贴
|
//拼贴
|
||||||
genSketchRecon: `/api/generate/genSketchRecon`,
|
genSketchRecon: `/aida/api/generate/genSketchRecon`,
|
||||||
saveReconCanvas: `/api/generate/saveReconCanvas`,
|
saveReconCanvas: `/aida/api/generate/saveReconCanvas`,
|
||||||
|
|
||||||
//动作变换
|
//动作变换
|
||||||
poseTransform: `/api/generate/poseTransform`,
|
poseTransform: `/aida/api/generate/poseTransform`,
|
||||||
poseTransformResult: `/api/generate/poseTransformResult`,
|
poseTransformResult: `/aida/api/generate/poseTransformResult`,
|
||||||
|
|
||||||
batchUpdateLibraryName: '/api/library/batchUpdateLibraryName', //Library修改用户文件名
|
batchUpdateLibraryName: '/aida/api/library/batchUpdateLibraryName', //Library修改用户文件名
|
||||||
batchDeleteLibrary: '/api/library/batchDeleteLibrary', //删除library
|
batchDeleteLibrary: '/aida/api/library/batchDeleteLibrary', //删除library
|
||||||
queryLibraryTopAndBottomPage: '/api/library/queryLibraryTopAndBottomPage', //Library分页列表(查询top和bottom)
|
queryLibraryTopAndBottomPage: '/aida/api/library/queryLibraryTopAndBottomPage', //Library分页列表(查询top和bottom)
|
||||||
saveOrEditTemplatePoint: '/api/library/saveOrEditTemplatePoint', //保存或者编辑template打点
|
saveOrEditTemplatePoint: '/aida/api/library/saveOrEditTemplatePoint', //保存或者编辑template打点
|
||||||
libraryModelsDot: '/api/library/modelsDot', //Models打点预览
|
libraryModelsDot: '/aida/api/library/modelsDot', //Models打点预览
|
||||||
chatStreamTest: `/api/python/chatStream`, //机器人助力
|
chatStreamTest: `/aida/api/python/chatStream`, //机器人助力
|
||||||
pictureLikeOrUnLike: `/api/python/pictureLikeOrUnLike`, //机器人生成图喜欢
|
pictureLikeOrUnLike: `/aida/api/python/pictureLikeOrUnLike`, //机器人生成图喜欢
|
||||||
getBloodBars: `/api/python/getBloodBars`, //机器人血条
|
getBloodBars: `/aida/api/python/getBloodBars`, //机器人血条
|
||||||
//工作空间
|
//工作空间
|
||||||
workspaceDetail: `/api/workspace/detail`, //用户习惯详情
|
workspaceDetail: `/aida/api/workspace/detail`, //用户习惯详情
|
||||||
workspaceenumValues: `/api/workspace/enumValues`, //getSex
|
workspaceenumValues: `/aida/api/workspace/enumValues`, //getSex
|
||||||
|
|
||||||
workspaceRemove: `/api/workspace/remove`, //删除用户习惯详情
|
workspaceRemove: `/aida/api/workspace/remove`, //删除用户习惯详情
|
||||||
workspacesaveOrUpdate: `/api/workspace/saveOrUpdate`, //修改用户习惯详情
|
workspacesaveOrUpdate: `/aida/api/workspace/saveOrUpdate`, //修改用户习惯详情
|
||||||
getMannequins: `/api/workspace/getMannequins`, //模特
|
getMannequins: `/aida/api/workspace/getMannequins`, //模特
|
||||||
getStyleList: `/api/workspace/styleList`, //获取所有风格列表
|
getStyleList: `/aida/api/workspace/styleList`, //获取所有风格列表
|
||||||
|
|
||||||
workspaceList: `/api/workspace/list`,
|
workspaceList: `/aida/api/workspace/list`,
|
||||||
sketchAndPrintGenerate: '/api/generate/sketchAndPrint', //sketchGenerate生成图片
|
sketchAndPrintGenerate: '/aida/api/generate/sketchAndPrint', //sketchGenerate生成图片
|
||||||
|
|
||||||
generatePrepare: '/api/generate/prepare', //开始生成generate图片
|
generatePrepare: '/aida/api/generate/prepare', //开始生成generate图片
|
||||||
generateStopWaiting: '/api/generate/stopWaiting', //取消生成
|
generateStopWaiting: '/aida/api/generate/stopWaiting', //取消生成
|
||||||
generateResult: '/api/generate/result', //获取生成结果
|
generateResult: '/aida/api/generate/result', //获取生成结果
|
||||||
generateLike: '/api/generate/like', //喜欢ganerate图片
|
generateLike: '/aida/api/generate/like', //喜欢ganerate图片
|
||||||
generateDislike: '/api/generate/dislike', //喜欢ganerate图片
|
generateDislike: '/aida/api/generate/dislike', //喜欢ganerate图片
|
||||||
imageToSketch: '/api/generate/imageToSketch', //成品图转为线稿
|
imageToSketch: '/aida/api/generate/imageToSketch', //成品图转为线稿
|
||||||
modifySketch: '/api/generate/modifySketch', //修改画布内容并且储存
|
modifySketch: '/aida/api/generate/modifySketch', //修改画布内容并且储存
|
||||||
|
|
||||||
elementUpload: `/api/element/upload`, //上传图片
|
elementUpload: `/aida/api/element/upload`, //上传图片
|
||||||
imageSegmentation: `/api/element/imageSegmentation`, //分割衣服
|
imageSegmentation: `/aida/api/element/imageSegmentation`, //分割衣服
|
||||||
convertRelightElement: `/api/history/convertRelightElement`, //toproduct复制到上传图片位置
|
convertRelightElement: `/aida/api/history/convertRelightElement`, //toproduct复制到上传图片位置
|
||||||
|
|
||||||
// oldHis:`/oldHis/history/queryUserGroup`,//上传图片
|
// oldHis:`/oldHis/history/queryUserGroup`,//上传图片
|
||||||
sketchBoardsBoundingBox: `/api/design/sketchBoardsBoundingBox`, //裁剪sketch图片
|
sketchBoardsBoundingBox: `/aida/api/design/sketchBoardsBoundingBox`, //裁剪sketch图片
|
||||||
|
|
||||||
trialOrderList: `/api/account/trialOrderList`, //获取审批列表
|
trialOrderList: `/aida/api/account/trialOrderList`, //获取审批列表
|
||||||
switchIsAutoApproval: `/api/account/switchIsAutoApproval`, //切换是否自动审批
|
switchIsAutoApproval: `/aida/api/account/switchIsAutoApproval`, //切换是否自动审批
|
||||||
getIsAutoApproval: `/api/account/getIsAutoApproval`, //获取是否自动审批
|
getIsAutoApproval: `/aida/api/account/getIsAutoApproval`, //获取是否自动审批
|
||||||
trialOrderApproval: `/api/account/trialOrderApproval`, //通过审批
|
trialOrderApproval: `/aida/api/account/trialOrderApproval`, //通过审批
|
||||||
trialOrderRefuse: `/api/account/trialOrderRefuse`, //拒绝审批
|
trialOrderRefuse: `/aida/api/account/trialOrderRefuse`, //拒绝审批
|
||||||
|
|
||||||
//管理员接口
|
//管理员接口
|
||||||
//查询所有试用用户
|
//查询所有试用用户
|
||||||
inquiryGetTrial: `/api/inquiry/getTrial`, //查询所有试用用户
|
inquiryGetTrial: `/aida/api/inquiry/getTrial`, //查询所有试用用户
|
||||||
getCities: `/api/inquiry/getCities`, //获取所有付款订单使用的国家
|
getCities: `/aida/api/inquiry/getCities`, //获取所有付款订单使用的国家
|
||||||
getUserInfo: `/api/inquiry/getUserInfo`, //查询所有用户
|
getUserInfo: `/aida/api/inquiry/getUserInfo`, //查询所有用户
|
||||||
queryTransaction: `/api/inquiry/queryTransaction`, //查询交易记录
|
queryTransaction: `/aida/api/inquiry/queryTransaction`, //查询交易记录
|
||||||
queryTransactionDownload: `/api/inquiry/queryTransaction/download`, //导出交易记录
|
queryTransactionDownload: `/aida/api/inquiry/queryTransaction/download`, //导出交易记录
|
||||||
createCoupon: `/api/stripe/createCoupon`, //创建优惠码
|
createCoupon: `/aida/api/stripe/createCoupon`, //创建优惠码
|
||||||
updatePromCodeInfo: `/api/stripe/updatePromCodeInfo`, //修改优惠码
|
updatePromCodeInfo: `/aida/api/stripe/updatePromCodeInfo`, //修改优惠码
|
||||||
getAllCoupons: `/api/stripe/getAllCoupons`, //查询优惠码列表
|
getAllCoupons: `/aida/api/stripe/getAllCoupons`, //查询优惠码列表
|
||||||
checkCoupon: `/api/stripe/checkCoupon`, //根据优惠码获取结算后的金额
|
checkCoupon: `/aida/api/stripe/checkCoupon`, //根据优惠码获取结算后的金额
|
||||||
deletePromCode: `/api/stripe/deletePromCode`, //删除优惠券
|
deletePromCode: `/aida/api/stripe/deletePromCode`, //删除优惠券
|
||||||
addOrganization: `/api/inquiry/addOrganization`, //添加企业版或者教育版
|
addOrganization: `/aida/api/inquiry/addOrganization`, //添加企业版或者教育版
|
||||||
queryOrganization: `/api/inquiry/queryOrganization`, //查询企业版或者教育版
|
queryOrganization: `/aida/api/inquiry/queryOrganization`, //查询企业版或者教育版
|
||||||
createSubscribePlan: '/api/subscription_plan/createPlan', // 创建订阅计划
|
createSubscribePlan: '/aida/api/subscription_plan/createPlan', // 创建订阅计划
|
||||||
deleteSubscribePlan: '/api/subscription_plan/deletePlan', // 删除订阅计划
|
deleteSubscribePlan: '/aida/api/subscription_plan/deletePlan', // 删除订阅计划
|
||||||
updateSubscribePlan: '/api/subscription_plan/updatePlan', // 修改订阅计划
|
updateSubscribePlan: '/aida/api/subscription_plan/updatePlan', // 修改订阅计划
|
||||||
searchAllSubscribePlan: '/api/subscription_plan/searchByPage', // 分页查询所有订阅计划
|
searchAllSubscribePlan: '/aida/api/subscription_plan/searchByPage', // 分页查询所有订阅计划
|
||||||
searchSubscribeByOrg: '/api/subscription_plan/searchByOrganizationIdAndStatus', // 不分页查询
|
searchSubscribeByOrg: '/aida/api/subscription_plan/searchByOrganizationIdAndStatus', // 不分页查询
|
||||||
switchSubscribePlan: '/api/subscription_plan/switchSubscriptionPlan', // 切换管理员订阅计划
|
switchSubscribePlan: '/aida/api/subscription_plan/switchSubscriptionPlan', // 切换管理员订阅计划
|
||||||
switchSubAccountSubscribePlan:
|
switchSubAccountSubscribePlan:
|
||||||
'/api/subscription_plan/switchSubAccSubscriptionPlan', // 切换子账号订阅计划
|
'/aida/api/subscription_plan/switchSubAccSubscriptionPlan', // 切换子账号订阅计划
|
||||||
|
|
||||||
//云生成
|
//云生成
|
||||||
designCloud: `/api/design/designCloud`, //创建云生成
|
designCloud: `/aida/api/design/designCloud`, //创建云生成
|
||||||
cloudPage: `/api/design/cloudPage`, //创建云生成
|
cloudPage: `/aida/api/design/cloudPage`, //创建云生成
|
||||||
cloudTaskDelete: `/api/design/cloudTaskDelete`, //删除云生成
|
cloudTaskDelete: `/aida/api/design/cloudTaskDelete`, //删除云生成
|
||||||
cloudTaskNameUpdate: `/api/design/cloudTaskNameUpdate`, //修改云生成名字
|
cloudTaskNameUpdate: `/aida/api/design/cloudTaskNameUpdate`, //修改云生成名字
|
||||||
getDesignCloudResult: `/api/design/getDesignCloudResult`, //查询这条云生成记录的所有内容
|
getDesignCloudResult: `/aida/api/design/getDesignCloudResult`, //查询这条云生成记录的所有内容
|
||||||
|
|
||||||
//企业版教育版管理员页面
|
//企业版教育版管理员页面
|
||||||
subAccountList: `/api/account/subAccountList`, //查询子账号
|
subAccountList: `/aida/api/account/subAccountList`, //查询子账号
|
||||||
addOrUpdateSubAccount: `/api/account/addOrUpdateSubAccount`, //添加子账号
|
addOrUpdateSubAccount: `/aida/api/account/addOrUpdateSubAccount`, //添加子账号
|
||||||
deleteSubAccount: `/api/account/deleteSubAccount`, //删除子账号
|
deleteSubAccount: `/aida/api/account/deleteSubAccount`, //删除子账号
|
||||||
subAccountImportExcelDownload: `/api/account/subAccountImportExcelDownload`, //批量添加模板下载模板
|
subAccountImportExcelDownload: `/aida/api/account/subAccountImportExcelDownload`, //批量添加模板下载模板
|
||||||
exportAccountsToExcel: `/api/account/exportAccountsToExcel`, //教育版导出用户数据
|
exportAccountsToExcel: `/aida/api/account/exportAccountsToExcel`, //教育版导出用户数据
|
||||||
getNextSequence: `/api/project/getNextSequence`, //批量添加模板下载模板
|
getNextSequence: `/aida/api/project/getNextSequence`, //批量添加模板下载模板
|
||||||
subAccountImport: `/api/account/subAccountImport`, //模板导入
|
subAccountImport: `/aida/api/account/subAccountImport`, //模板导入
|
||||||
getGenerateFrequency: `/api/inquiry/getGenerateFrequency`, //积分使用详情
|
getGenerateFrequency: `/aida/api/inquiry/getGenerateFrequency`, //积分使用详情
|
||||||
getAllGenerateFuncName: `/api/inquiry/getAllGenerateFuncName`, //获取所有generate类型
|
getAllGenerateFuncName: `/aida/api/inquiry/getAllGenerateFuncName`, //获取所有generate类型
|
||||||
|
|
||||||
//查询某个时间内design点击次数
|
//查询某个时间内design点击次数
|
||||||
getDesignStatistic: `/api/inquiry/getDesignStatistic`, //拒绝审批
|
getDesignStatistic: `/aida/api/inquiry/getDesignStatistic`, //拒绝审批
|
||||||
getAllQuestionnaire: `/api/inquiry/getAllQuestionnaire`, //拒绝审批
|
getAllQuestionnaire: `/aida/api/inquiry/getAllQuestionnaire`, //拒绝审批
|
||||||
getActiveUserFunc: `/api/inquiry/getActiveUserFunc`, //获取各模块功能
|
getActiveUserFunc: `/aida/api/inquiry/getActiveUserFunc`, //获取各模块功能
|
||||||
toProductImageElementDelete: `/api/history/toProductImageElementDelete`, //删除指定模块上传的内容
|
toProductImageElementDelete: `/aida/api/history/toProductImageElementDelete`, //删除指定模块上传的内容
|
||||||
recentActiveUser: `/api/inquiry/recentActiveUser`, //获取近期活跃用户
|
recentActiveUser: `/aida/api/inquiry/recentActiveUser`, //获取近期活跃用户
|
||||||
recentActiveUserChart: `/api/inquiry/recentActiveUserChart`, //获取近期活跃用户图表数据
|
recentActiveUserChart: `/aida/api/inquiry/recentActiveUserChart`, //获取近期活跃用户图表数据
|
||||||
recentNewUser: `/api/inquiry/recentNewUser`, //获取近期新增用户
|
recentNewUser: `/aida/api/inquiry/recentNewUser`, //获取近期新增用户
|
||||||
recentNewUserChart: `/api/inquiry/recentNewUserChart`, //获取新增用户图表
|
recentNewUserChart: `/aida/api/inquiry/recentNewUserChart`, //获取新增用户图表
|
||||||
trialUserCountry: `/api/inquiry/trialUserCountry`, //试用用户国家-城市分布
|
trialUserCountry: `/aida/api/inquiry/trialUserCountry`, //试用用户国家-城市分布
|
||||||
conversionRate: `/api/inquiry/conversionRate`, //试用用户国家-城市分布
|
conversionRate: `/aida/api/inquiry/conversionRate`, //试用用户国家-城市分布
|
||||||
getAllUserId: `/api/inquiry/getAllUserId`, //获取所有用户id和Name
|
getAllUserId: `/aida/api/inquiry/getAllUserId`, //获取所有用户id和Name
|
||||||
adminAddUser: `/api/inquiry/addUser`, //添加用户
|
adminAddUser: `/aida/api/inquiry/addUser`, //添加用户
|
||||||
modifyUser: `/api/inquiry/modifyUser`, //修改用户
|
modifyUser: `/aida/api/inquiry/modifyUser`, //修改用户
|
||||||
publishSysMessage: `/api/message/publishSysMessage`, //发布系统任务
|
publishSysMessage: `/aida/api/message/publishSysMessage`, //发布系统任务
|
||||||
//affiliate接口
|
//affiliate接口
|
||||||
viewsIncrease: `/api/affiliate/viewsIncrease`, //增加访问量
|
viewsIncrease: `/aida/api/affiliate/viewsIncrease`, //增加访问量
|
||||||
affiliateRegistration: `/api/affiliate/registration`, //affiliate注册
|
affiliateRegistration: `/aida/api/affiliate/registration`, //affiliate注册
|
||||||
personalCenter: `/api/affiliate/personalCenter`, //affiliate个人中心
|
personalCenter: `/aida/api/affiliate/personalCenter`, //affiliate个人中心
|
||||||
affiliateList: `/api/affiliate/list`, //affiliate审批列表
|
affiliateList: `/aida/api/affiliate/list`, //affiliate审批列表
|
||||||
updateCommission: `/api/affiliate/updateCommission`, //编辑佣金比例
|
updateCommission: `/aida/api/affiliate/updateCommission`, //编辑佣金比例
|
||||||
editAffiliate: `/api/affiliate/editAffiliate`, //编辑affiliate
|
editAffiliate: `/aida/api/affiliate/editAffiliate`, //编辑affiliate
|
||||||
getEachAffiliateGeneratedRevenue: `/api/affiliate/getEachAffiliateGeneratedRevenue`, //affiliate每个用户根据日期查询收益
|
getEachAffiliateGeneratedRevenue: `/aida/api/affiliate/getEachAffiliateGeneratedRevenue`, //affiliate每个用户根据日期查询收益
|
||||||
affiliateApproval: `/api/affiliate/approval`, //affiliate同意 审批
|
affiliateApproval: `/aida/api/affiliate/approval`, //affiliate同意 审批
|
||||||
getPersonalMonthlyIncome: `/api/affiliate/getPersonalMonthlyIncome`, //affiliate图表接口
|
getPersonalMonthlyIncome: `/aida/api/affiliate/getPersonalMonthlyIncome`, //affiliate图表接口
|
||||||
getReferrals: `/api/affiliate/getReferrals`, //affiliate Referral列表
|
getReferrals: `/aida/api/affiliate/getReferrals`, //affiliate Referral列表
|
||||||
editReferral: `/api/affiliate/editReferral`, //affiliate编辑referral
|
editReferral: `/aida/api/affiliate/editReferral`, //affiliate编辑referral
|
||||||
batchDeleteReferral: `/api/affiliate/batchDeleteReferral`, //affiliate删除referral
|
batchDeleteReferral: `/aida/api/affiliate/batchDeleteReferral`, //affiliate删除referral
|
||||||
// batchDeleteReferral:`/api/affiliate/batchDeleteReferral`,//affiliate删除referral
|
// batchDeleteReferral:`/aida/api/affiliate/batchDeleteReferral`,//affiliate删除referral
|
||||||
|
|
||||||
getTasksList: `/api/tasks/getList`, //获取w为执行完的所有任务
|
getTasksList: `/aida/api/tasks/getList`, //获取w为执行完的所有任务
|
||||||
getTasksHistory: `/api/tasks/getAllTask`, //获取所有任务列表
|
getTasksHistory: `/aida/api/tasks/getAllTask`, //获取所有任务列表
|
||||||
prepareForSR: `/api/python/prepareForSR`, //超分
|
prepareForSR: `/aida/api/python/prepareForSR`, //超分
|
||||||
|
|
||||||
//作品广场
|
//作品广场
|
||||||
publish: `/api/portfolio/publish`, //发布作品到作品广场
|
publish: `/aida/api/portfolio/publish`, //发布作品到作品广场
|
||||||
getPorfolio: `/api/portfolio/page`, //查询作品广场
|
getPorfolio: `/aida/api/portfolio/page`, //查询作品广场
|
||||||
getPorfolioDetail: `/api/portfolio/detail`, //查询作品广场作品详情
|
getPorfolioDetail: `/aida/api/portfolio/detail`, //查询作品广场作品详情
|
||||||
setPorfolioChoose: `/api/portfolio/choose`, //二次创作
|
setPorfolioChoose: `/aida/api/portfolio/choose`, //二次创作
|
||||||
portfolioLike: `/api/portfolio/like`, //作品广场点赞
|
portfolioLike: `/aida/api/portfolio/like`, //作品广场点赞
|
||||||
portfolioNoLike: `/api/portfolio/unlike`, //作品广场取消点赞
|
portfolioNoLike: `/aida/api/portfolio/unlike`, //作品广场取消点赞
|
||||||
portfolioComment: `/api/portfolio/comment`, //作品广场评论
|
portfolioComment: `/aida/api/portfolio/comment`, //作品广场评论
|
||||||
portfolioCommentPage: `/api/portfolio/commentPage`, //作品广场评论列表
|
portfolioCommentPage: `/aida/api/portfolio/commentPage`, //作品广场评论列表
|
||||||
commentDelete: `/api/portfolio/commentDelete`, //删除评论
|
commentDelete: `/aida/api/portfolio/commentDelete`, //删除评论
|
||||||
porfolioDelete: `/api/portfolio/delete`, //删除作品
|
porfolioDelete: `/aida/api/portfolio/delete`, //删除作品
|
||||||
porfolioFollow: `/api/portfolio/follow`, //删除作品
|
porfolioFollow: `/aida/api/portfolio/follow`, //删除作品
|
||||||
porfolioFollow: `/api/portfolio/follow`, //关注
|
porfolioFollow: `/aida/api/portfolio/follow`, //关注
|
||||||
porfolioCancelFollow: `/api/portfolio/cancelFollow`, //取消关注
|
porfolioCancelFollow: `/aida/api/portfolio/cancelFollow`, //取消关注
|
||||||
porfolioGetFolloweeList: `/api/portfolio/getFolloweeList`, //获取关注列表
|
porfolioGetFolloweeList: `/aida/api/portfolio/getFolloweeList`, //获取关注列表
|
||||||
porfolioGetFollowerList: `/api/portfolio/getFollowerList`, //获取粉丝列表
|
porfolioGetFollowerList: `/aida/api/portfolio/getFollowerList`, //获取粉丝列表
|
||||||
|
|
||||||
//product生成
|
//product生成
|
||||||
toProduct: `/api/history/toProduct`, //开始生成
|
toProduct: `/aida/api/history/toProduct`, //开始生成
|
||||||
toProductImageResult: `/api/history/toProductImageResult`, //获取结果
|
toProductImageResult: `/aida/api/history/toProductImageResult`, //获取结果
|
||||||
toProductImageElementUpload: `/api/history/toProductImageElementUpload`, //上传
|
toProductImageElementUpload: `/aida/api/history/toProductImageElementUpload`, //上传
|
||||||
historyDeleteResult: `/api/history/deleteResult`, //relight toproduct删除
|
historyDeleteResult: `/aida/api/history/deleteResult`, //relight toproduct删除
|
||||||
generateDeleteResult: `/api/generate/deleteResult`, //pose删除
|
generateDeleteResult: `/aida/api/generate/deleteResult`, //pose删除
|
||||||
|
|
||||||
productImageLike: `/api/history/productImageLike`, //like生成结果
|
productImageLike: `/aida/api/history/productImageLike`, //like生成结果
|
||||||
productImageUnLike: `/api/history/productImageUnLike`, //取消like生成结果
|
productImageUnLike: `/aida/api/history/productImageUnLike`, //取消like生成结果
|
||||||
productImageLikeList: `/api/history/productImageLikeList`, //like生成结果
|
productImageLikeList: `/aida/api/history/productImageLikeList`, //like生成结果
|
||||||
|
|
||||||
//打光
|
//打光
|
||||||
relight: `/api/history/relight`, //开始生成
|
relight: `/aida/api/history/relight`, //开始生成
|
||||||
relightResult: `/api/history/relightResult`, //开始生成
|
relightResult: `/aida/api/history/relightResult`, //开始生成
|
||||||
|
|
||||||
//保存画布
|
//保存画布
|
||||||
canvasElementUpload: `/api/history/canvasElementUpload`, //画布上传临时图片
|
canvasElementUpload: `/aida/api/history/canvasElementUpload`, //画布上传临时图片
|
||||||
exportSave: `/api/history/exportSave`, //保存画布
|
exportSave: `/aida/api/history/exportSave`, //保存画布
|
||||||
exportSearch: `/api/history/exportSearch`, //保存画布
|
exportSearch: `/aida/api/history/exportSearch`, //保存画布
|
||||||
|
|
||||||
//活动
|
//活动
|
||||||
activity: `/api/account/activity`,
|
activity: `/aida/api/account/activity`,
|
||||||
|
|
||||||
//bradDNA
|
//bradDNA
|
||||||
brandLogoUpload: `/api/history/brandLogoUpload`, //上传bradDNA
|
brandLogoUpload: `/aida/api/history/brandLogoUpload`, //上传bradDNA
|
||||||
brandDNAGenerate: `/api/history/brandDNAGenerate`, //上传bradDNA
|
brandDNAGenerate: `/aida/api/history/brandDNAGenerate`, //上传bradDNA
|
||||||
brandDNAUpload: `/api/history/brandDNAUpload`, //上传DNA图片
|
brandDNAUpload: `/aida/api/history/brandDNAUpload`, //上传DNA图片
|
||||||
getInitializeProgress: `/api/history/getInitializeProgress`, //获取brand进度
|
getInitializeProgress: `/aida/api/history/getInitializeProgress`, //获取brand进度
|
||||||
brandDNADelete: `/api/history/brandDNADelete`, //删除brandDna
|
brandDNADelete: `/aida/api/history/brandDNADelete`, //删除brandDna
|
||||||
|
|
||||||
brandDNAPage: `/api/history/brandDNAPage`, //brand列表
|
brandDNAPage: `/aida/api/history/brandDNAPage`, //brand列表
|
||||||
brandDNASaveOrUpdate: `/api/history/brandDNASaveOrUpdate`, //提交个人信息
|
brandDNASaveOrUpdate: `/aida/api/history/brandDNASaveOrUpdate`, //提交个人信息
|
||||||
productImageInitialize: `/api/history/productImageInitialize`, //产品识别
|
productImageInitialize: `/aida/api/history/productImageInitialize`, //产品识别
|
||||||
//调查问卷
|
//调查问卷
|
||||||
questionnaire: `/api/account/questionnaire`, //保存画布
|
questionnaire: `/aida/api/account/questionnaire`, //保存画布
|
||||||
|
|
||||||
//消息系统
|
//消息系统
|
||||||
getUnreadCount: `/api/message/getUnreadCount`, //获取未读消息
|
getUnreadCount: `/aida/api/message/getUnreadCount`, //获取未读消息
|
||||||
setReadStatus: `/api/message/setReadStatus`, //设置消息已读
|
setReadStatus: `/aida/api/message/setReadStatus`, //设置消息已读
|
||||||
getHistoryNotification: `/api/message/getHistoryNotification`, //获取历史消息
|
getHistoryNotification: `/aida/api/message/getHistoryNotification`, //获取历史消息
|
||||||
oneClickRead: `/api/message/oneClickRead`, //全部设为已读
|
oneClickRead: `/aida/api/message/oneClickRead`, //全部设为已读
|
||||||
personalHomepage: `/api/account/personalHomepage`, //获取个人主页信息
|
personalHomepage: `/aida/api/account/personalHomepage`, //获取个人主页信息
|
||||||
refreshMinioUrl: `/api/third/party/refreshMinioUrl`, //获取可以使用的minio地址
|
refreshMinioUrl: `/aida/api/third/party/refreshMinioUrl`, //获取可以使用的minio地址
|
||||||
|
|
||||||
// 画布
|
// 画布
|
||||||
segAnything: `/api/python/segAnything`, //分割Anything
|
segAnything: `/aida/api/python/segAnything`, //分割Anything
|
||||||
|
|
||||||
// award页面
|
// award页面
|
||||||
checkEmail: '/api/global-award/checkEmail', // 检查邮箱是否存在
|
checkEmail: '/aida/api/global-award/checkEmail', // 检查邮箱是否存在
|
||||||
checkOTP: '/api/global-award/checkCode', // 检查验证码是否正确
|
checkOTP: '/aida/api/global-award/checkCode', // 检查验证码是否正确
|
||||||
initPdfUpload: '/api/global-award/uploads/pdf/init', // 初始化pdf上传
|
initPdfUpload: '/aida/api/global-award/uploads/pdf/init', // 初始化pdf上传
|
||||||
initVideoUpload: '/api/global-award/uploads/video/init', // 初始化video上传
|
initVideoUpload: '/aida/api/global-award/uploads/video/init', // 初始化video上传
|
||||||
uploadPDF: '/api/global-award/uploads/pdf/chunk', // 上传pdf
|
uploadPDF: '/aida/api/global-award/uploads/pdf/chunk', // 上传pdf
|
||||||
uploadVideo: '/api/global-award/uploads/video/chunk', // 上传video
|
uploadVideo: '/aida/api/global-award/uploads/video/chunk', // 上传video
|
||||||
uploadPDFComplete: '/api/global-award/uploads/pdf/complete', // 上传pdf完成
|
uploadPDFComplete: '/aida/api/global-award/uploads/pdf/complete', // 上传pdf完成
|
||||||
uploadVideoComplete: '/api/global-award/uploads/video/complete', // 上传video完成
|
uploadVideoComplete: '/aida/api/global-award/uploads/video/complete', // 上传video完成
|
||||||
submitForm: '/api/global-award/contestants/save', // 提交表单
|
submitForm: '/aida/api/global-award/contestants/save', // 提交表单
|
||||||
getContestantByID: '/api/global-award/contestants/', // 获取表单
|
getContestantByID: '/aida/api/global-award/contestants/', // 获取表单
|
||||||
|
|
||||||
|
|
||||||
// 卖家端接口
|
// 卖家端接口
|
||||||
|
sellerUploadFile: '/seller/file/upload', // 卖家上传文件
|
||||||
checkSellerDesigner: '/seller/designer/check', // 检查卖家是否为设计师
|
checkSellerDesigner: '/seller/designer/check', // 检查卖家是否为设计师
|
||||||
getSellerApplyStatus: '/seller/designer/apply/status', // 获取卖家申请状态
|
getSellerApplyStatus: '/seller/designer/apply/status', // 获取卖家申请状态
|
||||||
submitSellerApply: '/seller/designer/apply', // 提交卖家申请
|
submitSellerApply: '/seller/designer/apply', // 提交卖家申请
|
||||||
|
deleteSellerDesigner: '/seller/designer/delete', // 删除设计师
|
||||||
getDesignerInfo: '/seller/designer/info', // 获取设计师信息
|
getDesignerInfo: '/seller/designer/info', // 获取设计师信息
|
||||||
updateDesignerInfo: '/seller/designer/update', // 更新设计师信息
|
updateDesignerInfo: '/seller/designer/update', // 更新设计师信息
|
||||||
getSellerOrderSummary: '/seller/order/summary', // 获取卖家订单数据总览
|
getSellerOrderSummary: '/seller/order/summary', // 获取卖家订单数据总览
|
||||||
getSellerOrderList: '/seller/order/page', // 获取卖家订单列表
|
getSellerOrderList: '/seller/order/page', // 获取卖家订单列表
|
||||||
getListingPopup: '/seller/listing/popup/check', // 获取是否勾选发布作品提示
|
getListingPopup: '/seller/listing/popup/check', // 获取是否勾选发布作品提示
|
||||||
setListingPopup: '/seller/listing/popup/set', // 设置是否勾选发布作品提示
|
setListingPopup: '/seller/listing/popup/set', // 设置是否勾选发布作品提示
|
||||||
|
getListingList: '/seller/listing/page', // 获取商品列表,发布和未发布
|
||||||
|
putListingStatus: '/seller/listing/status', // 更新商品状态
|
||||||
},
|
},
|
||||||
|
|
||||||
axiosGet(url, config, pathParams) {
|
axiosGet(url, config, pathParams) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (isLoginTime && url != '/api/portfolio/page') {
|
if (isLoginTime && url != '/aida/api/portfolio/page') {
|
||||||
resolve('')
|
resolve('')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -506,7 +501,7 @@ export const Https = {
|
|||||||
|
|
||||||
axiosPut(url, data, pathParams) {
|
axiosPut(url, data, pathParams) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (isLoginTime && url != '/api/portfolio/page') {
|
if (isLoginTime && url != '/aida/api/portfolio/page') {
|
||||||
resolve('')
|
resolve('')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -523,7 +518,7 @@ export const Https = {
|
|||||||
|
|
||||||
axiosPost(url, data, config, pathParams) {
|
axiosPost(url, data, config, pathParams) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (isLoginTime && url != '/api/portfolio/page') {
|
if (isLoginTime && url != '/aida/api/portfolio/page') {
|
||||||
resolve('')
|
resolve('')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -540,7 +535,7 @@ export const Https = {
|
|||||||
|
|
||||||
axiosDelete(url, newData, pathParams) {
|
axiosDelete(url, newData, pathParams) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (isLoginTime && url != '/api/portfolio/page') {
|
if (isLoginTime && url != '/aida/api/portfolio/page') {
|
||||||
resolve('')
|
resolve('')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -318,7 +318,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="homeMain_user">
|
<div class="homeMain_user">
|
||||||
<div class="homeMain_user_icon" @click="openAccount">
|
<div class="homeMain_user_icon">
|
||||||
<img :src="userDetail.avatar" alt="" />
|
<img :src="userDetail.avatar" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div class="homeMain_user_detail">
|
<div class="homeMain_user_detail">
|
||||||
@@ -373,6 +373,10 @@
|
|||||||
<i class="fi fi-rs-notebook"></i>
|
<i class="fi fi-rs-notebook"></i>
|
||||||
<span class="select_item_des">{{ $t('Header.ViewOrders') }}</span>
|
<span class="select_item_des">{{ $t('Header.ViewOrders') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="select_item" @click="openAccount">
|
||||||
|
<span class="icon"><svg-icon name="home" /></span>
|
||||||
|
<span class="select_item_des">{{ $t('Header.PersonalCenter') }}</span>
|
||||||
|
</div>
|
||||||
<div class="select_item" @click="onBecomeSeller" v-if="!isSeller">
|
<div class="select_item" @click="onBecomeSeller" v-if="!isSeller">
|
||||||
<span class="icon"><svg-icon name="seller-sellerIndex" /></span>
|
<span class="icon"><svg-icon name="seller-sellerIndex" /></span>
|
||||||
<span class="select_item_des">{{ $t('Header.BecomeSeller') }}</span>
|
<span class="select_item_des">{{ $t('Header.BecomeSeller') }}</span>
|
||||||
|
|||||||
@@ -338,7 +338,7 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
class="search_upImg"
|
class="search_upImg"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:before-upload="beforeUpload"
|
:before-upload="beforeUpload"
|
||||||
:data="{
|
:data="{
|
||||||
@@ -387,7 +387,7 @@
|
|||||||
<a-upload
|
<a-upload
|
||||||
class="search_upImg"
|
class="search_upImg"
|
||||||
:capture="null"
|
:capture="null"
|
||||||
:action="uploadUrl + '/api/element/upload'"
|
:action="uploadUrl + '/aida/api/element/upload'"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:data="{
|
:data="{
|
||||||
...upload,
|
...upload,
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="become-seller">
|
<div class="become-seller">
|
||||||
<seller-header
|
<seller-header />
|
||||||
title="Apply to Become a Seller"
|
|
||||||
tip="Join the Stylish Parade and start selling your design work"
|
|
||||||
/>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<seller-apply v-if="applyStatus === null" @submit="onSubmit" />
|
<seller-apply v-if="applyStatus === null" @submit="onSubmit" />
|
||||||
<seller-review v-else />
|
<seller-review v-else />
|
||||||
|
|||||||
@@ -2,56 +2,58 @@
|
|||||||
<div class="seller-apply">
|
<div class="seller-apply">
|
||||||
<div class="session">
|
<div class="session">
|
||||||
<div class="content mini-scrollbar">
|
<div class="content mini-scrollbar">
|
||||||
<div class="title">Brand Information</div>
|
<div class="title">{{ $t("ApplySeller.formTitle") }}</div>
|
||||||
<div class="tip">Share a few details to set up your seller profile</div>
|
<div class="tip">{{ $t("ApplySeller.formTip") }}</div>
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<a-form :model="formData" :rules="formRules" layout="vertical" ref="formRef">
|
<a-form :model="formData" :rules="formRules" layout="vertical" ref="formRef">
|
||||||
<a-form-item label="Store Name" name="storeName">
|
<a-form-item :label="$t('Seller.storeName')" name="storeName">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="formData.storeName"
|
v-model:value="formData.storeName"
|
||||||
placeholder="Enter the store name"
|
:placeholder="$t('Seller.storeNameDesc')"
|
||||||
:maxlength="80"
|
:maxlength="80"
|
||||||
/>
|
/>
|
||||||
<span class="tip-length">{{ formData.storeName.length }}/80</span>
|
<span class="tip-length">{{ formData.storeName.length }}/80</span>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Owner’s Full Name" name="fullName">
|
<a-form-item :label="$t('Seller.ownerName')" name="fullName">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="formData.fullName"
|
v-model:value="formData.fullName"
|
||||||
placeholder="Enter store owner's full name"
|
:placeholder="$t('Seller.ownerNameDesc')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<a-form-item label="Email" name="email">
|
<a-form-item :label="$t('Seller.email')" name="email">
|
||||||
<a-input
|
<a-input
|
||||||
type="email"
|
type="email"
|
||||||
v-model:value="formData.email"
|
v-model:value="formData.email"
|
||||||
placeholder="Enter email"
|
:placeholder="$t('Seller.emailDesc')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Phone Number" name="phoneNumber">
|
<a-form-item :label="$t('Seller.mobile')" name="mobile">
|
||||||
<a-input
|
<a-input
|
||||||
type="tel"
|
type="tel"
|
||||||
v-model:value="formData.phoneNumber"
|
v-model:value="formData.mobile"
|
||||||
placeholder="Enter phone number"
|
:placeholder="$t('Seller.mobileDesc')"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</div>
|
</div>
|
||||||
<a-form-item label="Store Description" name="description">
|
<a-form-item :label="$t('Seller.storeDescription')" name="description">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
v-model:value="formData.description"
|
v-model:value="formData.description"
|
||||||
placeholder="Briefly describe your design style and store features..."
|
:placeholder="$t('Seller.storeDescriptionDesc')"
|
||||||
:maxlength="500"
|
:maxlength="500"
|
||||||
/>
|
/>
|
||||||
<span class="tip-length">{{ formData.description.length }}/500</span>
|
<span class="tip-length">{{ formData.description.length }}/500</span>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Portfoilo/Social Media Links">
|
<a-form-item :label="$t('Seller.links')">
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="https://"
|
placeholder="https://"
|
||||||
v-for="(v, i) in formData.links"
|
v-for="(v, i) in formData.links"
|
||||||
:key="i"
|
:key="i"
|
||||||
v-model:value="formData.links[i]"
|
v-model:value="formData.links[i]"
|
||||||
>
|
>
|
||||||
<template #prefix>Link {{ i + 1 }}</template>
|
<template #prefix>{{
|
||||||
|
$t("Seller.link", { index: i + 1 })
|
||||||
|
}}</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="https://"
|
placeholder="https://"
|
||||||
@@ -71,33 +73,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="session">
|
<div class="session">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="title">Brand Information</div>
|
<div class="title">{{ $t("ApplySeller.termsTitle") }}</div>
|
||||||
<div class="tip">Share a few details to set up your seller profile</div>
|
<div class="tip">{{ $t("ApplySeller.termsTip") }}</div>
|
||||||
<div class="agreement">
|
<div class="agreement">
|
||||||
<div class="title">AiDA Seller Agreement</div>
|
<div class="title">{{ $t("ApplySeller.agreementTitle") }}</div>
|
||||||
<div class="tip">
|
<div class="tip">{{ $t("ApplySeller.agreementTip") }}</div>
|
||||||
By checking the box below, you agree to comply with the following terms:
|
|
||||||
</div>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Provide accurate and truthful personal and store information</li>
|
<li v-for="(v, i) in 8" :key="i">
|
||||||
<li>Only sell original designs or content with proper licensing</li>
|
{{ $t(`ApplySeller.agreementItem${i + 1}`) }}
|
||||||
<li>Maintain high quality standards for all products</li>
|
</li>
|
||||||
<li>Respond to customer inquiries within 48 hours</li>
|
|
||||||
<li>Ship orders within promised timeframes</li>
|
|
||||||
<li>Comply with AiDA's terms of service and community guidelines</li>
|
|
||||||
<li>Pay applicable platform fees and transaction charges</li>
|
|
||||||
<li>Handle customer disputes professionally and fairly</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<a-checkbox class="agree-agreement" v-model:checked="isAgreement">
|
<a-checkbox class="agree-agreement" v-model:checked="isAgreement">
|
||||||
I have read and agree to the Seller Agreement, understanding my responsibilities
|
{{ $t("ApplySeller.agreementAgreement") }}
|
||||||
and obligations as a seller on the AiDA platform.
|
|
||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<button class="cancel" @click="onCancel">Cancel</button>
|
<button class="cancel" @click="onCancel">{{ $t("Seller.cancel") }}</button>
|
||||||
<button class="submit" :disabled="!isAgreement" @click="onSubmit">
|
<button class="submit" :disabled="!isAgreement" @click="onSubmit">
|
||||||
Submit Application
|
{{ $t("ApplySeller.submitApplication") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -106,24 +100,26 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive } from "vue"
|
import { ref, reactive } from "vue"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
import { useRoute, useRouter } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
import { Https } from "@/tool/https"
|
import { Https } from "@/tool/https"
|
||||||
const emit = defineEmits(["submit"])
|
const emit = defineEmits(["submit"])
|
||||||
const formRules = {
|
const formRules = {
|
||||||
storeName: [{ required: true, message: "Enter the store name" }],
|
storeName: [{ required: true, message: t("Seller.storeNameDesc") }],
|
||||||
fullName: [{ required: true, message: "Enter store owner's full name" }],
|
fullName: [{ required: true, message: t("Seller.ownerNameDesc") }],
|
||||||
email: [{ required: true, message: "Enter email" }],
|
email: [{ required: true, message: t("Seller.emailDesc") }],
|
||||||
phoneNumber: [{ required: true, message: "Enter phone number" }],
|
mobile: [{ required: true, message: t("Seller.mobileDesc") }],
|
||||||
description: [{ required: true, message: "Enter store description" }]
|
description: [{ required: true, message: t("Seller.storeDescriptionErr") }]
|
||||||
}
|
}
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
storeName: "",
|
storeName: "",
|
||||||
fullName: "",
|
fullName: "",
|
||||||
email: "",
|
email: "",
|
||||||
phoneNumber: "",
|
mobile: "",
|
||||||
description: "",
|
description: "",
|
||||||
links: ["", ""]
|
links: ["", ""]
|
||||||
})
|
})
|
||||||
@@ -140,7 +136,6 @@
|
|||||||
formRef.value
|
formRef.value
|
||||||
.validate()
|
.validate()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log(formData)
|
|
||||||
const data = {
|
const data = {
|
||||||
// userId: 0,
|
// userId: 0,
|
||||||
shopName: formData.storeName,
|
shopName: formData.storeName,
|
||||||
@@ -148,7 +143,7 @@
|
|||||||
// brandBanner: "",
|
// brandBanner: "",
|
||||||
ownerName: formData.fullName,
|
ownerName: formData.fullName,
|
||||||
email: formData.email,
|
email: formData.email,
|
||||||
mobile: formData.phoneNumber,
|
mobile: formData.mobile,
|
||||||
description: formData.description,
|
description: formData.description,
|
||||||
socialLinks: JSON.stringify(formData.links.filter((v) => v))
|
socialLinks: JSON.stringify(formData.links.filter((v) => v))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="seller-review">
|
<div class="seller-review">
|
||||||
<img class="success" src="@/assets/images/seller/success-1.png" />
|
<img class="success" src="@/assets/images/seller/success-1.png" />
|
||||||
<div class="title">Application Submitted</div>
|
<div class="title">{{ $t("ApplySeller.applicationSubmitted") }}</div>
|
||||||
<div class="tip">
|
<div
|
||||||
Our team will review your application and get back to you within 1–3 business days.
|
class="tip"
|
||||||
You'll receive a notification in your email once a decision has been made.
|
v-html="$t('ApplySeller.applicationSubmittedTip', { click: 'onPersonalCenter' })"
|
||||||
</div>
|
></div>
|
||||||
<div class="step-list">
|
<div class="step-list">
|
||||||
<div v-for="v in list" :key="v.title" class="step-item">
|
<div v-for="v in list" :key="v.title" class="step-item">
|
||||||
<img v-show="!v.active" src="@/assets/images/seller/success-0.png" />
|
<img v-show="!v.active" src="@/assets/images/seller/success-0.png" />
|
||||||
@@ -16,7 +16,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="home-btn" @click="onBackToHome">Back to Homepage</button>
|
<button class="home-btn" @click="onBackToHome">
|
||||||
|
{{ $t("ApplySeller.backToHomepage") }}
|
||||||
|
</button>
|
||||||
|
<div class="tip">ID: {{ userId }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -25,30 +28,37 @@
|
|||||||
import { useRoute, useRouter } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
import { useStore } from "vuex"
|
import { useStore } from "vuex"
|
||||||
import { ApplyStatus } from "@/store/seller/index.d"
|
import { ApplyStatus } from "@/store/seller/index.d"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
const userId = computed(() => store.state.UserHabit.userDetail.userId)
|
||||||
const applyStatus = computed(() => store.state.seller.applyStatus)
|
const applyStatus = computed(() => store.state.seller.applyStatus)
|
||||||
const list = computed(() => [
|
const list = computed(() => [
|
||||||
{
|
{
|
||||||
title: "Step 1: Submit Application",
|
title: t("ApplySeller.auditStatus1_title"),
|
||||||
tip: "Fill out the seller information form and agree to our terms",
|
tip: t("ApplySeller.auditStatus1_tip"),
|
||||||
active: [ApplyStatus.Pending, ApplyStatus.Approved].includes(applyStatus.value)
|
active: [ApplyStatus.Pending, ApplyStatus.Approved].includes(applyStatus.value)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Step 2: Review & Verification",
|
title: t("ApplySeller.auditStatus2_title"),
|
||||||
tip: "Our team will review your application (typically 1-3 business days)",
|
tip: t("ApplySeller.auditStatus2_tip"),
|
||||||
active: applyStatus.value === ApplyStatus.Approved
|
active: applyStatus.value === ApplyStatus.Approved
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Step 3: Start Selling",
|
title: t("ApplySeller.auditStatus3_title"),
|
||||||
tip: "Once approved, access your seller dashboard and start listing products ",
|
tip: t("ApplySeller.auditStatus3_tip"),
|
||||||
active: applyStatus.value === ApplyStatus.Approved
|
active: applyStatus.value === ApplyStatus.Approved
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
const onBackToHome = () => {
|
const onBackToHome = () => {
|
||||||
router.push({ name: "home" })
|
router.push({ name: "home" })
|
||||||
}
|
}
|
||||||
|
window.onPersonalCenter = () => {
|
||||||
|
router.push("/home/account")
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.seller-review {
|
.seller-review {
|
||||||
@@ -73,11 +83,15 @@
|
|||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
> .tip {
|
> .tip {
|
||||||
font-family: pingfang_medium;
|
font-family: pingfang_regular;
|
||||||
font-size: 1.8rem;
|
font-size: 1.8rem;
|
||||||
line-height: 170%;
|
line-height: 170%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #585858;
|
color: #585858;
|
||||||
|
&:deep(span) {
|
||||||
|
color: #585858;
|
||||||
|
font-family: pingfang_heavy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
> .step-list {
|
> .step-list {
|
||||||
margin: 2.6rem 0;
|
margin: 2.6rem 0;
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<div class="brand-info">
|
<div class="brand-info">
|
||||||
<a-form :model="formData" :rules="isEdit ? formRules : {}" layout="vertical" ref="formRef">
|
<a-form :model="formData" :rules="isEdit ? formRules : {}" layout="vertical" ref="formRef">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<a-form-item label="Store Name" name="shopName">
|
<a-form-item :label="$t('Seller.storeName')" name="shopName">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="formData.shopName"
|
v-model:value="formData.shopName"
|
||||||
placeholder="Enter the store name"
|
:placeholder="$t('Seller.storeNameDesc')"
|
||||||
:maxlength="80"
|
:maxlength="80"
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
/>
|
/>
|
||||||
@@ -13,34 +13,34 @@
|
|||||||
>{{ formData.shopName.length }}/80</span
|
>{{ formData.shopName.length }}/80</span
|
||||||
>
|
>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Owner’s Full Name" name="ownerName">
|
<a-form-item :label="$t('Seller.ownerName')" name="ownerName">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="formData.ownerName"
|
v-model:value="formData.ownerName"
|
||||||
placeholder="Enter store owner's full name"
|
:placeholder="$t('Seller.ownerNameDesc')"
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<a-form-item label="Email" name="email">
|
<a-form-item :label="$t('Seller.email')" name="email">
|
||||||
<a-input
|
<a-input
|
||||||
type="email"
|
type="email"
|
||||||
v-model:value="formData.email"
|
v-model:value="formData.email"
|
||||||
placeholder="Enter email"
|
:placeholder="$t('Seller.emailDesc')"
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Phone Number" name="mobile">
|
<a-form-item :label="$t('Seller.mobile')" name="mobile">
|
||||||
<a-input
|
<a-input
|
||||||
type="tel"
|
type="tel"
|
||||||
v-model:value="formData.mobile"
|
v-model:value="formData.mobile"
|
||||||
placeholder="Enter phone number"
|
:placeholder="$t('Seller.mobileDesc')"
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<a-form-item label="Portfoilo/Social Media Links">
|
<a-form-item :label="$t('Seller.links')">
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="https://"
|
placeholder="https://"
|
||||||
v-for="(v, i) in formData.socialLinks"
|
v-for="(v, i) in formData.socialLinks"
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
v-model:value="formData.socialLinks[i]"
|
v-model:value="formData.socialLinks[i]"
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
>
|
>
|
||||||
<template #prefix>Link {{ i + 1 }}</template>
|
<template #prefix>{{ $t("Seller.link", { index: i + 1 }) }}</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
<a-input
|
<a-input
|
||||||
placeholder="https://"
|
placeholder="https://"
|
||||||
@@ -63,10 +63,10 @@
|
|||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Store Description" name="description">
|
<a-form-item :label="$t('Seller.storeDescription')" name="description">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
v-model:value="formData.description"
|
v-model:value="formData.description"
|
||||||
placeholder="Briefly describe your design style and store features..."
|
:placeholder="$t('Seller.storeDescriptionDesc')"
|
||||||
:maxlength="500"
|
:maxlength="500"
|
||||||
:readonly="!isEdit"
|
:readonly="!isEdit"
|
||||||
/>
|
/>
|
||||||
@@ -83,6 +83,9 @@
|
|||||||
import { ref, reactive, watch } from "vue"
|
import { ref, reactive, watch } from "vue"
|
||||||
import { useRoute, useRouter } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
import { useStore } from "vuex"
|
import { useStore } from "vuex"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const designerInfo = computed(() => store.state.seller.designerInfo)
|
const designerInfo = computed(() => store.state.seller.designerInfo)
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -94,11 +97,11 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const formRules = {
|
const formRules = {
|
||||||
shopName: [{ required: true, message: "Enter the store name" }],
|
shopName: [{ required: true, message: t("Seller.storeNameDesc") }],
|
||||||
ownerName: [{ required: true, message: "Enter store owner's full name" }],
|
ownerName: [{ required: true, message: t("Seller.ownerNameDesc") }],
|
||||||
email: [{ required: true, message: "Enter email" }],
|
email: [{ required: true, message: t("Seller.emailDesc") }],
|
||||||
mobile: [{ required: true, message: "Enter phone number" }],
|
mobile: [{ required: true, message: t("Seller.mobileDesc") }],
|
||||||
description: [{ required: true, message: "Enter store description" }]
|
description: [{ required: true, message: t("Seller.storeDescriptionErr") }]
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
|
|||||||
@@ -10,15 +10,35 @@
|
|||||||
:closable="false"
|
:closable="false"
|
||||||
wrapClassName="#app"
|
wrapClassName="#app"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
|
:destroyOnClose="true"
|
||||||
>
|
>
|
||||||
<div class="image-clip-dialog-box">
|
<div class="image-clip-dialog-box">
|
||||||
<div class="header" :class="{ 'is-product': data.isProduct }">
|
<div class="header" :class="{ 'is-product': data.isProduct }">
|
||||||
<div class="title">{{ data.title }}</div>
|
<div class="title">{{ data.title }}</div>
|
||||||
<div class="right">
|
<div class="right flex">
|
||||||
|
<div v-if="coverOrigin.length > 1" class="origin-container flex align-center">
|
||||||
|
<span>{{ $t("Seller.cropFrom") }}</span>
|
||||||
|
<div class="origin-select flex align-center">
|
||||||
|
<div
|
||||||
|
class="origin-item sketch"
|
||||||
|
:class="{ selected: currentOrigin === 'sketch' }"
|
||||||
|
@click="handleChangeOrigin('sketch')"
|
||||||
|
>
|
||||||
|
{{ $t("Seller.sketch") }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="origin-item product"
|
||||||
|
:class="{ selected: currentOrigin === 'mainProductImage' }"
|
||||||
|
@click="handleChangeOrigin('mainProductImage')"
|
||||||
|
>
|
||||||
|
{{ $t("Seller.mainProductImage") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="submit" v-if="!data.isPreview" @click="onSubmit">
|
<div class="submit" v-if="!data.isPreview" @click="onSubmit">
|
||||||
<svg-icon name="seller-dui" size="24" />
|
<svg-icon name="seller-dui" size="24" />
|
||||||
</div>
|
</div>
|
||||||
<button @click="onCancel">Cancel</button>
|
<button @click="onCancel">{{ $t("Seller.cancel") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" :class="{ 'is-product': data.isProduct }">
|
<div class="content" :class="{ 'is-product': data.isProduct }">
|
||||||
@@ -28,7 +48,7 @@
|
|||||||
ref="imageClipRef"
|
ref="imageClipRef"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:ratio="data.ratio"
|
:ratio="data.ratio"
|
||||||
:fixedBox="data.isProduct ? type !== 'apparel' : false"
|
:isProduct="isProduct"
|
||||||
:url="data.url"
|
:url="data.url"
|
||||||
:type="type"
|
:type="type"
|
||||||
@change="(v) => (data.preview_url = v)"
|
@change="(v) => (data.preview_url = v)"
|
||||||
@@ -45,7 +65,7 @@
|
|||||||
>
|
>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<span class="icon"><svg-icon name="seller-preview" size="24" /></span>
|
<span class="icon"><svg-icon name="seller-preview" size="24" /></span>
|
||||||
<span class="label">Crop Preview</span>
|
<span class="label">{{ $t("Seller.cropPreview") }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="preview-image">
|
<div class="preview-image">
|
||||||
<img :src="data.preview_url" />
|
<img :src="data.preview_url" />
|
||||||
@@ -60,32 +80,38 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from "vue"
|
import { ref, reactive, computed } from "vue"
|
||||||
import ImageClip from "./image-clip.vue"
|
import ImageClip from "./image-clip.vue"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
default: () => false
|
default: ""
|
||||||
|
},
|
||||||
|
isProduct: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const tips = computed(() => {
|
const tips = computed(() => {
|
||||||
if (props.type === "cover") {
|
if (props.type === "cover") {
|
||||||
return "Align crown to top, mid-thigh to bottom for best results."
|
return t("Seller.imageClipCoverTip")
|
||||||
}
|
}
|
||||||
if (props.type === "mainProductImage") {
|
if (props.type === "mainProductImage") {
|
||||||
return "Align crown to top, foot base to bottom for best results."
|
return t("Seller.imageClipMainProductImageTip")
|
||||||
}
|
}
|
||||||
if (props.type === "sketch") {
|
if (props.type === "sketch") {
|
||||||
return "Align crown to top, foot base to bottom for best results."
|
return t("Seller.imageClipSketchTip")
|
||||||
}
|
}
|
||||||
if (props.type === "apparel") {
|
if (props.type === "apparel") {
|
||||||
return "Trim whitespace and center your apparel sketch."
|
return t("Seller.imageClipApparelTip")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
url: "",
|
url: "",
|
||||||
title: "Crop Image",
|
title: "Crop Image",
|
||||||
preview_url: "",
|
preview_url: "",
|
||||||
@@ -93,10 +119,28 @@ const data = reactive({
|
|||||||
isPreview: true,
|
isPreview: true,
|
||||||
callback: null,
|
callback: null,
|
||||||
isProduct: false // 是否商品编辑
|
isProduct: false // 是否商品编辑
|
||||||
})
|
})
|
||||||
const show = ref(false)
|
|
||||||
const open = (url, callback, options) => {
|
const currentOrigin = ref("sketch")
|
||||||
|
const coverOrigin = ref([])
|
||||||
|
const handleChangeOrigin = (type) => {
|
||||||
|
const targetOrigin = coverOrigin.value.find((el) => el.type === type)
|
||||||
|
if (!targetOrigin) return
|
||||||
|
|
||||||
|
currentOrigin.value = type
|
||||||
|
data.url = targetOrigin.url
|
||||||
|
}
|
||||||
|
|
||||||
|
const show = ref(false)
|
||||||
|
const open = (url, callback, options, origin) => {
|
||||||
|
if (!props.isProduct) {
|
||||||
if (!url || !callback) return
|
if (!url || !callback) return
|
||||||
|
}
|
||||||
|
|
||||||
|
coverOrigin.value = []
|
||||||
|
data.url = null
|
||||||
|
currentOrigin.value = "sketch"
|
||||||
|
|
||||||
data.url = url
|
data.url = url
|
||||||
data.callback = callback
|
data.callback = callback
|
||||||
data.ratio = options.ratio || [1, 1]
|
data.ratio = options.ratio || [1, 1]
|
||||||
@@ -107,28 +151,34 @@ const open = (url, callback, options) => {
|
|||||||
if (options.hasOwnProperty("isPreview")) data.isPreview = options.isPreview
|
if (options.hasOwnProperty("isPreview")) data.isPreview = options.isPreview
|
||||||
data.isProduct = options.isProduct
|
data.isProduct = options.isProduct
|
||||||
}
|
}
|
||||||
|
if (origin?.length) {
|
||||||
|
coverOrigin.value = origin
|
||||||
|
const defaultOrigin = origin.find((el) => el.type === options?.coverFrom) || origin[0]
|
||||||
|
currentOrigin.value = defaultOrigin.type
|
||||||
|
data.url = defaultOrigin.url
|
||||||
|
}
|
||||||
show.value = true
|
show.value = true
|
||||||
}
|
}
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
show.value = false
|
show.value = false
|
||||||
}
|
}
|
||||||
const imageClipRef = ref(null)
|
const imageClipRef = ref(null)
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
imageClipRef.value.getCropBlob().then((blob) => {
|
imageClipRef.value.getCropBlob().then((blob) => {
|
||||||
if (data.callback) data.callback(blobToFile(blob, "image.png"))
|
if (data.callback) data.callback(blobToFile(blob, "image.png"), currentOrigin.value)
|
||||||
onCancel()
|
onCancel()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 将blob转换为file对象
|
// 将blob转换为file对象
|
||||||
const blobToFile = (blob, fileName) => {
|
const blobToFile = (blob, fileName) => {
|
||||||
return new File([blob], fileName, { type: blob.type })
|
return new File([blob], fileName, { type: blob.type })
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open
|
open
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.image-clip-dialog-box {
|
.image-clip-dialog-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -169,6 +219,35 @@ defineExpose({
|
|||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
.origin-container {
|
||||||
|
font-weight: 400;
|
||||||
|
color: #000;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
.origin-select {
|
||||||
|
margin-left: 1.2rem;
|
||||||
|
height: 4.8rem;
|
||||||
|
border: 1px solid #c7c7c7;
|
||||||
|
border-radius: 3rem;
|
||||||
|
column-gap: 1.2rem;
|
||||||
|
padding: 0.8rem;
|
||||||
|
.origin-item {
|
||||||
|
height: 3.2rem;
|
||||||
|
line-height: 3.2rem;
|
||||||
|
border-radius: 2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
&.selected {
|
||||||
|
background-color: #000;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
&.sketch {
|
||||||
|
padding: 0 1.9rem;
|
||||||
|
}
|
||||||
|
&.product {
|
||||||
|
padding: 0 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .content {
|
> .content {
|
||||||
@@ -180,6 +259,7 @@ defineExpose({
|
|||||||
|
|
||||||
.crop-wrapper {
|
.crop-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
padding-top: 1.2rem;
|
||||||
.tips {
|
.tips {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #585858;
|
color: #585858;
|
||||||
@@ -248,7 +328,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
&.is-cover {
|
&.is-cover {
|
||||||
> .preview-image > img {
|
> .preview-image > img {
|
||||||
// width: 29.7rem;
|
width: 29.7rem;
|
||||||
height: 37.5rem;
|
height: 37.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,5 +342,5 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -7,13 +7,11 @@
|
|||||||
crossOrigin="Anonymous"
|
crossOrigin="Anonymous"
|
||||||
:autoCrop="true"
|
:autoCrop="true"
|
||||||
:fixedNumber="ratio"
|
:fixedNumber="ratio"
|
||||||
:fixed="type !== 'apparel' && isProduct"
|
:fixed="isProduct ? type !== 'apparel' : true"
|
||||||
movable
|
movable
|
||||||
centerBox
|
|
||||||
:fixedBox="fixedBox"
|
|
||||||
@realTime="onChange"
|
@realTime="onChange"
|
||||||
outputType="png"
|
outputType="png"
|
||||||
v-bind="bindProps"
|
:full="true"
|
||||||
></VueCropper>
|
></VueCropper>
|
||||||
</div>
|
</div>
|
||||||
<div class="clip_opterate">
|
<div class="clip_opterate">
|
||||||
@@ -36,10 +34,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, useAttrs, onMounted, onBeforeUnmount, computed, nextTick, watch } from "vue"
|
import { ref, useAttrs, onMounted, onBeforeUnmount, computed, nextTick, watch } from "vue"
|
||||||
import "vue-cropper/dist/index.css"
|
import "vue-cropper/dist/index.css"
|
||||||
import { VueCropper } from "vue-cropper"
|
import { VueCropper } from "vue-cropper"
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
url: {
|
url: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: ""
|
||||||
@@ -60,75 +58,67 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: () => ""
|
default: () => ""
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const attrs = useAttrs()
|
const attrs = useAttrs()
|
||||||
|
|
||||||
const autoCropHeight = computed(() => {
|
const autoCropHeight = computed(() => {
|
||||||
let height = 426
|
let height = 426
|
||||||
if (props.type === "cover") height = 375
|
if (props.type === "cover") height = 375
|
||||||
else if (props.type === "apparel") height = 320
|
else if (props.type === "apparel") height = 320
|
||||||
return height
|
return height
|
||||||
})
|
})
|
||||||
|
|
||||||
const bindProps = computed(() => {
|
const onChange = (data) => {
|
||||||
// :autoCropWidth="isProduct ? undefined : type === 'cover' ? 297 : 242"
|
|
||||||
// :autoCropHeight="isProduct ? undefined : autoCropHeight"
|
|
||||||
if (props.isProduct) {
|
|
||||||
return {
|
|
||||||
autoCropHeight: autoCropHeight.value,
|
|
||||||
autoCropWidth: props.type === "cover" ? 297 : 242
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const onChange = (data) => {
|
|
||||||
if (attrs.onChange) {
|
if (attrs.onChange) {
|
||||||
getCropUrl().then((url) => attrs.onChange(url))
|
getCropUrl().then((url) => attrs.onChange(url))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const cropper = ref(null)
|
const cropper = ref(null)
|
||||||
const imageClipBody = ref(null)
|
const imageClipBody = ref(null)
|
||||||
let injectLabelFrame = 0
|
let injectLabelFrame = 0
|
||||||
const observer = new ResizeObserver((entries) => {
|
const observer = new ResizeObserver((entries) => {
|
||||||
refreshCrop()
|
refreshCrop()
|
||||||
})
|
})
|
||||||
|
|
||||||
const clearCropLabels = (cropperBox) => {
|
const clearCropLabels = (cropperBox) => {
|
||||||
if (!cropperBox) return
|
if (!cropperBox) return
|
||||||
cropperBox.querySelectorAll(".cropper-line-label").forEach((node) => node.remove())
|
cropperBox.querySelectorAll(".cropper-line-label").forEach((node) => node.remove())
|
||||||
}
|
}
|
||||||
|
|
||||||
const createCropLabel = ({ text, top, className }) => {
|
const createCropLabel = ({ text, top, className }) => {
|
||||||
const label = document.createElement("div")
|
const label = document.createElement("div")
|
||||||
label.className = `cropper-line-label ${className}`
|
label.className = `cropper-line-label ${className}`
|
||||||
label.textContent = text
|
label.textContent = text
|
||||||
label.style.top = top
|
label.style.top = top
|
||||||
label.style.left = className === "label-v" ? "50%" : "0"
|
label.style.left = className === "label-v" ? "50%" : "0"
|
||||||
label.style.transform = className === "label-v" ? "translate(-50%, -50%)" : "translateY(-50%)"
|
label.style.transform =
|
||||||
|
className === "label-v" ? "translate(-50%, -50%)" : "translateY(-50%)"
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
const cropLabelMap = {
|
const centerLabelTop = "8px"
|
||||||
|
|
||||||
|
const cropLabelMap = {
|
||||||
cover: [
|
cover: [
|
||||||
{ text: "crown", top: "2.67%", className: "label-h" },
|
{ text: "crown", top: "2.67%", className: "label-h" },
|
||||||
{ text: "hip line", top: "63.47%", className: "label-h" },
|
{ text: "hip line", top: "63.47%", className: "label-h" },
|
||||||
{ text: "mid-thigh", top: "92.8%", className: "label-h" },
|
{ text: "mid-thigh", top: "92.8%", className: "label-h" },
|
||||||
{ text: "center", top: "0", className: "label-v" }
|
{ text: "center", top: centerLabelTop, className: "label-v" }
|
||||||
],
|
],
|
||||||
mainProductImage: [
|
mainProductImage: [
|
||||||
{ text: "crown", top: "2.67%", className: "label-h" },
|
{ text: "crown", top: "2.67%", className: "label-h" },
|
||||||
{ text: "footbase", top: "97.6%", className: "label-h" },
|
{ text: "footbase", top: "97.6%", className: "label-h" },
|
||||||
{ text: "center", top: "0", className: "label-v" }
|
{ text: "center", top: centerLabelTop, className: "label-v" }
|
||||||
],
|
],
|
||||||
sketch: [
|
sketch: [
|
||||||
{ text: "crown", top: "2.67%", className: "label-h" },
|
{ text: "crown", top: "2.67%", className: "label-h" },
|
||||||
{ text: "footbase", top: "97.6%", className: "label-h" },
|
{ text: "footbase", top: "97.6%", className: "label-h" },
|
||||||
{ text: "center", top: "0", className: "label-v" }
|
{ text: "center", top: centerLabelTop, className: "label-v" }
|
||||||
],
|
],
|
||||||
apparel: [{ text: "center", top: "0", className: "label-v" }]
|
apparel: [{ text: "center", top: centerLabelTop, className: "label-v" }]
|
||||||
}
|
}
|
||||||
|
|
||||||
const injectCropLabel = () => {
|
const injectCropLabel = () => {
|
||||||
const cropperBox = imageClipBody.value?.querySelector(".cropper-view-box")
|
const cropperBox = imageClipBody.value?.querySelector(".cropper-view-box")
|
||||||
|
|
||||||
if (!cropperBox) return false
|
if (!cropperBox) return false
|
||||||
@@ -139,64 +129,64 @@ const injectCropLabel = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const scheduleInjectCropLabel = (retry = 0) => {
|
const scheduleInjectCropLabel = (retry = 0) => {
|
||||||
cancelAnimationFrame(injectLabelFrame)
|
cancelAnimationFrame(injectLabelFrame)
|
||||||
injectLabelFrame = requestAnimationFrame(() => {
|
injectLabelFrame = requestAnimationFrame(() => {
|
||||||
if (!injectCropLabel() && retry < 10) {
|
if (!injectCropLabel() && retry < 10) {
|
||||||
scheduleInjectCropLabel(retry + 1)
|
scheduleInjectCropLabel(retry + 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
observer.observe(imageClipBody.value)
|
observer.observe(imageClipBody.value)
|
||||||
scheduleInjectCropLabel()
|
scheduleInjectCropLabel()
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
observer.disconnect()
|
observer.disconnect()
|
||||||
cancelAnimationFrame(injectLabelFrame)
|
cancelAnimationFrame(injectLabelFrame)
|
||||||
})
|
})
|
||||||
const rotateLeft = () => {
|
const rotateLeft = () => {
|
||||||
cropper.value.rotateLeft()
|
cropper.value.rotateLeft()
|
||||||
}
|
}
|
||||||
const rotateRight = () => {
|
const rotateRight = () => {
|
||||||
cropper.value.rotateRight()
|
cropper.value.rotateRight()
|
||||||
}
|
}
|
||||||
const refreshCrop = () => {
|
const refreshCrop = () => {
|
||||||
cropper.value.refresh()
|
cropper.value.refresh()
|
||||||
}
|
}
|
||||||
const changeScale = (num = 1) => {
|
const changeScale = (num = 1) => {
|
||||||
cropper.value.changeScale(num)
|
cropper.value.changeScale(num)
|
||||||
}
|
}
|
||||||
const getCropUrl = () => {
|
const getCropUrl = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
cropper.value.getCropData(resolve)
|
cropper.value.getCropData(resolve)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const getCropBlob = () => {
|
const getCropBlob = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
cropper.value.getCropBlob(resolve)
|
cropper.value.getCropBlob(resolve)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
[() => props.type, () => props.url],
|
[() => props.type, () => props.url],
|
||||||
async () => {
|
async () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
scheduleInjectCropLabel()
|
scheduleInjectCropLabel()
|
||||||
},
|
},
|
||||||
{ flush: "post" }
|
{ flush: "post" }
|
||||||
)
|
)
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getCropUrl,
|
getCropUrl,
|
||||||
getCropBlob
|
getCropBlob
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.image-clip {
|
.image-clip {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -216,23 +206,23 @@ defineExpose({
|
|||||||
.cropper-box-canvas {
|
.cropper-box-canvas {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
|
||||||
img {
|
// img {
|
||||||
height: 100%;
|
// height: 100%;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.is-cover {
|
&.is-cover {
|
||||||
:deep(.vue-cropper) {
|
:deep(.vue-cropper) {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
:deep(.cropper-box-canvas) {
|
// :deep(.cropper-box-canvas) {
|
||||||
width: 31.1rem !important;
|
// width: 31.1rem !important;
|
||||||
left: 50% !important;
|
// left: 50% !important;
|
||||||
transform: translateX(-50%) !important;
|
// transform: translateX(-50%) !important;
|
||||||
img {
|
// img {
|
||||||
display: none;
|
// display: none;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,11 +290,16 @@ defineExpose({
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid rgba(75, 165, 255, 0.85);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 9; /* 位于图片之上,但在控制点之下 */
|
z-index: 9; /* 位于图片之上,但在控制点之下 */
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
:deep(.vue-cropper .crop-point) {
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-crop-type="cover"] {
|
&[data-crop-type="cover"] {
|
||||||
@@ -362,11 +357,11 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.cropper-line-label {
|
.cropper-line-label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
color: #4ba5ff; /* 统一颜色 */
|
color: #4ba5ff; /* 统一颜色 */
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@@ -378,19 +373,19 @@ defineExpose({
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 水平线名称:放在线段上方 2px */
|
/* 水平线名称:放在线段上方 2px */
|
||||||
.label-h {
|
.label-h {
|
||||||
transform: translateY(-100%);
|
transform: translateY(-100%);
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 垂直线名称:放在裁剪框顶部边缘上方 */
|
/* 垂直线名称:放在裁剪框顶部边缘上方 */
|
||||||
.label-v {
|
.label-v {
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
top: -20px;
|
top: -20px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
<img v-if="banner" :src="banner" />
|
<img v-if="banner" :src="banner" />
|
||||||
<div v-else class="null">
|
<div v-else class="null">
|
||||||
<span class="icon"><svg-icon name="seller-picture" size="60" /></span>
|
<span class="icon"><svg-icon name="seller-picture" size="60" /></span>
|
||||||
<span class="tip">Your brand banner has not been set up yet.</span>
|
<span class="tip">{{ $t("Seller.brandProfileBgNullTip") }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button @click="onChangeBanner">Change Brand Banner</button>
|
<button @click="onChangeBanner">{{ $t("Seller.changeBrandBanner") }}</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- 头像 -->
|
<!-- 头像 -->
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
@@ -25,14 +25,14 @@
|
|||||||
<div class="and-profile-footer">
|
<div class="and-profile-footer">
|
||||||
<template v-if="isEdit">
|
<template v-if="isEdit">
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<button class="cancel" @click="onCancel">Cancel</button>
|
<button class="cancel" @click="onCancel()">{{ $t("Seller.cancel") }}</button>
|
||||||
<button class="submit" @click="onSubmit">Save Change</button>
|
<button class="submit" @click="onSubmit()">{{ $t("Seller.saveChange") }}</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="tip">Changes will be reflected on your Stylish Parade brand page.</p>
|
<p class="tip">{{ $t("Seller.brandProfileEditTip") }}</p>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<button class="edit" @click="onEdit">Edit</button>
|
<button class="edit" @click="onEdit">{{ $t("Seller.edit") }}</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="tip"> </p>
|
<p class="tip"> </p>
|
||||||
</template>
|
</template>
|
||||||
@@ -46,7 +46,10 @@
|
|||||||
import BrandInfo from "./brand-info.vue"
|
import BrandInfo from "./brand-info.vue"
|
||||||
import ImageClipDialog from "./image-clip-dialog.vue"
|
import ImageClipDialog from "./image-clip-dialog.vue"
|
||||||
import { useStore } from "vuex"
|
import { useStore } from "vuex"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
store.dispatch("seller/get_designerInfo")
|
||||||
const designerInfo = computed(() => store.state.seller.designerInfo)
|
const designerInfo = computed(() => store.state.seller.designerInfo)
|
||||||
const avatar = computed(() => designerInfo.value.avatar)
|
const avatar = computed(() => designerInfo.value.avatar)
|
||||||
const banner = computed(() => designerInfo.value.brandBanner)
|
const banner = computed(() => designerInfo.value.brandBanner)
|
||||||
@@ -69,15 +72,27 @@
|
|||||||
input.click()
|
input.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uploadFile = async (file) => {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append("file", file)
|
||||||
|
return Https.axiosPost(Https.httpUrls.sellerUploadFile, formData, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const onChangeBanner = () => {
|
const onChangeBanner = () => {
|
||||||
uploadImg(({ url }) => {
|
uploadImg(({ url }) => {
|
||||||
imageClipDialogRef.value.open(
|
imageClipDialogRef.value.open(
|
||||||
url,
|
url,
|
||||||
(file) => {
|
async (file) => {
|
||||||
// banner.value = URL.createObjectURL(file)
|
store.commit("set_loading", true)
|
||||||
console.log(URL.createObjectURL(file))
|
const res = await uploadFile(file)
|
||||||
|
onSubmit({ brandBanner: res })
|
||||||
|
store.commit("set_loading", false)
|
||||||
},
|
},
|
||||||
{ ratio: [40, 7], isPreview: false, title: "Crop Brand Banner" }
|
{ ratio: [40, 7], isPreview: false, title: t("Seller.cropBrandBanner") }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -85,11 +100,13 @@
|
|||||||
uploadImg(({ url }) => {
|
uploadImg(({ url }) => {
|
||||||
imageClipDialogRef.value.open(
|
imageClipDialogRef.value.open(
|
||||||
url,
|
url,
|
||||||
(file) => {
|
async (file) => {
|
||||||
// avatar.value = URL.createObjectURL(file)
|
store.commit("set_loading", true)
|
||||||
console.log(URL.createObjectURL(file))
|
const res = await uploadFile(file)
|
||||||
|
onSubmit({ avatar: res })
|
||||||
|
store.commit("set_loading", false)
|
||||||
},
|
},
|
||||||
{ ratio: [1, 1], isPreview: true, title: "Crop Avatar" }
|
{ ratio: [1, 1], isPreview: true, title: t("Seller.cropAvatar") }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -99,12 +116,16 @@
|
|||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
isEdit.value = false
|
isEdit.value = false
|
||||||
}
|
}
|
||||||
const onSubmit = async () => {
|
const onSubmit = async (value = null) => {
|
||||||
const res = await brandInfoRef.value.submit()
|
const res = value ? value : await brandInfoRef.value.submit()
|
||||||
const data = {
|
const data = {
|
||||||
...designerInfo.value,
|
...designerInfo.value,
|
||||||
...res,
|
...res
|
||||||
socialLinks: JSON.stringify(res.socialLinks)
|
}
|
||||||
|
try {
|
||||||
|
data.socialLinks = JSON.stringify(data.socialLinks)
|
||||||
|
} catch (error) {
|
||||||
|
data.socialLinks = JSON.stringify([])
|
||||||
}
|
}
|
||||||
Https.axiosPut(Https.httpUrls.updateDesignerInfo, data).then((res) => {
|
Https.axiosPut(Https.httpUrls.updateDesignerInfo, data).then((res) => {
|
||||||
isEdit.value = false
|
isEdit.value = false
|
||||||
@@ -123,6 +144,7 @@
|
|||||||
margin-bottom: 6rem;
|
margin-bottom: 6rem;
|
||||||
> .bg {
|
> .bg {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
min-height: 15rem;
|
||||||
> img {
|
> img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|||||||
@@ -2,14 +2,6 @@
|
|||||||
<div class="status-wrapper flex flex-col flex-1">
|
<div class="status-wrapper flex flex-col flex-1">
|
||||||
<seller-header
|
<seller-header
|
||||||
class="edit-detail-header"
|
class="edit-detail-header"
|
||||||
title="Edit Listing Details"
|
|
||||||
:breadcrumbs="[
|
|
||||||
{ title: 'My Listings', name: 'myListingsIndex' },
|
|
||||||
{ title: 'Select Collection', name: 'myListingsSelect' },
|
|
||||||
{ title: 'Select Sketch', name: 'myListingsSelectItem' },
|
|
||||||
{ title: 'Edit Listing Details', name: 'EditDetail' },
|
|
||||||
{ title: $t(title), name: 'Status' }
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
<div class="status-container flex flex-col flex-1 flex-center">
|
<div class="status-container flex flex-col flex-1 flex-center">
|
||||||
<img src="@/assets/images/seller/success-0.png" class="icon" alt="" />
|
<img src="@/assets/images/seller/success-0.png" class="icon" alt="" />
|
||||||
@@ -17,30 +9,34 @@
|
|||||||
<div class="desc">
|
<div class="desc">
|
||||||
{{ $t(desc) }}
|
{{ $t(desc) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="btn">Back to My Listings</div>
|
<div class="btn" @click="handleBack">Back to My Listings</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from "vue"
|
import { ref, computed } from "vue"
|
||||||
import { useRoute } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
import SellerHeader from "../../seller-header.vue"
|
import SellerHeader from "../../seller-header.vue"
|
||||||
const ROUTE = useRoute()
|
const ROUTE = useRoute()
|
||||||
const title = computed(() => {
|
const ROUTER = useRouter()
|
||||||
|
const title = computed(() => {
|
||||||
if (ROUTE.params.status === "publish") return "SellerListEdit.listingLive"
|
if (ROUTE.params.status === "publish") return "SellerListEdit.listingLive"
|
||||||
if (ROUTE.params.status === "draft") return "SellerListEdit.draftSaved"
|
if (ROUTE.params.status === "draft") return "SellerListEdit.draftSaved"
|
||||||
})
|
})
|
||||||
|
|
||||||
const desc = computed(() => {
|
const desc = computed(() => {
|
||||||
if (ROUTE.params.status === "publish") return "SellerListEdit.publishDesc"
|
if (ROUTE.params.status === "publish") return "SellerListEdit.publishDesc"
|
||||||
if (ROUTE.params.status === "draft") return "SellerListEdit.draftDesc"
|
if (ROUTE.params.status === "draft") return "SellerListEdit.draftDesc"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleBack = () => {
|
||||||
|
ROUTER.push({ name: "myListingsIndex" })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.status-wrapper {
|
.status-wrapper {
|
||||||
.status-container {
|
.status-container {
|
||||||
row-gap: 2.4rem;
|
row-gap: 2.4rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@@ -74,5 +70,5 @@ const desc = computed(() => {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
115
src/views/SellerDashboard/MyListings/EditDetail/agents.md
Normal file
115
src/views/SellerDashboard/MyListings/EditDetail/agents.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# EditDetail Page Agent Notes
|
||||||
|
|
||||||
|
This directory owns the seller listing edit/create detail page.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `index.vue`: route-level container. Keep orchestration here: history-state entry mode, API calls, page switching, validation, save/publish navigation, image crop dialog wiring.
|
||||||
|
- `api.ts`: API wrappers for listing detail, sketch detail, listing batch save, status update, and file upload.
|
||||||
|
- `types.ts`: shared page-local TypeScript types. Add new cross-component page types here instead of duplicating interfaces in child components.
|
||||||
|
- `components/TopImageSection.vue`: presentational block for `sketch`, `mainProductImage`, and `cover`.
|
||||||
|
- `components/ProductImageList.vue`: presentational product-image selector and selected/main badge display.
|
||||||
|
- `components/ApparelSketchList.vue`: presentational apparel sketch list and crop trigger.
|
||||||
|
- `components/ListingForm.vue`: presentational listing form. Emits field updates; does not call APIs.
|
||||||
|
- `components/Radio.vue`: local radio/multi-select button component.
|
||||||
|
- `Status.vue`: save/publish result status page.
|
||||||
|
|
||||||
|
## Component Boundaries
|
||||||
|
|
||||||
|
- Keep `index.vue` as the single source of truth for `selectList`, `currentPage`, `currentListing`, per-listing `firstSelectedIndex`, and crop/save behavior.
|
||||||
|
- Child components should receive props and emit events only. Do not import listing APIs or mutate parent state directly from children.
|
||||||
|
- If a new visual section is added to this page, prefer a new child component under `components/` plus shared types in `types.ts`.
|
||||||
|
|
||||||
|
## Vue SFC Order
|
||||||
|
|
||||||
|
- Vue single-file components must keep sections in this order: `<template>` first, then `<script setup lang="ts">`, then `<style>`.
|
||||||
|
- When creating or refactoring `.vue` files in this page, preserve that order even if external Vue guidance suggests another layout.
|
||||||
|
|
||||||
|
## Image Category Mapping
|
||||||
|
|
||||||
|
Detail API images are mapped by `category`:
|
||||||
|
|
||||||
|
- `cover` -> `currentListing.cover`
|
||||||
|
- `cover_from` -> `currentListing.coverFrom`; `imageUrl` stores the source image URL, not the literal source key. Resolve it against `sketch` and `mainProductImage` when hydrating. Keep backward compatibility for old rows whose `imageUrl` is `sketch` or `mainProductImage`.
|
||||||
|
- `sketch` -> `currentListing.sketch`
|
||||||
|
- `mainProductImage` or `main_product` -> `currentListing.mainProductImage`
|
||||||
|
- `product` -> non-video entries in `currentListing.prodImageList`
|
||||||
|
- `firstFrame`, `gif`, and `video` -> one video entry in `currentListing.prodImageList` when the three rows share the same `sortOrder`
|
||||||
|
- `apparel` -> `currentListing.sketchList`
|
||||||
|
|
||||||
|
When saving, preserve the backend's expected image categories. Confirm backend naming before changing `main_product`, `product`, `firstFrame`, `gif`, `video`, or `mainProductImage`.
|
||||||
|
|
||||||
|
中文补充:
|
||||||
|
|
||||||
|
- 详情接口返回的 `images` 要按 `category` 回填到页面状态,不要只按数组顺序猜类型。
|
||||||
|
- `cover_from` 不是封面图本身,而是记录封面裁剪来源。它的 `imageUrl` 传来源图片链接,回显时用这个 URL 和 `sketch`、`mainProductImage` 比较,恢复裁剪弹窗里的来源选择。
|
||||||
|
- `main_product` 表示页面右上方的主产品图 URL;普通 `product` 只表示产品图列表里的非视频图片。
|
||||||
|
- 视频不要保存成 `product`。视频必须拆成 `firstFrame`、`gif`、`video` 三类,并在回显时按相同 `sortOrder` 合并成一个视频项。
|
||||||
|
|
||||||
|
## Product Image Rules
|
||||||
|
|
||||||
|
- The `main` badge represents the first selected product image, not the most recently selected one.
|
||||||
|
- `firstSelectedIndex` is stored on each `ListingItem` and passed to `ProductImageList.vue`.
|
||||||
|
- Hydrating detail data must only set `mainProductImage` from explicit `main_product` or `mainProductImage` rows. Never infer it from selected `product` rows.
|
||||||
|
- Selecting a product image should only set `mainProductImage` when no main image is currently tracked by that listing's `firstSelectedIndex`.
|
||||||
|
- Unselecting the current main product image clears `mainProductImage` and resets `firstSelectedIndex`.
|
||||||
|
- Videos can be selected and saved, but they cannot become `mainProductImage`, must not set `firstSelectedIndex`, and must not display the `main` badge.
|
||||||
|
|
||||||
|
中文补充:
|
||||||
|
|
||||||
|
- `main` 标识只给图片,不给视频。
|
||||||
|
- 数据回显时,只有接口明确返回 `main_product` / `mainProductImage` 才能设置主图。不要因为某个 `product` 是已选中状态,就自动把它当成 `mainProductImage` 或显示 `main`。
|
||||||
|
- 第一次选择视频时可以弹 warning,但视频本身仍然要保持选中;只是不要把它写入 `mainProductImage`,也不要更新 `firstSelectedIndex`。
|
||||||
|
- 如果先选中视频,再选中图片,图片仍然可以成为第一个主图。
|
||||||
|
- 如果取消的是当前主图图片,需要清空 `mainProductImage` 和 `firstSelectedIndex`;取消普通图片或视频不应影响主图。
|
||||||
|
|
||||||
|
## Save Image Ordering
|
||||||
|
|
||||||
|
- Every saved image row must include `sortOrder`.
|
||||||
|
- `sortOrder` is scoped per category; each category starts its own sequence.
|
||||||
|
- For `product` rows, save the image currently used as `mainProductImage` first, selected non-main images next, and unselected images last.
|
||||||
|
- Save video media as three rows with categories `firstFrame`, `gif`, and `video`. The three rows from the same video item must share the same `sortOrder`.
|
||||||
|
- When hydrating detail data, group `firstFrame`, `gif`, and `video` rows by matching `sortOrder` and restore the combined video item, including its selected state. Accept `isSelected`, old typo `isSeleted`, and `selected` from the API.
|
||||||
|
|
||||||
|
中文补充:
|
||||||
|
|
||||||
|
- `sortOrder` 是按 category 分开排的,不同 category 之间不要共用一个全局序号。
|
||||||
|
- `product` 的排序规则是:当前作为 `mainProductImage` 的图片第一,其他已选图片其次,未选图片最后。
|
||||||
|
- 同一个视频拆出的 `firstFrame`、`gif`、`video` 三条数据必须使用同一个 `sortOrder`。例如第一个视频三条都是 `sortOrder: 1`,第二个视频三条都是 `sortOrder: 2`。
|
||||||
|
- 回显视频时,用相同 `sortOrder` 找回一组 `firstFrame/gif/video`。三条里任意一条带选中标记,都应恢复为这个视频已选中。
|
||||||
|
- 选中字段要兼容 `isSelected`、历史拼写 `isSeleted`、以及 `selected`。
|
||||||
|
|
||||||
|
## Crop Flow
|
||||||
|
|
||||||
|
- `TopImageSection.vue` and `ApparelSketchList.vue` emit `crop`.
|
||||||
|
- `index.vue` handles `handleClickCrop`, opens `ImageClipDialog`, uploads with `uploadFile`, then writes the returned URL into the correct field/list item.
|
||||||
|
- Keep cover crop ratio at `[4, 5]`; other crop types use `[9, 16]`.
|
||||||
|
- Cover crop can be based on `sketch` or `mainProductImage`. Store the chosen source in `coverFrom`, save it via `cover_from.imageUrl` as the source image URL, and pass it back into `ImageClipDialog` so reopening cover crop restores the selected source.
|
||||||
|
|
||||||
|
中文补充:
|
||||||
|
|
||||||
|
- cover 裁剪弹窗会在 `sketch` 和 `mainProductImage` 之间切来源。用户保存 cover 时,父组件需要同时保存裁剪后的 cover URL 和本次使用的来源。
|
||||||
|
- 下次重新打开 cover 裁剪时,应该按 `coverFrom` 恢复来源选择,并用对应的原图作为裁剪图,不要直接拿已裁好的 cover 图再次裁。
|
||||||
|
- 如果只有一个来源图可用,就按可用来源打开;如果两个来源都可用,要显示来源切换。
|
||||||
|
|
||||||
|
## Form Flow
|
||||||
|
|
||||||
|
- `ListingForm.vue` accepts scalar form props and emits `update:*` events.
|
||||||
|
- `index.vue` writes those events back into `currentListing`.
|
||||||
|
- Category options are derived from current gender and Vuex `UserHabit` state.
|
||||||
|
|
||||||
|
## Validation And Navigation
|
||||||
|
|
||||||
|
- `validatePublishRequired()` validates each listing before publish.
|
||||||
|
- Draft currently requires `cover` before save.
|
||||||
|
- After save/publish, routing goes to `Status` with route param `status`.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- Run `npm run build` after behavior or type changes.
|
||||||
|
- Build can fail before code bundling completes if the existing `feedbackSurvey.vue` Google Fonts import cannot be fetched. If the failure is only `fonts.googleapis.com` socket/DNS related, retry when network is available.
|
||||||
|
- Project ESLint currently fails before linting files because `.eslintrc.js` contains invalid env key `se6`; do not treat that as a page-specific regression.
|
||||||
|
|
||||||
|
## Known Caution
|
||||||
|
|
||||||
|
- This page has active local edits. Before broad refactors, inspect both staged and unstaged diffs.
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
import { Https } from "@/tool/https"
|
import { Https } from "@/tool/https"
|
||||||
|
import type { ListingImageCategory, SketchDetailResponse } from "./types"
|
||||||
|
|
||||||
interface SketchIDs {
|
// 编辑时根据ID获取信息
|
||||||
designItemIds: Array
|
export const fetchListingDetailById = (id) => {
|
||||||
|
return Https.axiosGet("/seller/listing/detail", { params: { id } })
|
||||||
}
|
}
|
||||||
export const fetchSketchDetail = (data: SketchIDs) => {
|
|
||||||
|
type SketchIDs = Array<number | string>
|
||||||
|
// 获取designItemId对应的产品图
|
||||||
|
export const fetchSketchDetail = (data: SketchIDs): Promise<SketchDetailResponse[]> => {
|
||||||
let params = "?"
|
let params = "?"
|
||||||
data.forEach((id, index) => {
|
data.forEach((id, index) => {
|
||||||
if (index === data.length - 1) {
|
if (index === data.length - 1) {
|
||||||
@@ -12,13 +17,46 @@ export const fetchSketchDetail = (data: SketchIDs) => {
|
|||||||
params += `designItemIds=${id}&`
|
params += `designItemIds=${id}&`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return Https.axiosGet(`/api/seller/sketchDetail${params}`)
|
return Https.axiosGet(`/aida/api/seller/sketchDetail${params}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImageObj {
|
||||||
|
id?: number // 图片id,有值会更新,没有会自动新增
|
||||||
|
category: ListingImageCategory // 图片类型
|
||||||
|
imageUrl?: string | null
|
||||||
|
isSelected?: number
|
||||||
|
sortOrder?: number
|
||||||
|
}
|
||||||
|
interface DetailData {
|
||||||
|
id: number | string // 商品Id
|
||||||
|
title: string // 商品名
|
||||||
|
description: string // 商品描述
|
||||||
|
price: number | string // 价格
|
||||||
|
stock?: number // 库存
|
||||||
|
viewCount?: number // 浏览量
|
||||||
|
status: 0 | 1 | 2 // 0草稿 1发布 2删除
|
||||||
|
images: ImageObj[]
|
||||||
|
designFor: "male" | "female"
|
||||||
|
productCategory: string[] | null
|
||||||
|
}
|
||||||
|
// 保存/更新表单
|
||||||
|
export const fetchUpdateListing = (data: DetailData[]) => {
|
||||||
|
return Https.axiosPost("/seller/listing/batch", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StatusData {
|
||||||
|
id: number | string
|
||||||
|
status: 0 | 1 | 2 // 0草稿 1发布 2删除
|
||||||
|
}
|
||||||
|
// 设置商品状态
|
||||||
|
export const fetchChangeStatus = (data: StatusData) => {
|
||||||
|
return Https.axiosPut("/seller/listing/status", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const uploadFile = (file) => {
|
export const uploadFile = (file) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append("file", file)
|
formData.append("file", file)
|
||||||
return Https.axiosPost("/seller/file/ upload", formData, {
|
return Https.axiosPost("/seller/file/upload", formData, {
|
||||||
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" }
|
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<div class="apparel-container">
|
||||||
|
<div class="title">
|
||||||
|
<span class="main-title">{{ $t("SellerListEdit.apparelSketchTitle") }}</span>
|
||||||
|
<span class="sub-title">{{ $t("SellerListEdit.apparelSketchSubTitle") }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="sketch-list-container flex">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in sketchList"
|
||||||
|
:key="index"
|
||||||
|
class="sketch-element flex flex-center"
|
||||||
|
>
|
||||||
|
<img class="img-src" :src="item.url || ''" alt="" />
|
||||||
|
<div
|
||||||
|
class="crop-tool flex flex-center"
|
||||||
|
@click="emit('crop', item.url, 'apparel', index)"
|
||||||
|
>
|
||||||
|
<SvgIcon name="CCrop" color="#fff" size="12" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { ListingItem } from "../types"
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
sketchList: ListingItem["sketchList"]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "crop", data: string | null, type: "apparel", index?: number): void
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.apparel-container {
|
||||||
|
margin-top: 3rem;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
|
||||||
|
.main-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: bold;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "*";
|
||||||
|
color: #df2b2c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sketch-list-container {
|
||||||
|
column-gap: 1rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.sketch-element {
|
||||||
|
width: 10rem;
|
||||||
|
height: 14.6rem;
|
||||||
|
border: 0.15rem solid #c7c7c7;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.img-src {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crop-tool {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.4rem;
|
||||||
|
right: 0.4rem;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form-container flex flex-col">
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="form-item-label required">
|
||||||
|
{{ $t("SellerListEdit.productName") }}
|
||||||
|
</div>
|
||||||
|
<div class="form-item-value product-name">
|
||||||
|
<a-input
|
||||||
|
:value="productName"
|
||||||
|
show-count
|
||||||
|
placeholder="Enter product name"
|
||||||
|
:bordered="false"
|
||||||
|
:maxlength="60"
|
||||||
|
@update:value="emit('update:productName', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="form-item-label required">{{ $t("SellerListEdit.price") }}</div>
|
||||||
|
<div class="form-item-value price flex align-center">
|
||||||
|
<span>HK$</span>
|
||||||
|
<a-input
|
||||||
|
:value="price"
|
||||||
|
placeholder="0.00"
|
||||||
|
:bordered="false"
|
||||||
|
@update:value="emit('update:price', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="form-item-label required">
|
||||||
|
{{ $t("SellerListEdit.productDescription") }}
|
||||||
|
</div>
|
||||||
|
<div class="form-item-value desc">
|
||||||
|
<a-textarea
|
||||||
|
:value="desc"
|
||||||
|
show-count
|
||||||
|
:rows="4"
|
||||||
|
placeholder="Enter product description"
|
||||||
|
:bordered="false"
|
||||||
|
:maxlength="500"
|
||||||
|
@update:value="emit('update:desc', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="form-item-label required">
|
||||||
|
{{ $t("SellerListEdit.designFor") }}
|
||||||
|
</div>
|
||||||
|
<div class="form-item-value no-border">
|
||||||
|
<Radio
|
||||||
|
:options="genderOptions"
|
||||||
|
:model-value="gender"
|
||||||
|
@update:model-value="emit('update:gender', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-item">
|
||||||
|
<div class="form-item-label with-tip">
|
||||||
|
<span class="required">{{ $t("SellerListEdit.productCategory") }}</span>
|
||||||
|
<span class="help-text">{{ $t("SellerListEdit.categoryTips") }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-item-value no-border">
|
||||||
|
<Radio
|
||||||
|
multiple
|
||||||
|
:options="categoryOptions"
|
||||||
|
:model-value="category"
|
||||||
|
@update:model-value="emit('update:category', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="license-note flex align-center">
|
||||||
|
<img src="@/assets/images/seller/tips.png" class="info-icon" />
|
||||||
|
<div class="note-copy">
|
||||||
|
{{ $t("SellerListEdit.policy") }}
|
||||||
|
<a href="javascript:void(0)">{{ $t("SellerListEdit.learnMore") }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Radio from "./Radio.vue"
|
||||||
|
import type { RadioOption } from "../types"
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
productName: string
|
||||||
|
price: string
|
||||||
|
desc: string
|
||||||
|
gender: string
|
||||||
|
category: string[] | null
|
||||||
|
genderOptions: RadioOption[]
|
||||||
|
categoryOptions: RadioOption[]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "update:productName", value: string): void
|
||||||
|
(e: "update:price", value: string): void
|
||||||
|
(e: "update:desc", value: string): void
|
||||||
|
(e: "update:gender", value: string): void
|
||||||
|
(e: "update:category", value: string[] | null): void
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.required {
|
||||||
|
&::after {
|
||||||
|
content: "*";
|
||||||
|
color: #df2b2c;
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
row-gap: 3rem;
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
.form-item-label {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: bold;
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
&.with-tip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item-value {
|
||||||
|
border: 0.16rem solid #d1d1d1;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
position: relative;
|
||||||
|
padding: 1.6rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #000;
|
||||||
|
|
||||||
|
&.no-border {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.price {
|
||||||
|
column-gap: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input),
|
||||||
|
:deep(.ant-input-affix-wrapper),
|
||||||
|
:deep(.ant-input-textarea textarea) {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #000;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input) {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input-show-count-suffix) {
|
||||||
|
color: #df2c2c;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(textarea.ant-input) {
|
||||||
|
resize: none;
|
||||||
|
min-height: 5.4rem;
|
||||||
|
padding-bottom: 1.8rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-input-textarea-show-count) {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
float: none;
|
||||||
|
position: absolute;
|
||||||
|
color: #df2c2c;
|
||||||
|
bottom: 0;
|
||||||
|
right: 1.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.license-note {
|
||||||
|
padding: 1.6rem;
|
||||||
|
column-gap: 1.6rem;
|
||||||
|
background: #f7f7f7;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
|
||||||
|
.info-icon {
|
||||||
|
width: 2.4rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-copy {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #000;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: medium;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #0080ed;
|
||||||
|
text-decoration: underline;
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
<template>
|
||||||
|
<div class="product-image-list-container">
|
||||||
|
<div class="title flex align-center space-between">
|
||||||
|
<div class="title-left">
|
||||||
|
<span class="main-title">{{ $t("SellerListEdit.productImageMainTitle") }}</span>
|
||||||
|
<span class="sub-title">{{ $t("SellerListEdit.productImageSubTitle") }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="title-right">{{ selectedCount }}/{{ imageList.length }} selected</div>
|
||||||
|
</div>
|
||||||
|
<div class="product-image-list flex">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in imageList"
|
||||||
|
:key="index"
|
||||||
|
class="product-image-item flex flex-center"
|
||||||
|
:class="{ selected: item.selected, video: item.isVideo }"
|
||||||
|
@click="emit('select', index)"
|
||||||
|
@mouseenter="handleMouseEnter(index, item)"
|
||||||
|
@mouseleave="handleMouseLeave(index, item)"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="item.selected"
|
||||||
|
src="@/assets/images/seller/checked.png"
|
||||||
|
class="checked"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<img class="img-src" :src="getDisplayUrl(item, index)" alt="" />
|
||||||
|
<div v-if="item.isVideo && durationMap[index]" class="video-duration">
|
||||||
|
{{ durationMap[index] }}
|
||||||
|
</div>
|
||||||
|
<div v-if="item.selected && index === firstSelectedIndex && !item.isVideo" class="main-pic">
|
||||||
|
main
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from "vue"
|
||||||
|
import type { ListingItem, ProductMediaItem } from "../types"
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
imageList: ListingItem["prodImageList"]
|
||||||
|
firstSelectedIndex: number | null
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "select", index: number): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const selectedCount = computed(() => props.imageList.filter((item) => item.selected).length)
|
||||||
|
const hoveredVideoIndex = ref<number | null>(null)
|
||||||
|
const durationMap = ref<Record<number, string>>({})
|
||||||
|
const videoSourceKey = computed(() =>
|
||||||
|
props.imageList
|
||||||
|
.map((item) => `${item.videoUrl || ""}::${item.url || ""}`)
|
||||||
|
.join("|")
|
||||||
|
)
|
||||||
|
|
||||||
|
const getDisplayUrl = (item: ProductMediaItem, index: number) => {
|
||||||
|
if (item.isVideo && hoveredVideoIndex.value === index && item.gifUrl) {
|
||||||
|
return item.gifUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.url
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMouseEnter = (index: number, item: ProductMediaItem) => {
|
||||||
|
if (!item.isVideo || !item.gifUrl) return
|
||||||
|
hoveredVideoIndex.value = index
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMouseLeave = (index: number, item: ProductMediaItem) => {
|
||||||
|
if (!item.isVideo) return
|
||||||
|
if (hoveredVideoIndex.value === index) hoveredVideoIndex.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatVideoDuration = (duration: number) => {
|
||||||
|
if (!Number.isFinite(duration) || duration <= 0) return ""
|
||||||
|
|
||||||
|
const totalSeconds = Math.round(duration)
|
||||||
|
const minutes = Math.floor(totalSeconds / 60)
|
||||||
|
const seconds = totalSeconds % 60
|
||||||
|
|
||||||
|
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadVideoDurations = () => {
|
||||||
|
durationMap.value = {}
|
||||||
|
props.imageList.forEach((item, index) => {
|
||||||
|
if (!item.isVideo || !item.videoUrl) return
|
||||||
|
|
||||||
|
const video = document.createElement("video")
|
||||||
|
video.preload = "metadata"
|
||||||
|
video.src = item.videoUrl
|
||||||
|
video.onloadedmetadata = () => {
|
||||||
|
durationMap.value = {
|
||||||
|
...durationMap.value,
|
||||||
|
[index]: formatVideoDuration(video.duration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
video.onerror = () => {
|
||||||
|
video.src = ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
videoSourceKey,
|
||||||
|
() => {
|
||||||
|
hoveredVideoIndex.value = null
|
||||||
|
loadVideoDurations()
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.product-image-list-container {
|
||||||
|
margin-top: 3rem;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 1.2rem;
|
||||||
|
|
||||||
|
.main-title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-right {
|
||||||
|
color: #585858;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-image-list {
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
column-gap: 0.8rem;
|
||||||
|
max-width: 80.2rem;
|
||||||
|
padding-bottom: 1.2rem;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
height: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background: #d9d9d9;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #000000;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-image-item {
|
||||||
|
width: 11.6rem;
|
||||||
|
height: 20.6rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 0.15rem solid #c7c7c7;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
content: "";
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
opacity: 0.7;
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border-color: #000;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
position: absolute;
|
||||||
|
top: 0.8rem;
|
||||||
|
right: 0.8rem;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-src {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-duration {
|
||||||
|
position: absolute;
|
||||||
|
right: 0.8rem;
|
||||||
|
bottom: 0.8rem;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 0 0.8rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-pic {
|
||||||
|
position: absolute;
|
||||||
|
height: 2.4rem;
|
||||||
|
line-height: 2.4rem;
|
||||||
|
left: 0.8rem;
|
||||||
|
right: 0.8rem;
|
||||||
|
bottom: 0.8rem;
|
||||||
|
z-index: 1;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
'radio-button',
|
'radio-button',
|
||||||
{
|
{
|
||||||
'is-active': multiple
|
'is-active': multiple
|
||||||
? selectedValues.includes(item.key)
|
? selectedValues.includes(normalizeValue(item.key))
|
||||||
: modelValue === item.key
|
: modelValue === item.key
|
||||||
}
|
}
|
||||||
]"
|
]"
|
||||||
@@ -30,7 +30,12 @@ interface Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: string | number | boolean | Array<string | number | boolean> | null
|
modelValue:
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| Array<string | number | boolean | null | undefined>
|
||||||
|
| null
|
||||||
options: Option[] // 按钮选项数组
|
options: Option[] // 按钮选项数组
|
||||||
multiple?: boolean // 是否支持多选,默认为 false
|
multiple?: boolean // 是否支持多选,默认为 false
|
||||||
}>()
|
}>()
|
||||||
@@ -41,26 +46,40 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const multiple = props.multiple === true
|
const multiple = props.multiple === true
|
||||||
|
|
||||||
|
const normalizeValue = (value: any) =>
|
||||||
|
typeof value === "string" ? value.toLocaleLowerCase() : value
|
||||||
|
|
||||||
const selectedValues = computed(() => {
|
const selectedValues = computed(() => {
|
||||||
if (!multiple) {
|
if (!multiple) {
|
||||||
return typeof props.modelValue === 'undefined' || props.modelValue === null
|
return typeof props.modelValue === "undefined" || props.modelValue === null
|
||||||
? []
|
? []
|
||||||
: [props.modelValue]
|
: [props.modelValue]
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.isArray(props.modelValue) ? props.modelValue : []
|
return Array.isArray(props.modelValue)
|
||||||
|
? props.modelValue
|
||||||
|
.filter((value) => value !== null && typeof value !== "undefined")
|
||||||
|
.map(normalizeValue)
|
||||||
|
: []
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectOption = (value: any) => {
|
const selectOption = (value: any) => {
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
const current = Array.isArray(props.modelValue) ? [...props.modelValue] : []
|
const selectedValue = normalizeValue(value)
|
||||||
const index = current.indexOf(value)
|
const current = Array.isArray(props.modelValue)
|
||||||
|
? props.modelValue
|
||||||
|
.filter((item) => item !== null && typeof item !== "undefined")
|
||||||
|
.map(normalizeValue)
|
||||||
|
: []
|
||||||
|
const index = current.indexOf(selectedValue)
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
current.splice(index, 1)
|
current.splice(index, 1)
|
||||||
} else {
|
} else {
|
||||||
current.push(value)
|
current.push(selectedValue)
|
||||||
}
|
}
|
||||||
emit("update:modelValue", current)
|
|
||||||
|
emit("update:modelValue", current.length ? current : null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,13 +90,13 @@ const selectOption = (value: any) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.radio-button-group {
|
.radio-button-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-button {
|
.radio-button {
|
||||||
border: 1px solid #d9d9d9;
|
border: 1px solid #d9d9d9;
|
||||||
height: 3.2rem;
|
height: 3.2rem;
|
||||||
min-width: 8rem;
|
min-width: 8rem;
|
||||||
@@ -89,16 +108,16 @@ const selectOption = (value: any) => {
|
|||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-button:hover {
|
.radio-button:hover {
|
||||||
border-color: #000;
|
border-color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-button.is-active {
|
.radio-button.is-active {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
border-color: #000;
|
border-color: #000;
|
||||||
font-family: pingfang_medium;
|
font-family: pingfang_medium;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<div class="main-image-container flex">
|
||||||
|
<div
|
||||||
|
v-for="type in topImageList"
|
||||||
|
:key="type"
|
||||||
|
:class="`main-image-item flex flex-col align-center ${type}`"
|
||||||
|
>
|
||||||
|
<div class="title" :class="{ required: type !== 'mainProductImage' }">
|
||||||
|
{{ $t(topImageTitleMap[type]) }}
|
||||||
|
</div>
|
||||||
|
<div class="sketch-item flex flex-center" :class="type">
|
||||||
|
<div
|
||||||
|
v-if="images[type]"
|
||||||
|
class="crop-tool flex flex-center"
|
||||||
|
@click="emit('crop', images[type], type)"
|
||||||
|
>
|
||||||
|
<SvgIcon name="CCrop" color="#fff" size="12" />
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
v-if="images[type]"
|
||||||
|
:src="images[type] || ''"
|
||||||
|
class="sketch-img"
|
||||||
|
:class="type"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div v-else class="trigger flex flex-col align-center">
|
||||||
|
<div
|
||||||
|
v-if="type === 'cover'"
|
||||||
|
class="cover-trigger flex flex-col align-center"
|
||||||
|
@click="emit('crop', null, 'cover')"
|
||||||
|
>
|
||||||
|
<SvgIcon class="trigger-icon" name="CCrop" color="#585858" size="24" />
|
||||||
|
<div class="trigger-tips">
|
||||||
|
{{ $t("SellerListEdit.cropDesc") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<div class="trigger-img placeholder"></div>
|
||||||
|
<div class="trigger-tips">
|
||||||
|
{{ $t("SellerListEdit.productImageDesc") }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { TopImageType } from "../types"
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
images: Record<TopImageType, string | null>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "crop", data: string | null, type: TopImageType): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const topImageList: TopImageType[] = ["sketch", "mainProductImage", "cover"]
|
||||||
|
const topImageTitleMap: Record<TopImageType, string> = {
|
||||||
|
sketch: "SellerListEdit.sketch",
|
||||||
|
mainProductImage: "SellerListEdit.mainProductImage",
|
||||||
|
cover: "SellerListEdit.cover"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.c-svg {
|
||||||
|
width: initial;
|
||||||
|
height: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required {
|
||||||
|
&::after {
|
||||||
|
content: "*";
|
||||||
|
color: #df2b2c;
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-image-container {
|
||||||
|
column-gap: 3.5rem;
|
||||||
|
|
||||||
|
.main-image-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
margin-bottom: 0.8rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sketch-item {
|
||||||
|
width: 11.6rem;
|
||||||
|
height: 20.4rem;
|
||||||
|
border: 0.15rem solid #d1d1d1;
|
||||||
|
border-radius: 1rem;
|
||||||
|
position: relative;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.cover {
|
||||||
|
width: 16.2rem;
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' rx='11' ry='11' fill='none' stroke='%23D1D1D1' stroke-width='1.5' stroke-dasharray='8%2c 5' stroke-linecap='square'/%3e%3c/svg%3e");
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.crop-tool {
|
||||||
|
position: absolute;
|
||||||
|
top: 0.8rem;
|
||||||
|
right: 0.8rem;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #000000;
|
||||||
|
z-index: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sketch-img {
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
height: 100%;
|
||||||
|
&.sketch {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 100%;
|
||||||
|
padding: 6rem 2rem 0;
|
||||||
|
|
||||||
|
&,
|
||||||
|
.cover-trigger {
|
||||||
|
row-gap: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
width: 2.4rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
background: linear-gradient(135deg, #efefef 0%, #cdcdcd 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger-tips {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #585858;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
82
src/views/SellerDashboard/MyListings/EditDetail/types.ts
Normal file
82
src/views/SellerDashboard/MyListings/EditDetail/types.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
export type RadioOption = {
|
||||||
|
name: string | number
|
||||||
|
value: string | number | boolean
|
||||||
|
key: string
|
||||||
|
optype: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TopImageType = "sketch" | "mainProductImage" | "cover"
|
||||||
|
export type CropType = TopImageType | "apparel"
|
||||||
|
export type CoverSourceType = "sketch" | "mainProductImage"
|
||||||
|
export type ListingImageCategory =
|
||||||
|
| "cover"
|
||||||
|
| "cover_from"
|
||||||
|
| "main_product"
|
||||||
|
| "mainProductImage"
|
||||||
|
| "product"
|
||||||
|
| "sketch"
|
||||||
|
| "apparel"
|
||||||
|
| "firstFrame"
|
||||||
|
| "gif"
|
||||||
|
| "video"
|
||||||
|
|
||||||
|
export type ProductMediaItem = {
|
||||||
|
url: string
|
||||||
|
selected?: boolean
|
||||||
|
isVideo?: boolean
|
||||||
|
videoUrl?: string
|
||||||
|
gifUrl?: string
|
||||||
|
firstFrameUrl?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ListingItem = {
|
||||||
|
designItemId: number | string | null
|
||||||
|
sketch: string | null
|
||||||
|
mainProductImage: string
|
||||||
|
cover: string
|
||||||
|
productImage: string[]
|
||||||
|
apparelSketch: string[]
|
||||||
|
productName: string
|
||||||
|
price: string
|
||||||
|
desc: string
|
||||||
|
gender: string
|
||||||
|
category: string[] | null
|
||||||
|
coverFrom: CoverSourceType
|
||||||
|
firstSelectedIndex: number | null
|
||||||
|
prodImageList: ProductMediaItem[]
|
||||||
|
sketchList: Array<{ url: string | null }>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ListingDetailImage = {
|
||||||
|
category?: ListingImageCategory | string | null
|
||||||
|
imageUrl?: string | null
|
||||||
|
isSelected?: boolean | number | string | null
|
||||||
|
isSeleted?: boolean | number | string | null
|
||||||
|
selected?: boolean | number | string | null
|
||||||
|
sortOrder?: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ListingDetailResponse = {
|
||||||
|
id?: number | string | null
|
||||||
|
title?: string | null
|
||||||
|
description?: string | null
|
||||||
|
price?: number | string | null
|
||||||
|
designFor?: string | null
|
||||||
|
productCategory?: string | string[] | null
|
||||||
|
images?: ListingDetailImage[] | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SketchDetailVideo = {
|
||||||
|
firstFrameUrl?: string | null
|
||||||
|
gifUrl?: string | null
|
||||||
|
videoUrl?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SketchDetailResponse = {
|
||||||
|
clothes?: string[] | null
|
||||||
|
designItemId?: number | string | null
|
||||||
|
toProductImageUrls?: string[] | null
|
||||||
|
videos?: SketchDetailVideo[] | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type StatusType = "draft" | "publish"
|
||||||
@@ -41,7 +41,10 @@ const getCreateList = ()=>{
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const selectCollectionItem = (item:any)=>{
|
const selectCollectionItem = (item:any)=>{
|
||||||
|
console.log(item)
|
||||||
|
if(item.userLikeGroupVO?.groupDetails?.length > 0){
|
||||||
emit('selectCollectionItem',item)
|
emit('selectCollectionItem',item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
getCreateList()
|
getCreateList()
|
||||||
@@ -55,14 +58,17 @@ defineExpose({getCreateList})
|
|||||||
<div class="list">
|
<div class="list">
|
||||||
<div v-for="(item,index) in list" :key="index" class="item" @click="selectCollectionItem(item)">
|
<div v-for="(item,index) in list" :key="index" class="item" @click="selectCollectionItem(item)">
|
||||||
<div class="imgList">
|
<div class="imgList">
|
||||||
<div v-for="(img,index) in item.userLikeGroupVO?.groupDetails" :key="index" class="img">
|
<div v-if="item.userLikeGroupVO?.groupDetails?.length > 0" v-for="(img,index) in item.userLikeGroupVO?.groupDetails.slice(0, 4)" :key="index" class="img">
|
||||||
<img :src="img.url" alt="">
|
<img :src="img.url" alt="">
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="img null">
|
||||||
|
<img src="@/assets/images/seller/selectCollectionNullStatus.png" alt="">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<div class="name">{{item.name}}</div>
|
<div class="name">{{item.name}}</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<div>{{item.userLikeGroupVO?.groupDetails?.length || 0}} sketchs</div>
|
<div>{{item.userLikeGroupVO?.groupDetails?.length || 0}} {{ $t('Seller.sketchs') }}</div>
|
||||||
<div>{{setPubDate(item.updateTime,t)}}</div>
|
<div>{{setPubDate(item.updateTime,t)}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -123,8 +129,11 @@ defineExpose({getCreateList})
|
|||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
&.null{
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
> img{
|
> img{
|
||||||
object-fit: cover;
|
object-fit: contain;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,20 +40,13 @@ defineExpose({})
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="create-select">
|
<div class="create-select">
|
||||||
<seller-header
|
<seller-header />
|
||||||
title="Select Collection"
|
|
||||||
:breadcrumbs="[
|
|
||||||
{title:'My Listings', name:'myListingsIndex'},
|
|
||||||
{title:'Select Collection', name: 'myListingsSelect' }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
</seller-header>
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div :class="{active:!getCollectionListData.process?.[0]}" @click="setProcess('')">All</div>
|
<div :class="{active:!getCollectionListData.process?.[0]}" @click="setProcess('')">{{$t('Seller.All')}}</div>
|
||||||
<div :class="{active:getCollectionListData.process[0] == 'SERIES_DESIGN'}" @click="setProcess('SERIES_DESIGN')">Series Design</div>
|
<div :class="{active:getCollectionListData.process[0] == 'SERIES_DESIGN'}" @click="setProcess('SERIES_DESIGN')">{{$t('Seller.SeriesDesign')}}</div>
|
||||||
<div :class="{active:getCollectionListData.process[0] == 'SINGLE_DESIGN'}" @click="setProcess('SINGLE_DESIGN')">Single Design</div>
|
<div :class="{active:getCollectionListData.process[0] == 'SINGLE_DESIGN'}" @click="setProcess('SINGLE_DESIGN')">{{$t('Seller.SingleDesign')}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="search_input flex flex-align-center">
|
<div class="search_input flex flex-align-center">
|
||||||
@@ -62,7 +55,7 @@ defineExpose({})
|
|||||||
v-model="getCollectionListData.projectName"
|
v-model="getCollectionListData.projectName"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
@keydown.enter="handleSearch"
|
@keydown.enter="handleSearch"
|
||||||
placeholder="123123"
|
placeholder="Search"
|
||||||
/>
|
/>
|
||||||
<!-- <SearchOutlined class="search_input_icon" @click="handleSearch" /> -->
|
<!-- <SearchOutlined class="search_input_icon" @click="handleSearch" /> -->
|
||||||
<SvgIcon name="CSearch" size="20" class="search_input_icon" @click="handleSearch" />
|
<SvgIcon name="CSearch" size="20" class="search_input_icon" @click="handleSearch" />
|
||||||
|
|||||||
@@ -6,7 +6,14 @@ import selectMenu from '@/component/modules/selectMenu.vue'
|
|||||||
import { Https } from '@/tool/https'
|
import { Https } from '@/tool/https'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
// 定义组件名称
|
||||||
|
defineOptions({
|
||||||
|
name: 'myListingsSelectItem'
|
||||||
|
})
|
||||||
|
const { t } = useI18n()
|
||||||
//const props = defineProps({
|
//const props = defineProps({
|
||||||
//})
|
//})
|
||||||
//const emit = defineEmits([
|
//const emit = defineEmits([
|
||||||
@@ -18,15 +25,15 @@ const route = useRoute()
|
|||||||
const domSize = ref('Small')
|
const domSize = ref('Small')
|
||||||
const domSizeList = ref([
|
const domSizeList = ref([
|
||||||
{
|
{
|
||||||
label:'Small',
|
label:t('Header.Small'),
|
||||||
value:'Small',
|
value:'Small',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'Medium',
|
label:t('Header.Medium'),
|
||||||
value:'Medium',
|
value:'Medium',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'Large',
|
label:t('Header.Large'),
|
||||||
value:'Large',
|
value:'Large',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -36,17 +43,26 @@ const list = ref([
|
|||||||
const showList = ref([])
|
const showList = ref([])
|
||||||
const chooseList = ref([])
|
const chooseList = ref([])
|
||||||
const chooseItem = (item:any)=>{
|
const chooseItem = (item:any)=>{
|
||||||
|
if(chooseList.value.findIndex((i:any)=>i.designItemId == item.designItemId) != -1){
|
||||||
|
chooseList.value.splice(chooseList.value.findIndex((i:any)=>i.designItemId == item.designItemId),1)
|
||||||
|
}else{
|
||||||
|
if(chooseList.value.length >= 9){
|
||||||
|
message.info(t('Seller.selectSketchMaxNum'))
|
||||||
|
return
|
||||||
|
}
|
||||||
chooseList.value.push(item)
|
chooseList.value.push(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = ()=>{
|
const next = ()=>{
|
||||||
if(chooseList.value.length == 0)return
|
if(chooseList.value.length == 0)return
|
||||||
let designItemIds = chooseList.value.map((item:any)=>({designOutfitUrl:item.designOutfitUrl,designItemId:item.id}))
|
let designItemIds = chooseList.value.map((item:any)=>({designOutfitUrl:item.designOutfitUrl,designItemId:item.designItemId}))
|
||||||
router.push({
|
router.push({
|
||||||
path:'/home/seller/myListings/edit',
|
path:'/home/seller/myListings/edit',
|
||||||
state: {
|
state: {
|
||||||
id:route.params.collectionId,
|
|
||||||
designItemIds,
|
designItemIds,
|
||||||
|
type:'create',
|
||||||
|
collectionId: route.params.collectionId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -83,7 +99,7 @@ const setDomSize = (width: number)=>{
|
|||||||
if(!listingsBoxRef.value)return
|
if(!listingsBoxRef.value)return
|
||||||
let listDom = listingsBoxRef.value.querySelector('.list')
|
let listDom = listingsBoxRef.value.querySelector('.list')
|
||||||
let listItemDom = listDom.querySelector('.item')
|
let listItemDom = listDom.querySelector('.item')
|
||||||
let offsetWidth = listItemDom.getBoundingClientRect().width
|
let offsetWidth = listItemDom?.getBoundingClientRect?.()?.width
|
||||||
let lineNum = Math.floor(width / offsetWidth)
|
let lineNum = Math.floor(width / offsetWidth)
|
||||||
let itemNum = Math.floor((width - (lineNum - 1) * parseInt(gap.value[domSize.value])) / offsetWidth)
|
let itemNum = Math.floor((width - (lineNum - 1) * parseInt(gap.value[domSize.value])) / offsetWidth)
|
||||||
listDom.style.maxWidth = ((itemNum - 1) * parseInt(gap.value[domSize.value]) + itemNum * (offsetWidth)) + 'px'
|
listDom.style.maxWidth = ((itemNum - 1) * parseInt(gap.value[domSize.value]) + itemNum * (offsetWidth)) + 'px'
|
||||||
@@ -136,8 +152,11 @@ onMounted(()=>{
|
|||||||
// 开始监听
|
// 开始监听
|
||||||
if(resizeObserver)resizeObserver.observe(listingsBoxRef.value)
|
if(resizeObserver)resizeObserver.observe(listingsBoxRef.value)
|
||||||
})
|
})
|
||||||
|
chooseList.value = []
|
||||||
getCollectionDetail()
|
getCollectionDetail()
|
||||||
})
|
})
|
||||||
|
onActivated(()=>{
|
||||||
|
})
|
||||||
onUnmounted(()=>{
|
onUnmounted(()=>{
|
||||||
})
|
})
|
||||||
defineExpose({})
|
defineExpose({})
|
||||||
@@ -145,21 +164,14 @@ const {} = toRefs(data);
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="create-select-item">
|
<div class="create-select-item">
|
||||||
<seller-header
|
<seller-header>
|
||||||
title="Select Collection"
|
|
||||||
:breadcrumbs="[
|
|
||||||
{title:'My Listings', name:'myListingsIndex'},
|
|
||||||
{title:'Select Collection', name: 'myListingsSelect' },
|
|
||||||
{title:'Select Sketch', name: 'myListingsSelectItem' }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<template #right>
|
<template #right>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="chooseNum">
|
<div class="chooseNum">
|
||||||
{{ chooseList.length }} sketches selected
|
{{ chooseList.length }} / 9 {{ t('Seller.sketchesSelected') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="button" @click="next">
|
<div class="button" @click="next">
|
||||||
<span>Next</span>
|
<span>{{ $t('Seller.Next') }}</span>
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="fi fi-rr-arrow-small-right"></i>
|
<i class="fi fi-rr-arrow-small-right"></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -171,7 +183,7 @@ const {} = toRefs(data);
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<i class="fi fi-rs-comments"></i>
|
<i class="fi fi-rs-comments"></i>
|
||||||
<span>Active Listings</span>
|
<span>{{ $t('Seller.Praka') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="generalModel_state">
|
<div class="generalModel_state">
|
||||||
@@ -310,6 +322,7 @@ const {} = toRefs(data);
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
|
min-width: 90%;
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -364,7 +377,8 @@ const {} = toRefs(data);
|
|||||||
}
|
}
|
||||||
> img{
|
> img{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
width: 100%;
|
||||||
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
&.active{
|
&.active{
|
||||||
border: 1.5px solid #000;
|
border: 1.5px solid #000;
|
||||||
|
|||||||
@@ -4,37 +4,34 @@ import { VueDraggable } from "vue-draggable-plus"
|
|||||||
import contentItem from "./contentItem.vue"
|
import contentItem from "./contentItem.vue"
|
||||||
import selectMenu from '@/component/modules/selectMenu.vue'
|
import selectMenu from '@/component/modules/selectMenu.vue'
|
||||||
import deleteDrafts from './deleteDrafts.vue'
|
import deleteDrafts from './deleteDrafts.vue'
|
||||||
|
import { Https } from '@/tool/https'
|
||||||
|
import { message } from 'ant-design-vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
//const props = defineProps({
|
//const props = defineProps({
|
||||||
//})
|
//})
|
||||||
//const emit = defineEmits([
|
//const emit = defineEmits([
|
||||||
//])
|
//])
|
||||||
|
const { t:$t } = useI18n()
|
||||||
let data = reactive({
|
let data = reactive({
|
||||||
showDrafts: false,
|
showDrafts: false,
|
||||||
})
|
})
|
||||||
|
const publishData = reactive({
|
||||||
|
pageSize: 10,
|
||||||
|
pageNum: 1,
|
||||||
|
isShowMark:false,
|
||||||
|
isNoData:false,
|
||||||
|
})
|
||||||
|
const noPublishData = reactive({
|
||||||
|
pageSize: 10,
|
||||||
|
pageNum: 1,
|
||||||
|
isShowMark:false,
|
||||||
|
isNoData:false,
|
||||||
|
})
|
||||||
const list = ref([
|
const list = ref([
|
||||||
{ id: "1" },
|
|
||||||
{ id: "2" },
|
|
||||||
{ id: "3" },
|
|
||||||
{ id: "4" },
|
|
||||||
{ id: "5" },
|
|
||||||
{ id: "6" },
|
|
||||||
{ id: "7" },
|
|
||||||
{ id: "8" },
|
|
||||||
{ id: "9" },
|
|
||||||
{ id: "10" }
|
|
||||||
])
|
])
|
||||||
const list2 = ref([
|
const list2 = ref([
|
||||||
{ id: "1" },
|
|
||||||
{ id: "2" },
|
|
||||||
{ id: "3" },
|
|
||||||
{ id: "4" },
|
|
||||||
{ id: "5" },
|
|
||||||
{ id: "6" },
|
|
||||||
{ id: "7" },
|
|
||||||
{ id: "8" },
|
|
||||||
{ id: "9" },
|
|
||||||
{ id: "10" }
|
|
||||||
])
|
])
|
||||||
const config = ref({
|
const config = ref({
|
||||||
"data-container-type": "root",
|
"data-container-type": "root",
|
||||||
@@ -55,40 +52,130 @@ const config = ref({
|
|||||||
const domSize = ref('Small')
|
const domSize = ref('Small')
|
||||||
const domSizeList = ref([
|
const domSizeList = ref([
|
||||||
{
|
{
|
||||||
label:'Small',
|
label:$t('Header.Small'),
|
||||||
value:'Small',
|
value:'Small',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'Medium',
|
label:$t('Header.Medium'),
|
||||||
value:'Medium',
|
value:'Medium',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label:'Large',
|
label:$t('Header.Large'),
|
||||||
value:'Large',
|
value:'Large',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const deleteDraftsRef = ref(null)
|
const deleteDraftsRef = ref(null)
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const deleteDraft = (item: any)=>{
|
const deleteDraft = (item: any)=>{
|
||||||
deleteDraftsRef.value.open(()=>{
|
deleteDraftsRef.value.open(item,()=>{
|
||||||
|
putListingStatus(item,2).then(()=>{
|
||||||
list2.value = list2.value.filter((v: any)=>v.id != item.id)
|
list2.value = list2.value.filter((v: any)=>v.id != item.id)
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const draftListing = (item: any)=>{
|
const vObserve = {
|
||||||
//数组前面添加item
|
mounted (el,binding) {
|
||||||
list2.value.unshift(item)
|
// console.log(binding.instance);
|
||||||
list.value = list.value.filter((v: any)=>v.id != item.id)
|
data.isShowMark = false
|
||||||
|
data.isNoData = false
|
||||||
|
let parentDom = el.parentNode
|
||||||
|
new IntersectionObserver(
|
||||||
|
(entries, observer) => {
|
||||||
|
// 如果不是相交,则直接返回
|
||||||
|
// console.log(entries[0]);
|
||||||
|
if (!entries[0].intersectionRatio) return;
|
||||||
|
data.pageNum += 1
|
||||||
|
binding.value()
|
||||||
|
},
|
||||||
|
// { root:worksPage }
|
||||||
|
).observe(el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const publishListing = (item: any)=>{
|
const getPublishedData = async ()=>{
|
||||||
|
if(publishData.isShowMark && !publishData.isNoData)return
|
||||||
|
publishData.isShowMark = true
|
||||||
|
let value = {
|
||||||
|
pageSize: publishData.pageSize,
|
||||||
|
pageNum: publishData.pageNum,
|
||||||
|
status: 1,
|
||||||
|
}
|
||||||
|
await getPublishList(value).then((res)=>{
|
||||||
|
if(res.content.length == 0)publishData.isNoData = true
|
||||||
|
publishData.pageNum += 1
|
||||||
|
list.value.push(...res.content)
|
||||||
|
})
|
||||||
|
publishData.isShowMark = false
|
||||||
|
}
|
||||||
|
const getNoPublishedData = async ()=>{
|
||||||
|
if(noPublishData.isShowMark && !noPublishData.isNoData)return
|
||||||
|
noPublishData.isShowMark = true
|
||||||
|
let value = {
|
||||||
|
pageSize: noPublishData.pageSize,
|
||||||
|
pageNum: noPublishData.pageNum,
|
||||||
|
status: 0,
|
||||||
|
}
|
||||||
|
await getPublishList(value).then((res)=>{
|
||||||
|
if(res.content.length == 0)noPublishData.isNoData = true
|
||||||
|
noPublishData.pageNum += 1
|
||||||
|
list2.value.push(...res.content)
|
||||||
|
})
|
||||||
|
noPublishData.isShowMark = false
|
||||||
|
}
|
||||||
|
const getPublishList = (data:any)=>{
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
Https.axiosGet(Https.httpUrls.getListingList,{params:data}).then((res:any)=>{
|
||||||
|
resolve(res)
|
||||||
|
}).catch((err:any)=>{
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const putListingStatus = async (item,status:number)=>{
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
let data = {
|
||||||
|
id:item.id,
|
||||||
|
status:status,
|
||||||
|
}
|
||||||
|
Https.axiosPut(Https.httpUrls.putListingStatus,data).then((res:any)=>{
|
||||||
|
resolve(res)
|
||||||
|
}).catch((err:any)=>{
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const draftListing = async (item: any)=>{
|
||||||
|
//数组前面添加item
|
||||||
|
await putListingStatus(item,0).then(()=>{
|
||||||
|
list2.value.unshift(item)
|
||||||
|
list.value = list.value.filter((v: any)=>v.id != item.id)
|
||||||
|
})
|
||||||
|
message.success($t('Seller.draftMessage'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const publishListing = async (item: any)=>{
|
||||||
|
await putListingStatus(item,1).then(()=>{
|
||||||
list.value.unshift(item)
|
list.value.unshift(item)
|
||||||
list2.value = list2.value.filter((v: any)=>v.id != item.id)
|
list2.value = list2.value.filter((v: any)=>v.id != item.id)
|
||||||
|
})
|
||||||
|
message.success($t('Seller.publishMessage'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const editListing = (item: any)=>{
|
const editListing = (item: any)=>{
|
||||||
|
router.push({
|
||||||
|
path:'/home/seller/myListings/edit',
|
||||||
|
state: {
|
||||||
|
id:item.id,
|
||||||
|
type:'edit'
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -107,7 +194,7 @@ const setDomSize = (width: number)=>{
|
|||||||
if(!listingsBoxRef.value)return
|
if(!listingsBoxRef.value)return
|
||||||
let listDom = listingsBoxRef.value.querySelector('.list')
|
let listDom = listingsBoxRef.value.querySelector('.list')
|
||||||
let listItemDom = listDom.querySelector('.item')
|
let listItemDom = listDom.querySelector('.item')
|
||||||
let offsetWidth = listItemDom.getBoundingClientRect().width
|
let offsetWidth = listItemDom?.getBoundingClientRect?.()?.width
|
||||||
let lineNum = Math.floor(width / offsetWidth)
|
let lineNum = Math.floor(width / offsetWidth)
|
||||||
let itemNum = Math.floor((width - (lineNum - 1) * parseInt(gap.value[domSize.value])) / offsetWidth)
|
let itemNum = Math.floor((width - (lineNum - 1) * parseInt(gap.value[domSize.value])) / offsetWidth)
|
||||||
listDom.style.maxWidth = ((itemNum - 1) * parseInt(gap.value[domSize.value]) + itemNum * (offsetWidth)) + 'px'
|
listDom.style.maxWidth = ((itemNum - 1) * parseInt(gap.value[domSize.value]) + itemNum * (offsetWidth)) + 'px'
|
||||||
@@ -127,11 +214,7 @@ onMounted(()=>{
|
|||||||
nextTick(()=>{
|
nextTick(()=>{
|
||||||
resizeObserver = new ResizeObserver((entries) => {
|
resizeObserver = new ResizeObserver((entries) => {
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
// 获取元素尺寸
|
|
||||||
const width = entry.contentRect.width
|
const width = entry.contentRect.width
|
||||||
const height = entry.contentRect.height
|
|
||||||
const borderBoxSize = entry.borderBoxSize[0] // 包含边框
|
|
||||||
const contentBoxSize = entry.contentBoxSize[0] // 内容区域
|
|
||||||
if(upDataDomWidthTime)clearTimeout(upDataDomWidthTime)
|
if(upDataDomWidthTime)clearTimeout(upDataDomWidthTime)
|
||||||
upDataDomWidthTime = setTimeout(()=>{
|
upDataDomWidthTime = setTimeout(()=>{
|
||||||
setDomSize(width)
|
setDomSize(width)
|
||||||
@@ -156,31 +239,10 @@ const { showDrafts } = toRefs(data);
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<i class="fi fi-rs-comments"></i>
|
<i class="fi fi-rs-comments"></i>
|
||||||
<span>Active Listings</span>
|
<span>{{ $t('Seller.ActiveListings') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="generalModel_state">
|
<div class="generalModel_state">
|
||||||
<div>
|
|
||||||
<selectMenu
|
|
||||||
:selectList="domSizeList"
|
|
||||||
@change="changeDomSize"
|
|
||||||
:isBtnOpen='true'
|
|
||||||
:style="{
|
|
||||||
'border-radius':'0rem',
|
|
||||||
'border':'none',
|
|
||||||
'font-weight': '900',
|
|
||||||
'border-right':'2px solid rgba(0,0,0,.2)',
|
|
||||||
'line-height': '3rem',
|
|
||||||
'height': '3rem',
|
|
||||||
'background': 'rgba(0,0,0,0)',
|
|
||||||
}"
|
|
||||||
v-model:select="domSize"
|
|
||||||
>
|
|
||||||
<template v-slot:btnText>
|
|
||||||
{{ $t('Header.Filter') }}
|
|
||||||
</template>
|
|
||||||
</selectMenu>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<selectMenu
|
<selectMenu
|
||||||
:selectList="domSizeList"
|
:selectList="domSizeList"
|
||||||
@@ -225,6 +287,12 @@ const { showDrafts } = toRefs(data);
|
|||||||
@draftListing="draftListing"
|
@draftListing="draftListing"
|
||||||
@editListing="editListing"
|
@editListing="editListing"
|
||||||
/>
|
/>
|
||||||
|
<div v-show="!publishData.isNoData" class="material_content_list_loding">
|
||||||
|
<span class="page_loading" v-show="!publishData.isShowMark" v-observe="getPublishedData"></span>
|
||||||
|
<span v-show="publishData.isShowMark">
|
||||||
|
<a-spin size="large" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</VueDraggable>
|
</VueDraggable>
|
||||||
</div>
|
</div>
|
||||||
<div class="openOrCloseDrafts" :class="{'active': showDrafts}" @click="unfoldDrafits">
|
<div class="openOrCloseDrafts" :class="{'active': showDrafts}" @click="unfoldDrafits">
|
||||||
@@ -236,7 +304,7 @@ const { showDrafts } = toRefs(data);
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<i class="fi fi-rs-comments"></i>
|
<i class="fi fi-rs-comments"></i>
|
||||||
<span>Drafts</span>
|
<span>{{ $t('Seller.Drafts') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<VueDraggable
|
<VueDraggable
|
||||||
@@ -259,6 +327,12 @@ const { showDrafts } = toRefs(data);
|
|||||||
@editListing="editListing"
|
@editListing="editListing"
|
||||||
@publishListing="publishListing"
|
@publishListing="publishListing"
|
||||||
/>
|
/>
|
||||||
|
<div v-show="!noPublishData.isNoData" class="material_content_list_loding">
|
||||||
|
<span class="page_loading" v-show="!noPublishData.isShowMark" v-observe="getNoPublishedData"></span>
|
||||||
|
<span v-show="noPublishData.isShowMark">
|
||||||
|
<a-spin size="large" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</VueDraggable>
|
</VueDraggable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -326,9 +400,23 @@ const { showDrafts } = toRefs(data);
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
min-width: 90%;
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
> .material_content_list_loding{
|
||||||
|
width: 100%;
|
||||||
|
height: 5rem;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
> img{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,39 +32,39 @@ const {} = toRefs(data);
|
|||||||
<template>
|
<template>
|
||||||
<div class="item" :draging="true" :class="domSize">
|
<div class="item" :draging="true" :class="domSize">
|
||||||
<div class="imgBox">
|
<div class="imgBox">
|
||||||
<img src="" alt="">
|
<img :src="item.cover" alt="">
|
||||||
<div class="maskBtn">
|
<div class="maskBtn">
|
||||||
<div @click="$emit('editListing',item)">
|
<div @click="$emit('editListing',item)">
|
||||||
<svgIcon name="seller-edit" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
|
<svgIcon name="seller-edit" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
|
||||||
<div>Edit</div>
|
<div>{{ $t('Seller.Edit') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="type == 'listings'" @click="$emit('draftListing',item)">
|
<div v-if="type == 'listings'" @click="$emit('draftListing',item)">
|
||||||
<svgIcon name="seller-draft" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
|
<svgIcon name="seller-draft" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
|
||||||
<div>Draft</div>
|
<div>{{ $t('Seller.Draft') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="type == 'drafts'" @click="$emit('publishListing',item)">
|
<div v-else-if="type == 'drafts'" @click="$emit('publishListing',item)">
|
||||||
<svgIcon name="seller-share" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
|
<svgIcon name="seller-share" :size="domSize == 'Small'?32:domSize == 'Medium'?40:48" />
|
||||||
<div>Publish</div>
|
<div>{{ $t('Seller.Publish') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="name">item name</div>
|
<div class="name">{{item.title}}</div>
|
||||||
<div class="price">$1123</div>
|
<div class="price">${{item.price}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="detailItem" v-if="type == 'listings'">
|
<div class="detailItem" v-if="type == 'listings'">
|
||||||
<div class="shopping1">
|
<div class="shopping1">
|
||||||
<i class="fi fi-rr-shopping-bag-add"></i>
|
<i class="fi fi-rr-shopping-bag-add"></i>
|
||||||
</div>
|
</div>
|
||||||
<span>123</span>
|
<span>{{ item.salesVolume || 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detailItem" v-if="type == 'listings'">
|
<div class="detailItem" v-if="type == 'listings'">
|
||||||
<div class="eye1">
|
<div class="eye1">
|
||||||
<i class="fi fi-rs-eye"></i>
|
<i class="fi fi-rs-eye"></i>
|
||||||
</div>
|
</div>
|
||||||
<span>123</span>
|
<span>{{ item.viewCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detailItem drafts" v-if="type == 'drafts'" @click="$emit('deleteDraft',item)">
|
<div class="detailItem drafts" v-if="type == 'drafts'" @click="$emit('deleteDraft',item)">
|
||||||
<div class="">
|
<div class="">
|
||||||
@@ -128,6 +128,12 @@ const {} = toRefs(data);
|
|||||||
position: relative;
|
position: relative;
|
||||||
height: var(--itemImgHeight);
|
height: var(--itemImgHeight);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
> img{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
> .maskBtn{
|
> .maskBtn{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -182,6 +188,7 @@ const {} = toRefs(data);
|
|||||||
gap: var(--detailRightItemGap);
|
gap: var(--detailRightItemGap);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
> div{
|
> div{
|
||||||
color: var(--rightColor);
|
color: var(--rightColor);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -15,12 +15,14 @@ const router = useRouter()
|
|||||||
const {t} = useI18n()
|
const {t} = useI18n()
|
||||||
let data = reactive({
|
let data = reactive({
|
||||||
})
|
})
|
||||||
|
const item = ref<any>()
|
||||||
const fun = ref(null)
|
const fun = ref(null)
|
||||||
|
|
||||||
let deleteDraftsRef = ref(null)
|
let deleteDraftsRef = ref(null)
|
||||||
|
|
||||||
const open = (deleteFun)=>{
|
const open = (data:any,deleteFun)=>{
|
||||||
|
console.log(data)
|
||||||
|
item.value = data
|
||||||
fun.value = deleteFun
|
fun.value = deleteFun
|
||||||
emit('update:visible', true)
|
emit('update:visible', true)
|
||||||
}
|
}
|
||||||
@@ -35,6 +37,7 @@ const deleteDrafts = ()=>{
|
|||||||
|
|
||||||
|
|
||||||
const cleardata = ()=>{
|
const cleardata = ()=>{
|
||||||
|
item.value = null
|
||||||
emit('update:visible', false)
|
emit('update:visible', false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,22 +75,22 @@ const { showAgain } = toRefs(data);
|
|||||||
<i class="fi fi-rr-trash"></i>
|
<i class="fi fi-rr-trash"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="titleText">
|
<div class="titleText">
|
||||||
<h1>Delete this listing?</h1>
|
<h1>{{ $t('Seller.DeleteConfirm') }}</h1>
|
||||||
<p>Your listing and its details will be permanently removed.</p>
|
<p>{{ $t('Seller.DeleteDesc') }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="deleteContent">
|
<div class="deleteContent">
|
||||||
<div class="img">
|
<div class="img">
|
||||||
<img src="" alt="">
|
<img :src="item?.cover" alt="">
|
||||||
</div>
|
</div>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<div class="name">Item Name</div>
|
<div class="name">{{ item?.title }}</div>
|
||||||
<div class="price">HK$392.00 · Draft</div>
|
<div class="price">HK${{ item?.price }} · {{ $t('Seller.Drafts') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btnBox">
|
<div class="btnBox">
|
||||||
<div class="btn" @click.stop="cleardata()">Cancel</div>
|
<div class="btn" @click.stop="cleardata()">{{ $t('Seller.Cancel') }}</div>
|
||||||
<div class="btn" @click.stop="deleteDrafts()">Delete</div>
|
<div class="btn" @click.stop="deleteDrafts()">{{ $t('Seller.Delete') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -41,13 +41,10 @@ const {} = toRefs(data);
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="myListings-seller">
|
<div class="myListings-seller">
|
||||||
<seller-header
|
<seller-header :displayBack="false">
|
||||||
title="My Listings"
|
|
||||||
tip="Active listings and unpublished inventory."
|
|
||||||
>
|
|
||||||
<template #right>
|
<template #right>
|
||||||
<div class="button" @click="newListing">
|
<div class="button" @click="newListing">
|
||||||
<span>New Listing</span>
|
<span>{{ $t('Seller.newListing') }}</span>
|
||||||
<div class="icon">
|
<div class="icon">
|
||||||
<i class="fi fi-br-plus"></i>
|
<i class="fi fi-br-plus"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="filter-box">
|
<div class="filter-box">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="title">All Invoice</div>
|
<div class="title">{{ t("Seller.allInvoice") }}</div>
|
||||||
<div class="tip">A summary of all completed transactions.</div>
|
<div class="tip">{{ t("Seller.myOrdersTip") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
v-model="nameOrId"
|
v-model="nameOrId"
|
||||||
placeholder="Search by item name or order ID"
|
:placeholder="t('Seller.myOrdersSearchPlaceholder')"
|
||||||
@keydown.enter.prevent="getList(true)"
|
@keydown.enter.prevent="getList(true)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,11 +30,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="table">
|
<div class="table">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="order-id">Order ID</div>
|
<div class="order-id">{{ t("Seller.orderId") }}</div>
|
||||||
<div class="item">Item</div>
|
<div class="item">{{ t("Seller.item") }}</div>
|
||||||
<div class="price">Price</div>
|
<div class="price">{{ t("Seller.price") }}</div>
|
||||||
<div class="buyer-username">Buyer Username</div>
|
<div class="buyer-username">{{ t("Seller.buyerUsername") }}</div>
|
||||||
<div class="date">Date</div>
|
<div class="date">{{ t("Seller.date") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="item" v-for="v in list" :key="v.orderId">
|
<div class="item" v-for="v in list" :key="v.orderId">
|
||||||
@@ -65,7 +65,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="null" v-show="list.length === 0 && !loading && finish">no data</div>
|
<div class="null" v-show="list.length === 0 && !loading && finish">
|
||||||
|
<img src="@/assets/images/homePage/null_img.png" alt="" />
|
||||||
|
</div>
|
||||||
<div class="placeholder" ref="placeholderRef" v-show="!loading"></div>
|
<div class="placeholder" ref="placeholderRef" v-show="!loading"></div>
|
||||||
<div class="footer" :class="{ null: list.length === 0 }" v-if="!finish">
|
<div class="footer" :class="{ null: list.length === 0 }" v-if="!finish">
|
||||||
<a-spin :delay="0.5" v-show="loading" />
|
<a-spin :delay="0.5" v-show="loading" />
|
||||||
@@ -77,6 +79,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onBeforeUnmount, computed } from "vue"
|
import { ref, onMounted, onBeforeUnmount, computed } from "vue"
|
||||||
import { Https } from "@/tool/https"
|
import { Https } from "@/tool/https"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
const totals_obj = ref({
|
const totals_obj = ref({
|
||||||
totalRevenue: "--",
|
totalRevenue: "--",
|
||||||
totalPurchases: "--",
|
totalPurchases: "--",
|
||||||
@@ -85,17 +89,17 @@
|
|||||||
const totals = computed(() => [
|
const totals = computed(() => [
|
||||||
{
|
{
|
||||||
icon: "seller-qiandaizi",
|
icon: "seller-qiandaizi",
|
||||||
title: "Total Revenue",
|
title: t("Seller.totalRevenue"),
|
||||||
value: `HK$ ${totals_obj.value.totalRevenue}`
|
value: `HK$ ${totals_obj.value.totalRevenue}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "seller-gouwudai",
|
icon: "seller-gouwudai",
|
||||||
title: "Total Purchases",
|
title: t("Seller.totalPurchases"),
|
||||||
value: totals_obj.value.totalPurchases
|
value: totals_obj.value.totalPurchases
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "seller-eye",
|
icon: "seller-eye",
|
||||||
title: "Total Views",
|
title: t("Seller.totalViews"),
|
||||||
value: totals_obj.value.totalViews
|
value: totals_obj.value.totalViews
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@@ -120,7 +124,8 @@
|
|||||||
size: size.value
|
size: size.value
|
||||||
}
|
}
|
||||||
if (nameOrId.value) data.keyword = nameOrId.value
|
if (nameOrId.value) data.keyword = nameOrId.value
|
||||||
Https.axiosGet(Https.httpUrls.getSellerOrderList, { params: data }).then((res) => {
|
Https.axiosGet(Https.httpUrls.getSellerOrderList, { params: data })
|
||||||
|
.then((res) => {
|
||||||
res.content?.forEach((v) => {
|
res.content?.forEach((v) => {
|
||||||
const obj = {
|
const obj = {
|
||||||
orderId: v.orderId,
|
orderId: v.orderId,
|
||||||
@@ -142,6 +147,10 @@
|
|||||||
finish.value = page.value > total.value / size.value
|
finish.value = page.value > total.value / size.value
|
||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
|
.catch(() => {
|
||||||
|
finish.value = true
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const getSummary = () => {
|
const getSummary = () => {
|
||||||
Https.axiosGet(Https.httpUrls.getSellerOrderSummary).then((res) => {
|
Https.axiosGet(Https.httpUrls.getSellerOrderSummary).then((res) => {
|
||||||
@@ -360,8 +369,14 @@
|
|||||||
}
|
}
|
||||||
> .null {
|
> .null {
|
||||||
margin-top: 10rem;
|
margin-top: 10rem;
|
||||||
text-align: center;
|
display: flex;
|
||||||
color: #999;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
> img {
|
||||||
|
width: 30rem;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
> .footer {
|
> .footer {
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
<div class="settings-index">
|
<div class="settings-index">
|
||||||
<div>
|
<div>
|
||||||
<div class="notification">
|
<div class="notification">
|
||||||
<div class="header">Notifications</div>
|
<div class="header">{{ $t("Seller.notifications") }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="title">New order notification</div>
|
<div class="title">{{ $t("Seller.notificationsTitle") }}</div>
|
||||||
<div class="tip">Receive an inbox message when a new order is placed.</div>
|
<div class="tip">{{ $t("Seller.notificationsTip") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<a-switch v-model:checked="checked" />
|
<a-switch v-model:checked="checked" />
|
||||||
@@ -14,29 +14,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="payout">
|
<div class="payout">
|
||||||
<div class="header">Payout</div>
|
<div class="header">{{ $t("Seller.payout") }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="title">Payment Providers</div>
|
<div class="title">{{ $t("Seller.payoutTitle") }}</div>
|
||||||
<div class="tip">Select how you want to receive payments.</div>
|
<div class="tip">{{ $t("Seller.payoutTip") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pay-item" v-for="v in payList" :key="v.type">
|
<div class="pay-item" v-for="v in payList" :key="v.type">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<img :src="v.icon" />
|
<img :src="v.icon" />
|
||||||
<div class="value">{{ v.value || "Unbound" }}</div>
|
<div class="value">{{ v.value || $t("Seller.unbound") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<button v-if="v.value" class="manage">Manage</button>
|
<button v-if="v.value" class="manage">{{ $t("Seller.manage") }}</button>
|
||||||
<button v-else class="bind-now">Bind Now</button>
|
<button v-else class="bind-now">{{ $t("Seller.bindNow") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="title">Payment Currency</div>
|
<div class="title">{{ $t("Seller.paymentCurrency") }}</div>
|
||||||
<div class="tip">HKD - Hong Kong Dollar</div>
|
<div class="tip">{{ $t("Seller.HKD") }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<button>Fixed</button>
|
<button>{{ $t("Seller.fixed") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,40 +44,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="data-privacy">
|
<div class="data-privacy">
|
||||||
<div class="header">Data & Privacy</div>
|
<div class="header">{{ $t("Seller.dataPrivacy") }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="title">Copyright licence</div>
|
<div class="title">{{ $t("Seller.dataPrivacyTitle") }}</div>
|
||||||
<div class="tip">
|
<div class="tip">{{ $t("Seller.dataPrivacyTip1") }}</div>
|
||||||
A licence certificate is automatically included with every purchase
|
<div class="tip">{{ $t("Seller.dataPrivacyTip2") }}</div>
|
||||||
download. View the default licensing terms applied to your listings.
|
<div
|
||||||
</div>
|
class="tip"
|
||||||
<div class="tip">
|
v-html="
|
||||||
This licence is issued by Code-Create and is legally binding upon purchase.
|
$t('Seller.dataPrivacyTip3', { click: 'onSellerSettingsContactUs' })
|
||||||
It certifies the buyer's right to use the purchased design asset in
|
"
|
||||||
accordance with the terms below.
|
></div>
|
||||||
</div>
|
|
||||||
<div class="tip">
|
|
||||||
For custom licensing arrangements, <span>contact us</span>.
|
|
||||||
</div>
|
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<button>
|
<button @click="onDownloadDataPrivacy">
|
||||||
<span class="icon"><svg-icon name="seller-download" size="14" /></span>
|
<span class="icon"><svg-icon name="seller-download" size="14" /></span>
|
||||||
<span class="label">Download to View</span>
|
<span class="label">{{ $t("Seller.downloadToView") }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stop">
|
<div class="stop">
|
||||||
<div class="header">Stop Selling</div>
|
<div class="header">{{ $t("Seller.stopSelling") }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="title">Deactivate seller account</div>
|
<div class="title">{{ $t("Seller.stopSellingTitle") }}</div>
|
||||||
<div class="tip">
|
<div class="tip">{{ $t("Seller.stopSellingTip") }}</div>
|
||||||
Permanently deactivate your seller account. All listings and invoice records
|
|
||||||
will be deleted. You may re-register as a seller in the future, but your
|
|
||||||
previous sales data cannot be recovered.
|
|
||||||
</div>
|
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<button>Deactivate</button>
|
<button @click="onStopSelling">{{ $t("Seller.deactivate") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,10 +79,19 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue"
|
import { ref } from "vue"
|
||||||
|
import { Https } from "@/tool/https"
|
||||||
|
import { Modal } from "ant-design-vue"
|
||||||
import paypal from "@/assets/images/seller/setting/paypal.png"
|
import paypal from "@/assets/images/seller/setting/paypal.png"
|
||||||
import stripe from "@/assets/images/seller/setting/stripe.png"
|
import stripe from "@/assets/images/seller/setting/stripe.png"
|
||||||
import alipayHk from "@/assets/images/seller/setting/alipay-hk.png"
|
import alipayHk from "@/assets/images/seller/setting/alipay-hk.png"
|
||||||
import alipayChinese from "@/assets/images/seller/setting/alipay-chinese.png"
|
import alipayChinese from "@/assets/images/seller/setting/alipay-chinese.png"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
|
import { useStore } from "vuex"
|
||||||
|
const store = useStore()
|
||||||
|
import { useRouter } from "vue-router"
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const checked = ref(true)
|
const checked = ref(true)
|
||||||
const payList = ref([
|
const payList = ref([
|
||||||
{
|
{
|
||||||
@@ -114,6 +115,33 @@
|
|||||||
value: "123123"
|
value: "123123"
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
window.onSellerSettingsContactUs = () => {
|
||||||
|
console.log("contact us")
|
||||||
|
}
|
||||||
|
const onDownloadDataPrivacy = () => {
|
||||||
|
console.log("download data privacy")
|
||||||
|
}
|
||||||
|
const onStopSelling = () => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t("Seller.stopSellingTitle"),
|
||||||
|
content: t("Seller.stopSellingTip"),
|
||||||
|
okText: t("Seller.confirm"),
|
||||||
|
cancelText: t("Seller.cancel"),
|
||||||
|
centered: true,
|
||||||
|
onOk() {
|
||||||
|
store.commit("set_loading", true)
|
||||||
|
Https.axiosDelete(Https.httpUrls.deleteSellerDesigner)
|
||||||
|
.then((res) => {
|
||||||
|
store.commit("set_loading", false)
|
||||||
|
store.commit("seller/clear_state")
|
||||||
|
router.push({ name: "home" })
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
store.commit("set_loading", false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.settings-index {
|
.settings-index {
|
||||||
@@ -281,7 +309,7 @@
|
|||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
color: #999;
|
color: #999;
|
||||||
margin-bottom: 3rem;
|
margin-bottom: 3rem;
|
||||||
> span {
|
&:deep(*) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: #0080ed;
|
color: #0080ed;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="seller-dashboard-index">
|
<div class="seller-dashboard-index" v-if="isSeller">
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<div
|
<div
|
||||||
v-for="v in list"
|
v-for="v in list"
|
||||||
@@ -12,7 +12,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<router-view></router-view>
|
<router-view v-slot="{ Component }">
|
||||||
|
<keep-alive :include="cachedRoutes">
|
||||||
|
<component :is="Component" />
|
||||||
|
</keep-alive>
|
||||||
|
</router-view>
|
||||||
<toolTipBox v-model:visible="visible" @close="() => {}" ref="toolTipBoxRef"></toolTipBox>
|
<toolTipBox v-model:visible="visible" @close="() => {}" ref="toolTipBoxRef"></toolTipBox>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -24,30 +28,40 @@
|
|||||||
import toolTipBox from "./toolTipBox.vue"
|
import toolTipBox from "./toolTipBox.vue"
|
||||||
import myEvent from "@/tool/myEvents.js"
|
import myEvent from "@/tool/myEvents.js"
|
||||||
import { useStore } from "vuex"
|
import { useStore } from "vuex"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
cachedRoutes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
store.dispatch("seller/get_designerInfo")
|
const isSeller = computed(() => store.state.seller.isSeller)
|
||||||
|
// store.dispatch("seller/get_designerInfo")
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const list = ref([
|
const list = ref([
|
||||||
{
|
{
|
||||||
icon: "seller-brandProfile",
|
icon: "seller-brandProfile",
|
||||||
layer: "Brand Profile",
|
layer: t("Seller.brandProfile"),
|
||||||
path: "/home/seller/brandProfile"
|
path: "/home/seller/brandProfile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "seller-myListings",
|
icon: "seller-myListings",
|
||||||
layer: "My Listings",
|
layer: t("Seller.myListings"),
|
||||||
path: "/home/seller/myListings"
|
path: "/home/seller/myListings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "seller-myOrders",
|
icon: "seller-myOrders",
|
||||||
layer: "My Orders",
|
layer: t("Seller.myOrders"),
|
||||||
path: "/home/seller/myOrders"
|
path: "/home/seller/myOrders"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "seller-settings",
|
icon: "seller-settings",
|
||||||
layer: "Settings",
|
layer: t("Seller.settings"),
|
||||||
path: "/home/seller/settings"
|
path: "/home/seller/settings"
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@@ -57,8 +71,8 @@
|
|||||||
if (path === activePath.value) return
|
if (path === activePath.value) return
|
||||||
router.push(path)
|
router.push(path)
|
||||||
}
|
}
|
||||||
onMounted(()=>{
|
onMounted(() => {
|
||||||
myEvent.add('newListing',(path)=>{
|
myEvent.add("newListing", (path) => {
|
||||||
toolTipBoxRef.value.routerPath = path
|
toolTipBoxRef.value.routerPath = path
|
||||||
visible.value = true
|
visible.value = true
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,27 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="seller-header">
|
<div class="seller-header">
|
||||||
<div class="back" @click="() => router.back()">
|
<div class="back" v-if="displayBack" @click="() => router.back()">
|
||||||
<svg-icon name="seller-back" size="24" />
|
<svg-icon name="seller-back" size="24" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<span class="title" v-show="title">{{ title }}</span>
|
<span class="title" v-show="displayTitle">{{ displayTitle }}</span>
|
||||||
<span class="tip" v-show="tip">{{ tip }}</span>
|
<span class="tip" v-show="displayTip">{{ displayTip }}</span>
|
||||||
<div class="breadcrumbs" v-show="breadcrumbs.length > 0">
|
<div class="breadcrumbs" v-show="breadcrumbList.length > 1">
|
||||||
<template v-for="(v, i) in breadcrumbs" :key="i">
|
<template v-for="(v, i) in breadcrumbList" :key="`${v.title}-${i}`">
|
||||||
<span
|
<span
|
||||||
class="title"
|
class="title"
|
||||||
:class="{
|
:class="{
|
||||||
last: i === breadcrumbs.length - 1
|
last: i === breadcrumbList.length - 1,
|
||||||
|
clickable: i < breadcrumbList.length - 1
|
||||||
}"
|
}"
|
||||||
@click="
|
@click="onBreadcrumbClick(v, i)"
|
||||||
() => {
|
>{{ $t(v.title) }}</span
|
||||||
const index = -(breadcrumbs.length - i - 1)
|
|
||||||
if (index < 0) router.go(index)
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>{{ v.title }}</span
|
|
||||||
>
|
>
|
||||||
<span class="icon" v-show="i < breadcrumbs.length - 1">
|
<span class="icon" v-show="i < breadcrumbList.length - 1">
|
||||||
<svg-icon name="seller-arrow_right_solid" size="10" />
|
<svg-icon name="seller-arrow_right_solid" size="10" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -33,25 +29,177 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import { ref, computed } from "vue"
|
import { computed } from "vue"
|
||||||
|
import { useI18n } from "vue-i18n"
|
||||||
import { useRoute, useRouter } from "vue-router"
|
import { useRoute, useRouter } from "vue-router"
|
||||||
const props = defineProps({
|
import type { RouteLocationNormalizedLoaded, RouteLocationRaw } from "vue-router"
|
||||||
title: {
|
|
||||||
type: String,
|
type RouteMetaValue<T> = T | ((route: RouteLocationNormalizedLoaded) => T)
|
||||||
default: ""
|
type SellerBreadcrumbSource =
|
||||||
},
|
| string
|
||||||
tip: {
|
| {
|
||||||
type: String,
|
title?: RouteMetaValue<string>
|
||||||
default: ""
|
titleKey?: RouteMetaValue<string>
|
||||||
},
|
to?: RouteMetaValue<RouteLocationRaw | undefined>
|
||||||
breadcrumbs: {
|
name?: string
|
||||||
type: Array, // { title: string, name: string }
|
path?: string
|
||||||
default: () => []
|
|
||||||
}
|
}
|
||||||
})
|
type SellerBreadcrumbItem = {
|
||||||
|
title: string
|
||||||
|
to?: RouteLocationRaw
|
||||||
|
}
|
||||||
|
type SellerBreadcrumbsSource = RouteMetaValue<SellerBreadcrumbSource[]>
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
title?: string
|
||||||
|
tip?: string
|
||||||
|
displayBack?: boolean
|
||||||
|
breadcrumbs?: SellerBreadcrumbSource[]
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
tip: "",
|
||||||
|
breadcrumbs: () => [],
|
||||||
|
displayBack: true
|
||||||
|
}
|
||||||
|
|
||||||
|
)
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const resolveMetaValue = <T,>(value?: RouteMetaValue<T>) => {
|
||||||
|
if (typeof value === "function") {
|
||||||
|
return (value as (route: RouteLocationNormalizedLoaded) => T)(route)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveRouteLocation = (to?: RouteLocationRaw) => {
|
||||||
|
if (!to || typeof to === "string") return to
|
||||||
|
const location = to as any
|
||||||
|
if (location.name) {
|
||||||
|
return {
|
||||||
|
...location,
|
||||||
|
params: {
|
||||||
|
...route.params,
|
||||||
|
...location.params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveBreadcrumb = (source: SellerBreadcrumbSource) => {
|
||||||
|
if (typeof source === "string") {
|
||||||
|
return {
|
||||||
|
title: source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const titleKey = resolveMetaValue(source.titleKey)
|
||||||
|
const title = titleKey ? t(titleKey) : resolveMetaValue(source.title)
|
||||||
|
const to = resolveRouteLocation(resolveMetaValue(source.to))
|
||||||
|
const fallbackTo = source.name ? { name: source.name } : source.path
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: title || "",
|
||||||
|
to: resolveRouteLocation(to || fallbackTo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveTitle = (title?: RouteMetaValue<string>, titleKey?: RouteMetaValue<string>) => {
|
||||||
|
let key = title || titleKey
|
||||||
|
// const key = resolveMetaValue(titleKey)
|
||||||
|
return key ? t(key) || "" : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoBreadcrumbs = computed(() => {
|
||||||
|
const currentRecord = route.matched[route.matched.length - 1]
|
||||||
|
const customBreadcrumbs = resolveMetaValue(
|
||||||
|
currentRecord?.meta?.sellerBreadcrumbs as SellerBreadcrumbsSource | undefined
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Array.isArray(customBreadcrumbs)) {
|
||||||
|
return customBreadcrumbs
|
||||||
|
.map((breadcrumb) => resolveBreadcrumb(breadcrumb as SellerBreadcrumbSource))
|
||||||
|
.filter((breadcrumb) => breadcrumb.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
return route.matched
|
||||||
|
.map((record) => record.meta?.sellerBreadcrumb)
|
||||||
|
.filter(
|
||||||
|
(breadcrumb): breadcrumb is SellerBreadcrumbSource =>
|
||||||
|
typeof breadcrumb === "string" ||
|
||||||
|
(typeof breadcrumb === "object" && breadcrumb !== null)
|
||||||
|
)
|
||||||
|
.map(resolveBreadcrumb)
|
||||||
|
.filter((breadcrumb) => breadcrumb.title)
|
||||||
|
})
|
||||||
|
|
||||||
|
const breadcrumbList = computed<SellerBreadcrumbItem[]>(() => {
|
||||||
|
if (props.breadcrumbs.length) {
|
||||||
|
return props.breadcrumbs
|
||||||
|
.map(resolveBreadcrumb)
|
||||||
|
.filter((breadcrumb) => breadcrumb.title)
|
||||||
|
}
|
||||||
|
return autoBreadcrumbs.value
|
||||||
|
})
|
||||||
|
|
||||||
|
const displayTitle = computed(() => {
|
||||||
|
return (
|
||||||
|
props.title ||
|
||||||
|
resolveTitle(
|
||||||
|
route.meta.sellerHeaderTitle as RouteMetaValue<string> | undefined,
|
||||||
|
route.meta.sellerHeaderTitleKey as RouteMetaValue<string> | undefined
|
||||||
|
) ||
|
||||||
|
breadcrumbList.value[breadcrumbList.value.length - 1]?.title ||
|
||||||
|
""
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const displayTip = computed(() => {
|
||||||
|
return (
|
||||||
|
props.tip ||
|
||||||
|
resolveTitle(
|
||||||
|
route.meta.sellerHeaderTip as RouteMetaValue<string> | undefined,
|
||||||
|
route.meta.sellerHeaderTipKey as RouteMetaValue<string> | undefined
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const onBreadcrumbClick = (breadcrumb: SellerBreadcrumbItem, index: number) => {
|
||||||
|
if (index >= breadcrumbList.value.length - 1) return
|
||||||
|
|
||||||
|
const historyIndex = -(breadcrumbList.value.length - index - 1)
|
||||||
|
if (canUseBreadcrumbHistory(Math.abs(historyIndex))) {
|
||||||
|
router.go(historyIndex)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (breadcrumb.to) {
|
||||||
|
router.replace(breadcrumb.to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canUseBreadcrumbHistory = (steps: number) => {
|
||||||
|
if (steps <= 0 || typeof history === "undefined") return false
|
||||||
|
|
||||||
|
const state = history.state as {
|
||||||
|
back?: unknown
|
||||||
|
position?: unknown
|
||||||
|
} | null
|
||||||
|
const backPath = state?.back
|
||||||
|
|
||||||
|
return (
|
||||||
|
typeof state?.position === "number" &&
|
||||||
|
state.position >= steps &&
|
||||||
|
typeof backPath === "string" &&
|
||||||
|
backPath.startsWith("/home/seller/myListings")
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.seller-header {
|
.seller-header {
|
||||||
@@ -90,8 +238,8 @@
|
|||||||
font-family: "pingfang_regular";
|
font-family: "pingfang_regular";
|
||||||
color: #999;
|
color: #999;
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
|
&.clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:not(.last) {
|
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,10 +88,10 @@ export default defineConfig(({ mode }) => {
|
|||||||
overlay: true,
|
overlay: true,
|
||||||
},
|
},
|
||||||
proxy: {
|
proxy: {
|
||||||
"/api": {
|
"/aida": {
|
||||||
// target: 'https://develop.api.aida.com.hk',
|
// target: 'https://develop.api.aida.com.hk',
|
||||||
target: baseURL,
|
target: baseURL,
|
||||||
rewrite: (path) => path.replace(/^\/api/, "/aida/api"),
|
rewrite: (path) => path.replace(/^\/aida/, "/aida"),
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
"/seller": {
|
"/seller": {
|
||||||
|
|||||||
Reference in New Issue
Block a user