Merge branch 'main' of http://18.167.251.121:10003/aidlab/lanecarford_front
All checks were successful
git提交控制 AiDA WEB-Node.js main 分支构建部署 / build (20.19.0) (push) Has been skipped
All checks were successful
git提交控制 AiDA WEB-Node.js main 分支构建部署 / build (20.19.0) (push) Has been skipped
This commit is contained in:
@@ -8,26 +8,26 @@ import request from '@/utils/request'
|
|||||||
* @param data.stylist 提示词
|
* @param data.stylist 提示词
|
||||||
* @param data.gender 原始试穿效果id
|
* @param data.gender 原始试穿效果id
|
||||||
* @param data.num 是否重新生成 0-否,1-是
|
* @param data.num 是否重新生成 0-否,1-是
|
||||||
*/
|
*/
|
||||||
export function generateRequestOutfit(data: Object) {
|
export function generateRequestOutfit(data: Object) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/style/requestOutfit',
|
url: '/api/style/requestOutfit',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取传达风格
|
* 获取传达风格
|
||||||
* @param data 获取传达风格数据
|
* @param data 获取传达风格数据
|
||||||
* @param data.requestIDs 获取生成结果的taskId
|
* @param data.requestIDs 获取生成结果的taskId
|
||||||
*/
|
*/
|
||||||
export function getRequestOutfit(data: Object) {
|
export function getRequestOutfit(data: Object) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/style/getOutfitResult',
|
url: '/api/style/getOutfitResult',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params:data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,13 +41,13 @@ export function getRequestOutfit(data: Object) {
|
|||||||
* @param data.prompt 提示词
|
* @param data.prompt 提示词
|
||||||
* @param data.originalTryOnId 原始试穿效果id
|
* @param data.originalTryOnId 原始试穿效果id
|
||||||
* @param data.isRegenerated 是否重新生成 0-否,1-是
|
* @param data.isRegenerated 是否重新生成 0-否,1-是
|
||||||
*/
|
*/
|
||||||
export function generateTryOnEffect(data: Object) {
|
export function generateTryOnEffect(data: Object) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/try-on-effects/generate',
|
url: '/api/try-on-effects/generate',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 生成试穿效果-演示
|
* 生成试穿效果-演示
|
||||||
@@ -55,13 +55,13 @@ export function generateTryOnEffect(data: Object) {
|
|||||||
* @param data.customerPhotoId 顾客照片id
|
* @param data.customerPhotoId 顾客照片id
|
||||||
* @param data.prompt 提示词
|
* @param data.prompt 提示词
|
||||||
* @param data.tryonUrl AI魔改url
|
* @param data.tryonUrl AI魔改url
|
||||||
*/
|
*/
|
||||||
export function generateTryOnEffectDemo(data: Object) {
|
export function generateTryOnEffectDemo(data: Object) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/try-on-effects/reFace',
|
url: '/api/try-on-effects/reFace',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 上传图片-AI换脸
|
/** 上传图片-AI换脸
|
||||||
@@ -71,56 +71,111 @@ export function generateTryOnEffectDemo(data: Object) {
|
|||||||
* @param data.file 顾客照片文件
|
* @param data.file 顾客照片文件
|
||||||
*/
|
*/
|
||||||
export function uploadCustomerPhoto(data: FormData) {
|
export function uploadCustomerPhoto(data: FormData) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/customer-photos/upload',
|
url: '/api/customer-photos/upload',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
loading: true,
|
loading: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 设置喜欢
|
* 设置喜欢
|
||||||
* @param tryOnId 试穿效果id
|
* @param tryOnId 试穿效果id
|
||||||
*/
|
*/
|
||||||
export function setTryOnEffectFavorite(tryOnId: string | number) {
|
export function setTryOnEffectFavorite(tryOnId: string | number) {
|
||||||
if (!tryOnId) return Promise.reject('试穿效果id不能为空');
|
if (!tryOnId) return Promise.reject('试穿效果id不能为空')
|
||||||
return request({
|
return request({
|
||||||
url: `/api/try-on-effects/set-favorite/${tryOnId}`,
|
url: `/api/try-on-effects/set-favorite/${tryOnId}`,
|
||||||
method: 'post',
|
method: 'post'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 取消喜欢
|
* 取消喜欢
|
||||||
* @param tryOnId 试穿效果id
|
* @param tryOnId 试穿效果id
|
||||||
*/
|
*/
|
||||||
export function cancelTryOnEffectFavorite(tryOnId: string | number) {
|
export function cancelTryOnEffectFavorite(tryOnId: string | number) {
|
||||||
if (!tryOnId) return Promise.reject('试穿效果id不能为空');
|
if (!tryOnId) return Promise.reject('试穿效果id不能为空')
|
||||||
return request({
|
return request({
|
||||||
url: `/api/try-on-effects/cancel-favorite/${tryOnId}`,
|
url: `/api/try-on-effects/cancel-favorite/${tryOnId}`,
|
||||||
method: 'post',
|
method: 'post'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询进店记录-library
|
/** 查询进店记录-library
|
||||||
* @param customerId 客户id
|
* @param customerId 客户id
|
||||||
*/
|
*/
|
||||||
export function getCustomerPhotos(customerId: string | number) {
|
export function getCustomerPhotos(customerId: string | number) {
|
||||||
if (!customerId) return Promise.reject('客户id不能为空');
|
if (!customerId) return Promise.reject('客户id不能为空')
|
||||||
return request({
|
return request({
|
||||||
url: `/api/visit-records/customer/${customerId}`,
|
url: `/api/visit-records/customer/${customerId}`,
|
||||||
method: 'get',
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/** 删除进店记录-library
|
/** 删除进店记录-library
|
||||||
* @param visitRecordId 进店记录id
|
* @param visitRecordId 进店记录id
|
||||||
*/
|
*/
|
||||||
export function deleteCustomerPhoto(visitRecordId: string | number) {
|
export function deleteCustomerPhoto(visitRecordId: string | number) {
|
||||||
if (!visitRecordId) return Promise.reject('进店记录id不能为空');
|
if (!visitRecordId) return Promise.reject('进店记录id不能为空')
|
||||||
|
return request({
|
||||||
|
url: `/api/visit-records/${visitRecordId}`,
|
||||||
|
method: 'delete'
|
||||||
|
// loading: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/** 查询收藏列表
|
||||||
|
* @param visitRecordId 进店记录id
|
||||||
|
*/
|
||||||
|
export function getTryOnEffectFavoriteList(visitRecordId: string | number) {
|
||||||
|
if (!visitRecordId) return Promise.reject('进店记录id不能为空')
|
||||||
|
return request({
|
||||||
|
url: `/api/try-on-effects/favorites/${visitRecordId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/** 查询某套试穿效果列表
|
||||||
|
* @param styleId 服装id
|
||||||
|
*/
|
||||||
|
export function getTryOnEffectStyleList(styleId: string | number) {
|
||||||
|
if (!styleId) return Promise.reject('服装id不能为空')
|
||||||
|
return request({
|
||||||
|
url: `/api/try-on-effects/style/${styleId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前Sales名下的customers列表
|
||||||
|
export interface CustomerListParams {
|
||||||
|
current: number
|
||||||
|
size: number
|
||||||
|
desc: boolean
|
||||||
|
sortField?: 'createTime'
|
||||||
|
sortOrder?: 'DESC' | 'ASC'
|
||||||
|
keyword?: string
|
||||||
|
startTime?: string
|
||||||
|
endTime?: string
|
||||||
|
status?: number
|
||||||
|
offset?: number
|
||||||
|
limit?: number
|
||||||
|
}
|
||||||
|
export const getCustomerList = (data: CustomerListParams) => {
|
||||||
|
return request({
|
||||||
|
url: '/api/customers/getAllCustomer',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建顾客
|
||||||
|
export interface CreateCustomerParams {
|
||||||
|
nickname: string
|
||||||
|
vipId: string
|
||||||
|
}
|
||||||
|
export const createCustomer = (data: CreateCustomerParams) => {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/visit-records/${visitRecordId}`,
|
url: '/api/customers/createCustomer',
|
||||||
method: 'delete',
|
method: 'get',
|
||||||
// loading: true,
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// /** 查询收藏列表
|
// /** 查询收藏列表
|
||||||
@@ -162,19 +217,19 @@ export function getGenerateHistoricals(params: Object) {
|
|||||||
interface CustomerInfo {
|
interface CustomerInfo {
|
||||||
vipId: string
|
vipId: string
|
||||||
}
|
}
|
||||||
export const customerCheckin = (data: CustomerInfo) => {
|
export const customerCheckin = (data: CustomerInfo) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/customers/checkIn',
|
url: '/api/customers/checkIn',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data,
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// AI对话
|
// AI对话
|
||||||
interface AIConversation {
|
interface AIConversation {
|
||||||
message: string
|
message: string
|
||||||
sessionId: string | number //用户ID
|
sessionId: string | number //用户ID
|
||||||
gender: 'male' | 'female' //性别
|
gender: 'male' | 'female' //性别
|
||||||
}
|
}
|
||||||
export const streamChatAddress = '/api/llm/streamChat'
|
export const streamChatAddress = '/api/llm/streamChat'
|
||||||
|
|
||||||
@@ -185,11 +240,46 @@ export const streamChatAddress = '/api/llm/streamChat'
|
|||||||
* @param data.visitRecordId 进店记录id
|
* @param data.visitRecordId 进店记录id
|
||||||
* @param data.customerId 顾客id
|
* @param data.customerId 顾客id
|
||||||
* @param data.suggestion 意见和建议
|
* @param data.suggestion 意见和建议
|
||||||
*/
|
*/
|
||||||
export function addTryOnEffectComment(data: Object) {
|
export function addTryOnEffectComment(data: Object) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/try-on-effects/add-comment',
|
url: '/api/try-on-effects/add-comment',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* like outfit接口
|
||||||
|
* @param styleId 设置like的styleid
|
||||||
|
*/
|
||||||
|
export function setStyleFavorite(styleId: Object) {
|
||||||
|
return request({
|
||||||
|
url: `/api/style/set-favorite/${styleId}`,
|
||||||
|
method: 'post',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消like outfit接口
|
||||||
|
* @param styleId 取消like的styleid
|
||||||
|
*/
|
||||||
|
export function cancelStyleFavorite(styleId: Object) {
|
||||||
|
return request({
|
||||||
|
url: `/api/style/cancel-favorite/${styleId}`,
|
||||||
|
method: 'post',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* try on 返推outfitId
|
||||||
|
* @param tryOnEffectsId tryOnId
|
||||||
|
*/
|
||||||
|
export function retrieveAndRegenerate(data: Object) {
|
||||||
|
return request({
|
||||||
|
url: `/api/style/retrieveAndRegenerate`,
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
9
src/assets/icons/reTry.svg
Normal file
9
src/assets/icons/reTry.svg
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<rect width="44" height="44" fill="url(#pattern0_27_31213)"/>
|
||||||
|
<defs>
|
||||||
|
<pattern id="pattern0_27_31213" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||||
|
<use xlink:href="#image0_27_31213" transform="scale(0.0078125)"/>
|
||||||
|
</pattern>
|
||||||
|
<image id="image0_27_31213" width="128" height="128" preserveAspectRatio="none" xlink:href="data:image/png;base64,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"/>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -25,13 +25,13 @@
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
MyEvent.emit('clear-generate-state')
|
MyEvent.emit('clear-generate-state')
|
||||||
MyEvent.emit('clearAllCache')
|
// MyEvent.emit('clearAllCache')
|
||||||
nav.path && router.push(nav.path)
|
nav.path && router.push(nav.path)
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
const navs = [
|
const navs = [
|
||||||
{ label: 'Home', icon: 'home', size: 73, path: '/workshop/home' },
|
{ label: 'Home', icon: 'home', size: 73, path: '/workshop/home', on: onHome },
|
||||||
{ label: 'Library', icon: 'library', size: 53, path: '/workshop/library' },
|
{ label: 'Library', icon: 'library', size: 53, path: '/workshop/library' },
|
||||||
// { label: 'Profile', icon: 'profile', size: 55, path: '/workshop/profile' }
|
// { label: 'Profile', icon: 'profile', size: 55, path: '/workshop/profile' }
|
||||||
]
|
]
|
||||||
|
|||||||
58
src/components/gradientButton.vue
Normal file
58
src/components/gradientButton.vue
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||||
|
//const props = defineProps({
|
||||||
|
//})
|
||||||
|
//const emit = defineEmits([
|
||||||
|
//])
|
||||||
|
let data = reactive({
|
||||||
|
})
|
||||||
|
onMounted(()=>{
|
||||||
|
})
|
||||||
|
onUnmounted(()=>{
|
||||||
|
})
|
||||||
|
defineExpose({})
|
||||||
|
const {} = toRefs(data);
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="gradientButton">
|
||||||
|
<div class="bg">
|
||||||
|
<slot name="content">
|
||||||
|
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.gradientButton{
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
--gradientButtonBorderRadius: var(--borderRadius,1rem);
|
||||||
|
--gradientButtonBorderWidth: var(--borderWidth,2px);
|
||||||
|
> .bg{
|
||||||
|
position: absolute;
|
||||||
|
inset: var(--gradientButtonBorderWidth);
|
||||||
|
display: flex;
|
||||||
|
background-color: #fff;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: var(--gradientButtonBorderRadius);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
&::before{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% + 0.2rem);
|
||||||
|
height: calc(100% + 0.2rem);
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
border-radius: var(--gradientButtonBorderRadius);
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: linear-gradient(125deg,
|
||||||
|
#f1f1f1 0%,
|
||||||
|
#000 40%,
|
||||||
|
#000 65%,
|
||||||
|
#fff 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -121,7 +121,7 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/workshop/selectStyle',
|
path: '/workshop/selectStyle',
|
||||||
name: 'SelectStyle',
|
name: 'selectStyle',
|
||||||
component: () => import('../views/Workshop/selectStyle.vue'),
|
component: () => import('../views/Workshop/selectStyle.vue'),
|
||||||
meta: { verify: ()=> VerifyIDs(2) }
|
meta: { verify: ()=> VerifyIDs(2) }
|
||||||
},
|
},
|
||||||
@@ -133,7 +133,7 @@ const router = createRouter({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/workshop/product',
|
path: '/workshop/product',
|
||||||
name: 'Product',
|
name: 'product',
|
||||||
component: () => import('../views/Workshop/product.vue'),
|
component: () => import('../views/Workshop/product.vue'),
|
||||||
meta: { verify: ()=> VerifyIDs(4) }
|
meta: { verify: ()=> VerifyIDs(4) }
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ export const useGenerateStore = defineStore({
|
|||||||
return {
|
return {
|
||||||
style: {
|
style: {
|
||||||
id: '',
|
id: '',
|
||||||
oldId: '' //表示从生成页面返回回来,需要调整的样式id
|
path: '',
|
||||||
|
taskId:'',
|
||||||
|
isLike: false, //是否喜欢
|
||||||
|
status: ''
|
||||||
},
|
},
|
||||||
styleList: [{}, {}, {}, {}],
|
styleList: [{}, {}, {}, {}],
|
||||||
model: {
|
model: {
|
||||||
@@ -68,7 +71,7 @@ export const useGenerateStore = defineStore({
|
|||||||
/** 进店记录id */
|
/** 进店记录id */
|
||||||
visitRecordId: (state) => state.customerInfo.visitRecordId,
|
visitRecordId: (state) => state.customerInfo.visitRecordId,
|
||||||
/** 服装id */
|
/** 服装id */
|
||||||
styleId: (state) => state.style.id || state.style.oldId,
|
styleId: (state) => state.style.id,
|
||||||
/** 模特照片id */
|
/** 模特照片id */
|
||||||
modelPhotoId: (state) => state.model.id,
|
modelPhotoId: (state) => state.model.id,
|
||||||
/** 原始试穿id不包含魔改id */
|
/** 原始试穿id不包含魔改id */
|
||||||
@@ -82,23 +85,19 @@ export const useGenerateStore = defineStore({
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
selectStyle(data: any) {
|
selectStyle(data: any) {
|
||||||
this.style.id = data.id
|
this.style = {
|
||||||
},
|
...data,
|
||||||
//生成后去掉id 设置oldId来修改样式
|
|
||||||
useStyleGenerate() {
|
|
||||||
if (!this.style.id) return
|
|
||||||
this.style.oldId = this.style.id
|
|
||||||
// this.style.id = ''
|
|
||||||
},
|
|
||||||
updateStyle(data) {
|
|
||||||
if (data.id == this.style.oldId) {
|
|
||||||
this.style.oldId = ''
|
|
||||||
}
|
|
||||||
if(data.id == this.style.id) {
|
|
||||||
this.style.id = ''
|
|
||||||
}
|
}
|
||||||
console.log(this.style)
|
|
||||||
},
|
},
|
||||||
|
clearStyle() {
|
||||||
|
this.style = {
|
||||||
|
id: '',
|
||||||
|
path: '',
|
||||||
|
isLike: false,
|
||||||
|
taskId:'',
|
||||||
|
status: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
//模特相关
|
//模特相关
|
||||||
selectModel(data: any) {
|
selectModel(data: any) {
|
||||||
this.model.id = data.id
|
this.model.id = data.id
|
||||||
@@ -110,7 +109,10 @@ export const useGenerateStore = defineStore({
|
|||||||
this.styleList = [{}, {}, {}, {}]
|
this.styleList = [{}, {}, {}, {}]
|
||||||
this.style = {
|
this.style = {
|
||||||
id: '',
|
id: '',
|
||||||
oldId: ''
|
path: '',
|
||||||
|
isLike: false,
|
||||||
|
taskId:'',
|
||||||
|
status: ''
|
||||||
}
|
}
|
||||||
this.model = {
|
this.model = {
|
||||||
id: ''
|
id: ''
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class MyEvent {
|
|||||||
MyEvent.list = MyEvent.list.filter(item => item.name != name && item.call != call)
|
MyEvent.list = MyEvent.list.filter(item => item.name != name && item.call != call)
|
||||||
}
|
}
|
||||||
emit(name, data) {
|
emit(name, data) {
|
||||||
|
console.log('Myevent触发--',name)
|
||||||
MyEvent.list.forEach(item => {
|
MyEvent.list.forEach(item => {
|
||||||
if (item.name == name) item.call(data)
|
if (item.name == name) item.call(data)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ service.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
const res = response.data
|
const res = response.data
|
||||||
// 处理异常的情况
|
// 处理异常的情况
|
||||||
console.log(res)
|
// console.log(res)
|
||||||
if (res.code != 0) {
|
if (res.code != 0) {
|
||||||
showToast({
|
showToast({
|
||||||
message: res.errMsg || res.message,
|
message: res.errMsg || res.message,
|
||||||
|
|||||||
@@ -156,4 +156,31 @@ export async function DownloadImages(list: Array<{ url: string, name?: string }>
|
|||||||
*/
|
*/
|
||||||
export function encryptPassword(password: string): string {
|
export function encryptPassword(password: string): string {
|
||||||
return CryptoJS.MD5(password).toString()
|
return CryptoJS.MD5(password).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片分享到WhatsApp
|
||||||
|
* @param url 图片URL
|
||||||
|
* @returns 无
|
||||||
|
*/
|
||||||
|
export async function shareImageToWhatsapp (url: string){
|
||||||
|
// 把图片 URL 转为 Blob
|
||||||
|
const blob = await fetch(url).then((res) => res.blob())
|
||||||
|
|
||||||
|
// 创建文件对象
|
||||||
|
const file = new File([blob], 'image.jpg', { type: 'image/jpeg' })
|
||||||
|
|
||||||
|
// 判断浏览器是否支持文件分享
|
||||||
|
if (navigator.canShare && navigator.canShare({ files: [file] })) {
|
||||||
|
await navigator.share({
|
||||||
|
files: [file]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 你可以附加一些自定义文本
|
||||||
|
const message = 'share image ' + url
|
||||||
|
|
||||||
|
// 构造WhatsApp链接
|
||||||
|
const whatsappLink = `https://api.whatsapp.com/send/?text=${encodeURIComponent(message)}`
|
||||||
|
window.open(whatsappLink, '_blank')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ import { FlowType } from '@/types/enum'
|
|||||||
//const props = defineProps({
|
//const props = defineProps({
|
||||||
//})
|
//})
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
'view-type'
|
'viewType'
|
||||||
])
|
])
|
||||||
|
|
||||||
// const data = reactive({
|
// const data = reactive({
|
||||||
@@ -23,7 +23,7 @@ const historicalReview = ()=>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
emit('view-type', 1)
|
emit('viewType', 1)
|
||||||
})
|
})
|
||||||
onUnmounted(()=>{
|
onUnmounted(()=>{
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ onMounted(()=>{
|
|||||||
flowTypeList: [FlowType.H_TRYON,FlowType.H_AI],
|
flowTypeList: [FlowType.H_TRYON,FlowType.H_AI],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'recommended',
|
path: 'product',
|
||||||
imgPath: new URL('@/assets/images/nav2.png',import.meta.url).href,
|
imgPath: new URL('@/assets/images/nav2.png',import.meta.url).href,
|
||||||
flowTypeList: [FlowType.H_OUTFIT],
|
flowTypeList: [FlowType.H_OUTFIT],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted, reactive, ref, toRefs } from "vue";
|
import { onMounted, onUnmounted, reactive, ref, toRefs, computed } from "vue";
|
||||||
import HeaderTitle from '@/components/HeaderTitle.vue'
|
|
||||||
import FooterNavigation from '@/components/FooterNavigation.vue'
|
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import GenerateLoading from '@/views/asistant/components/GenerateLoading.vue'
|
import GenerateLoading from '@/views/asistant/components/GenerateLoading.vue'
|
||||||
import { useGenerateStore } from '@/stores'
|
import { useGenerateStore, useHGenerateStore } from '@/stores'
|
||||||
import { generateTryOnEffect, setTryOnEffectFavorite, cancelTryOnEffectFavorite, addTryOnEffectComment } from '@/api/workshop'
|
import { generateTryOnEffect, setTryOnEffectFavorite, cancelTryOnEffectFavorite, addTryOnEffectComment } from '@/api/workshop'
|
||||||
import { FlowType } from '@/types/enum'
|
import { FlowType, IsHistoryFlow } from '@/types/enum'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
//const props = defineProps({
|
//const props = defineProps({
|
||||||
@@ -19,8 +17,11 @@ let data = reactive({
|
|||||||
],
|
],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
})
|
})
|
||||||
|
const query = computed(() => router.currentRoute.value.query)
|
||||||
const generateStore = useGenerateStore()
|
const generateStore = useGenerateStore()
|
||||||
|
const hGenerateStore = useHGenerateStore()
|
||||||
|
|
||||||
|
const isHistoryFlow = computed(() => IsHistoryFlow(query.value.flowType))
|
||||||
|
|
||||||
const vanDialogShow = ref(false)
|
const vanDialogShow = ref(false)
|
||||||
const feedbackForm = ref({
|
const feedbackForm = ref({
|
||||||
@@ -34,11 +35,10 @@ const feedbackForm = ref({
|
|||||||
|
|
||||||
|
|
||||||
const onContinue = ()=>{
|
const onContinue = ()=>{
|
||||||
const query = router.currentRoute.value.query
|
if(!isHistoryFlow.value){
|
||||||
if(query?.flowType == FlowType.MAIN || !query?.flowType){
|
router.push({ path: 'uploadFace', query: {...query.value} })
|
||||||
router.push({ path: 'uploadFace', query: {...query} })
|
|
||||||
}else{
|
}else{
|
||||||
router.push({ path: 'creation', query: {...query} })
|
router.push({ path: 'creation', query: {...query.value} })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ const startGenerate = ()=>{
|
|||||||
let value = {
|
let value = {
|
||||||
customerId:generateStore.customerId,
|
customerId:generateStore.customerId,
|
||||||
visitRecordId:generateStore.visitRecordId,
|
visitRecordId:generateStore.visitRecordId,
|
||||||
styleId:generateStore.styleId,
|
styleId:isHistoryFlow.value ? hGenerateStore.styleId : generateStore.styleId,
|
||||||
// customerPhotoId:null,
|
// customerPhotoId:null,
|
||||||
// modelPhotoId:null,
|
// modelPhotoId:null,
|
||||||
// prompt:null,
|
// prompt:null,
|
||||||
@@ -63,7 +63,7 @@ const startGenerate = ()=>{
|
|||||||
generateStore.originalTryOn.isLike = false
|
generateStore.originalTryOn.isLike = false
|
||||||
generateStore.originalTryOn.id = res.id
|
generateStore.originalTryOn.id = res.id
|
||||||
generateStore.originalTryOn.tryOnUrl = res.tryOnUrl
|
generateStore.originalTryOn.tryOnUrl = res.tryOnUrl
|
||||||
generateStore.useStyleGenerate()//生成后需要对选择衣服页面设置不可选中样式
|
// generateStore.useStyleGenerate()//生成后需要对选择衣服页面设置不可选中样式
|
||||||
generateStore.setIsGenerate(false)
|
generateStore.setIsGenerate(false)
|
||||||
|
|
||||||
generateStore.clearCustomizeInfo()
|
generateStore.clearCustomizeInfo()
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import router from '@/router'
|
|||||||
import { showConfirmDialog } from 'vant'
|
import { showConfirmDialog } from 'vant'
|
||||||
import { useUserInfoStore, useOverallStore } from '@/stores'
|
import { useUserInfoStore, useOverallStore } from '@/stores'
|
||||||
import { LogOut } from '@/api/login'
|
import { LogOut } from '@/api/login'
|
||||||
|
import { getCustomerList, type CustomerListParams,customerCheckin } from '@/api/workshop'
|
||||||
|
import MyEvent from '@/utils/myEvent'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
isCustomer?: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
const userInfoStore = useUserInfoStore()
|
const userInfoStore = useUserInfoStore()
|
||||||
const overallStore = useOverallStore()
|
const overallStore = useOverallStore()
|
||||||
const emit = defineEmits(['view-type', 'selected-customer'])
|
const emit = defineEmits(['view-type', 'selected-customer'])
|
||||||
@@ -60,22 +67,84 @@ const logout = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showSwitchCustomerPopup = ref(false)
|
const showSwitchCustomerPopup = ref(false)
|
||||||
|
const custmerParams = ref<CustomerListParams>({
|
||||||
|
current: 1,
|
||||||
|
size: 5,
|
||||||
|
desc: true
|
||||||
|
})
|
||||||
|
const customerList = ref<any[]>([])
|
||||||
|
const pager = reactive({
|
||||||
|
loading: false,
|
||||||
|
noMore: false,
|
||||||
|
total: null as number | null
|
||||||
|
})
|
||||||
|
const customerListEl = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
const customerList = ref([
|
const loadCustomers = async (reset = false) => {
|
||||||
{ id: 'CUST001', nickname: 'Customer One', checked: true },
|
if (pager.loading) return
|
||||||
{ id: 'CUST002', nickname: 'Customer Two', checked: false },
|
if (reset) {
|
||||||
{ id: 'CUST003', nickname: 'Customer Three', checked: false },
|
custmerParams.value.current = 1
|
||||||
{ id: 'CUST004', nickname: 'Customer Four', checked: false },
|
pager.noMore = false
|
||||||
{ id: 'CUST005', nickname: 'Customer Five', checked: false }
|
customerList.value = []
|
||||||
])
|
}
|
||||||
|
if (pager.noMore) return
|
||||||
|
pager.loading = true
|
||||||
|
try {
|
||||||
|
const res: any = await getCustomerList(custmerParams.value)
|
||||||
|
let list: any[] = []
|
||||||
|
const pages = res?.pages ?? res?.data?.pages ?? null
|
||||||
|
if (res && Array.isArray(res.records)) {
|
||||||
|
list = res.records
|
||||||
|
pager.total = res.total ?? pager.total
|
||||||
|
} else if (res && Array.isArray(res.data)) {
|
||||||
|
list = res.data
|
||||||
|
} else if (res && res.data && Array.isArray(res.data.list)) {
|
||||||
|
list = res.data.list
|
||||||
|
pager.total = res.data.total ?? pager.total
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reset) customerList.value = list
|
||||||
|
else customerList.value = customerList.value.concat(list)
|
||||||
|
|
||||||
|
if (pages != null) {
|
||||||
|
if (custmerParams.value.current >= pages) {
|
||||||
|
pager.noMore = true
|
||||||
|
} else {
|
||||||
|
custmerParams.value.current += 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (list.length === 0 || list.length < custmerParams.value.size) {
|
||||||
|
pager.noMore = true
|
||||||
|
} else {
|
||||||
|
custmerParams.value.current += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// ignore error for now
|
||||||
|
} finally {
|
||||||
|
pager.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onScroll = (e: Event) => {
|
||||||
|
const el = e.target as HTMLElement
|
||||||
|
if (!el) return
|
||||||
|
if (pager.loading || pager.noMore) return
|
||||||
|
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 50) {
|
||||||
|
loadCustomers(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
// 打开customer选择时关闭profile弹窗 如果不是点击confirem关闭则重新打开profile弹窗
|
// 打开customer选择时关闭profile弹窗 如果不是点击confirem关闭则重新打开profile弹窗
|
||||||
const handleShowPopup = (flag: boolean) => {
|
const handleShowPopup = (flag: boolean) => {
|
||||||
showSwitchCustomerPopup.value = flag
|
showSwitchCustomerPopup.value = flag
|
||||||
show.value = !flag
|
show.value = !flag
|
||||||
|
if (flag) {
|
||||||
|
loadCustomers(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const handleChangeChecked = (item) => {
|
const handleChangeChecked = (item) => {
|
||||||
customerList.value.forEach((customer) => {
|
customerList.value.forEach((customer) => {
|
||||||
customer.checked = customer.id === item.id
|
customer.checked = customer.vipId === item.vipId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleSelectCustomer = () => {
|
const handleSelectCustomer = () => {
|
||||||
@@ -83,13 +152,30 @@ const handleSelectCustomer = () => {
|
|||||||
if (selectedCustomer) {
|
if (selectedCustomer) {
|
||||||
emit('selected-customer', selectedCustomer)
|
emit('selected-customer', selectedCustomer)
|
||||||
}
|
}
|
||||||
|
if(!props.isCustomer){
|
||||||
|
// show.value = true
|
||||||
|
customerCheckin({ nickname: selectedCustomer.name }).then((res) => {
|
||||||
|
useUserInfoStore().resetGenerateParams()
|
||||||
|
MyEvent.emit('clear-generate-state')
|
||||||
|
useUserInfoStore().setCustomerInfo(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
showSwitchCustomerPopup.value = false
|
showSwitchCustomerPopup.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleFetchCustomerList = () => {
|
||||||
|
loadCustomers(true)
|
||||||
|
}
|
||||||
|
MyEvent.add('update-customer-list', handleFetchCustomerList)
|
||||||
|
|
||||||
const openSwitchCustomerPopup = (flag = true) => {
|
const openSwitchCustomerPopup = (flag = true) => {
|
||||||
showSwitchCustomerPopup.value = flag
|
showSwitchCustomerPopup.value = flag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
handleFetchCustomerList()
|
||||||
|
})
|
||||||
|
|
||||||
defineExpose({ open, close, openSwitchCustomerPopup })
|
defineExpose({ open, close, openSwitchCustomerPopup })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -185,16 +271,16 @@ defineExpose({ open, close, openSwitchCustomerPopup })
|
|||||||
<div class="title-txt">Saved Customer ID</div>
|
<div class="title-txt">Saved Customer ID</div>
|
||||||
<SvgIcon name="close_nocolor" color="#a1a1a1" size="40" @click="handleShowPopup(false)" />
|
<SvgIcon name="close_nocolor" color="#a1a1a1" size="40" @click="handleShowPopup(false)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="cusomter-list">
|
<div ref="customerListEl" class="cusomter-list" @scroll="onScroll">
|
||||||
<div
|
<div
|
||||||
class="customer-item flex flex-align-center flex-between"
|
class="customer-item flex flex-align-center flex-between"
|
||||||
v-for="item in customerList"
|
v-for="(item, index) in customerList"
|
||||||
:key="item.id"
|
:key="index + 'customer'"
|
||||||
@click="handleChangeChecked(item)"
|
@click="handleChangeChecked(item)"
|
||||||
>
|
>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="name">{{ item.nickname }}</div>
|
<div class="name">{{ item.name }}</div>
|
||||||
<div class="id">{{ item.id }}</div>
|
<div class="id">{{ item.vipId }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="select-box">
|
<div class="select-box">
|
||||||
<div class="check-box flex flex-center" v-show="!item.checked">
|
<div class="check-box flex flex-center" v-show="!item.checked">
|
||||||
@@ -204,6 +290,10 @@ defineExpose({ open, close, openSwitchCustomerPopup })
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="list-footer">
|
||||||
|
<div v-if="pager.loading">Loading...</div>
|
||||||
|
<div v-else-if="pager.noMore">No more</div>
|
||||||
|
</div>
|
||||||
<div class="confirm-btn" @click="handleSelectCustomer">Confirm</div>
|
<div class="confirm-btn" @click="handleSelectCustomer">Confirm</div>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
</template>
|
</template>
|
||||||
@@ -375,6 +465,12 @@ defineExpose({ open, close, openSwitchCustomerPopup })
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.list-footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 2rem 0;
|
||||||
|
font-size: 3rem;
|
||||||
|
color: #9b9b9b;
|
||||||
|
}
|
||||||
.confirm-btn {
|
.confirm-btn {
|
||||||
margin: 4.9rem 12.7rem 0 13.3rem;
|
margin: 4.9rem 12.7rem 0 13.3rem;
|
||||||
border: 0.25rem solid #3b3b3b;
|
border: 0.25rem solid #3b3b3b;
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, onUnmounted, reactive, toRefs, computed, onActivated } from "vue";
|
import { onMounted, onUnmounted, reactive, toRefs, computed, ref } from "vue";
|
||||||
import SelectItem from "@/components/selectStyle/selectItem.vue";
|
import SelectItem from "@/components/selectStyle/selectItem.vue";
|
||||||
import HeaderTitle from '@/components/HeaderTitle.vue'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import FooterNavigation from '@/components/FooterNavigation.vue'
|
import { useGenerateStore, useUserInfoStore, useHGenerateStore } from '@/stores'
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import { useGenerateStore, useUserInfoStore } from '@/stores'
|
|
||||||
import { showToast } from 'vant';
|
import { showToast } from 'vant';
|
||||||
import { generateRequestOutfit, getRequestOutfit } from '@/api/workshop'
|
import { shareImageToWhatsapp } from '@/utils/tools'
|
||||||
import { FlowType } from '@/types/enum'
|
import { generateRequestOutfit, getRequestOutfit, setStyleFavorite, cancelStyleFavorite, retrieveAndRegenerate } from '@/api/workshop'
|
||||||
|
import { FlowType, IsHistoryFlow } from '@/types/enum'
|
||||||
|
import GenerateLoading from '@/views/asistant/components/GenerateLoading.vue'
|
||||||
|
import gradientButton from '@/components/gradientButton.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
//const props = defineProps({
|
//const props = defineProps({
|
||||||
//})
|
//})
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
@@ -18,125 +19,190 @@ const emit = defineEmits([
|
|||||||
])
|
])
|
||||||
const generateStore = useGenerateStore()
|
const generateStore = useGenerateStore()
|
||||||
const userInfoStore = useUserInfoStore()
|
const userInfoStore = useUserInfoStore()
|
||||||
|
const hGenerateStore = useHGenerateStore()
|
||||||
|
|
||||||
|
const query = computed(() => route.query)
|
||||||
|
const isHistoryFlow = computed(() => IsHistoryFlow(query.value.flowType))
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const loadingTitle= ref('Analyzing the Outfit...')
|
||||||
|
// const loadingTitle = computed(()=>{
|
||||||
|
// let str = ''
|
||||||
|
// if(!select.value.status)str = 'Analyzing the Outfit...'
|
||||||
|
// if(select.value.status == 'RUNNING')str = 'Generating Results...'
|
||||||
|
// if(select.value.status == 'PENDING')str = 'Almost there...'
|
||||||
|
// return str
|
||||||
|
// })
|
||||||
|
|
||||||
let data = reactive({
|
let data = reactive({
|
||||||
select:computed(()=>generateStore.style),
|
select:computed(()=>generateStore.style),
|
||||||
styleList:computed(()=>generateStore.styleList),
|
// styleList:computed(()=>generateStore.styleList),
|
||||||
})
|
})
|
||||||
|
|
||||||
let getGenerateTime = null as any
|
let getGenerateTime = null as any
|
||||||
|
|
||||||
const selectItem = (item)=>{
|
const updateStyle = ()=>{
|
||||||
if(!item.id || item.status != 'SUCCEEDED'){
|
// generateStore.updateStyle(item)
|
||||||
return
|
// data.styleList[index] = {}
|
||||||
|
requestOutfit({num:1})
|
||||||
|
}
|
||||||
|
const setLikeStyle = (likeStyle)=>{
|
||||||
|
if(!select.value.id)return
|
||||||
|
if(likeStyle){
|
||||||
|
cancelStyleFavorite(select.value.id).then(()=>{
|
||||||
|
select.value.isLike = false
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
setStyleFavorite(select.value.id).then(()=>{
|
||||||
|
select.value.isLike = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
generateStore.selectStyle(item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateStyle = ({item,index})=>{
|
const setDownload = ()=>{
|
||||||
generateStore.updateStyle(item)
|
if(select.value.path)shareImageToWhatsapp(select.value.path)
|
||||||
data.styleList[index] = {}
|
|
||||||
requestOutfit({num:1,index})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const toProduct = ()=>{
|
const toProduct = ()=>{
|
||||||
if(!generateStore.style.id){
|
// if(generateStore.style.id){
|
||||||
showToast({ message: 'Please select a style.' });
|
// generateStore.setIsGenerate(true)
|
||||||
return
|
// }
|
||||||
}
|
if(!isHistoryFlow.value){
|
||||||
if(generateStore.style.id != generateStore.style.oldId){
|
router.push({ path: 'product', query: {...query.value} })
|
||||||
generateStore.setIsGenerate(true)
|
|
||||||
}
|
|
||||||
const query = router.currentRoute.value.query
|
|
||||||
if(query?.flowType == FlowType.MAIN || !query?.flowType){
|
|
||||||
router.push({ path: 'product', query: {...query} })
|
|
||||||
}else{
|
}else{
|
||||||
router.push({ path: 'creation', query: {...query} })
|
router.push({ path: 'creation', query: {...query.value, active: FlowType.H_OUTFIT} })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestOutfit = ({num,index})=>{
|
const requestOutfit = async ({num})=>{
|
||||||
let value = {
|
let rv = await new Promise<void>((resolve, reject) => {
|
||||||
"customerId": generateStore.customerId,
|
if(isHistoryFlow.value){
|
||||||
"checkInId": generateStore.visitRecordId,
|
retrieveAndRegenerate({tryOnEffectsId:hGenerateStore.originalTryOn.id}).then((rv:any)=>{
|
||||||
"stylist": userInfoStore.state.generateParams.stylist,
|
resolve(rv)
|
||||||
"gender": userInfoStore.state.generateParams.sex,
|
})
|
||||||
"sessionId": generateStore.sessionId,
|
}else{
|
||||||
num,
|
let value = {
|
||||||
}
|
"customerId": generateStore.customerId,
|
||||||
generateRequestOutfit(value).then((rv)=>{
|
"checkInId": generateStore.visitRecordId,
|
||||||
let rvIndex = 0
|
"stylist": userInfoStore.state.generateParams.stylist,
|
||||||
data.styleList.forEach((item,styleIndex)=>{
|
"gender": userInfoStore.state.generateParams.sex,
|
||||||
if(styleIndex < index)return
|
"sessionId": generateStore.sessionId,
|
||||||
item.taskId = rv[rvIndex]
|
num,
|
||||||
rvIndex++
|
}
|
||||||
})
|
generateRequestOutfit(value).then((rv:any)=>{
|
||||||
getRequestOutfitList(rv)
|
resolve(rv)
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
isLoading.value = true
|
||||||
|
generateStore.clearStyle()
|
||||||
|
data.select.taskId = rv[0]
|
||||||
|
getRequestOutfitList(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRequestOutfitList = (generateList)=>{
|
const getRequestOutfitList = (generateList)=>{
|
||||||
let value = {requestIDs:generateList.join(',')}
|
let value = {requestIDs:generateList.join(',')}
|
||||||
getRequestOutfit(value).then((rv:any)=>{
|
getRequestOutfit(value).then((rv:any)=>{
|
||||||
let pendingList = []
|
|
||||||
rv.forEach((item)=>{
|
rv.forEach((item)=>{
|
||||||
if(['RUNNING','PENDING'].includes(item.status))pendingList.push(item.requestId)
|
data.select.id = item.id
|
||||||
let index = data.styleList.findIndex((styleItem)=>styleItem.taskId == item.requestId)
|
data.select.path = item.path
|
||||||
if(index != -1){
|
data.select.status = item.status
|
||||||
data.styleList[index].id = item.id
|
|
||||||
data.styleList[index].path = item.path
|
|
||||||
data.styleList[index].status = item.status
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if(pendingList.length > 0){
|
if(['RUNNING','PENDING'].includes(data.select.status)){
|
||||||
getGenerateTime = setTimeout(()=>{
|
getGenerateTime = setTimeout(()=>{
|
||||||
getRequestOutfitList(pendingList)
|
getRequestOutfitList([data.select.taskId])
|
||||||
},3000)
|
},3000)
|
||||||
|
}else{
|
||||||
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(()=>{
|
||||||
// generateStore.clearProductData()
|
// generateStore.clearProductData()
|
||||||
|
|
||||||
emit('view-type', 1)
|
emit('view-type', 1)
|
||||||
// if(!data.styleList[0]?.id)getRequestOutfitList(0)
|
// if(!data.styleList[0]?.id)getRequestOutfitList(0)
|
||||||
if(getGenerateTime)clearTimeout(getGenerateTime)
|
if(getGenerateTime)clearTimeout(getGenerateTime)
|
||||||
if(!data.styleList[0]?.taskId){
|
if(data.select.status == 'SUCCEEDED'){
|
||||||
requestOutfit({num:4,index:0})
|
return
|
||||||
}else if(data.styleList.filter((item)=>item?.status != 'SUCCEEDED').length > 0){
|
}else if(!data.select?.taskId){
|
||||||
let generateList = data.styleList.map((item)=>item.taskId)
|
requestOutfit({num:1})
|
||||||
getRequestOutfitList(generateList)
|
}else if(data.select.status != 'SUCCEEDED'){
|
||||||
|
isLoading.value = true
|
||||||
|
// let generateList = [data.styleList[0].taskId]
|
||||||
|
getRequestOutfitList([data.select.taskId])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
onUnmounted(()=>{
|
onUnmounted(()=>{
|
||||||
if(getGenerateTime)clearTimeout(getGenerateTime)
|
if(getGenerateTime)clearTimeout(getGenerateTime)
|
||||||
})
|
})
|
||||||
defineExpose({})
|
defineExpose({})
|
||||||
const { styleList, select } = toRefs(data);
|
const { select } = toRefs(data);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="selectStyle">
|
<div class="selectStyle">
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
What’s your Style?
|
Outfit Result
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
Select the outfit that matches you the most.
|
Refine your Look
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectContent flex-1">
|
<div class="selectContent">
|
||||||
<SelectItem :selectList="styleList" v-model:select="select" @selectItem="selectItem" @updateStyle="updateStyle" />
|
<!-- {{ select }} -->
|
||||||
|
<div class="imgBox">
|
||||||
|
<img :src="select.path" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="btn">
|
||||||
|
<div class="like" @click.stop="setLikeStyle(select.isLike)">
|
||||||
|
<SvgIcon :name="`love_${select.isLike?1:0}`" size="35" />
|
||||||
|
</div>
|
||||||
|
<div class="down" @click.stop="setDownload()">
|
||||||
|
<SvgIcon name="download" size="35" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="btn">
|
||||||
<button class="flex flex-center" @click.stop="toProduct">Continue</button>
|
<div class="btnItem style1" @click.stop="updateStyle()">
|
||||||
|
<gradientButton>
|
||||||
|
<template #content>
|
||||||
|
<div class="text">
|
||||||
|
<span class="icon">
|
||||||
|
<SvgIcon name="reTry" size="40" />
|
||||||
|
</span>
|
||||||
|
Re-try
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</gradientButton>
|
||||||
|
</div>
|
||||||
|
<div class="btnItem style2" @click.stop="toProduct">Continue</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="footer placeholder"></div> -->
|
<!-- <div class="footer placeholder"></div> -->
|
||||||
|
<div class="loading-container" v-if="isLoading">
|
||||||
|
<GenerateLoading :title="loadingTitle"/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.header-title {
|
.header-title {
|
||||||
// --header-title-background: #f6f6f6;
|
// --header-title-background: #f6f6f6;
|
||||||
}
|
}
|
||||||
|
.loading-container{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 2;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
.selectStyle{
|
.selectStyle{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -149,12 +215,12 @@ const { styleList, select } = toRefs(data);
|
|||||||
> .text{
|
> .text{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 3rem;
|
margin-top: 8.5rem;
|
||||||
margin-bottom: 4.9rem;
|
margin-bottom: 8.5rem;
|
||||||
> .title{
|
> .title{
|
||||||
font-family: satoshiBold;
|
font-family: satoshiBold;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 9.6rem;
|
font-size: 8.6rem;
|
||||||
line-height: 124%;
|
line-height: 124%;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
@@ -162,46 +228,74 @@ const { styleList, select } = toRefs(data);
|
|||||||
font-size: 4rem;
|
font-size: 4rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 124%;
|
line-height: 124%;
|
||||||
margin-top: 1.3rem;
|
margin-top: 3.2rem;
|
||||||
color: rgba(0, 0, 0, 0.6);
|
color: rgba(0, 0, 0, 0.6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.selectContent{
|
.selectContent{
|
||||||
padding: 0 4rem;
|
// padding: 0 4rem;
|
||||||
|
margin: 0 auto;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
width: 73.7rem;
|
||||||
|
margin-bottom: 19.4rem;
|
||||||
|
> .imgBox{
|
||||||
|
height: 73.7rem;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 4.4rem;
|
||||||
|
> img{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> .btn{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 2rem;
|
||||||
|
> div{
|
||||||
|
color: #000;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 7rem;
|
||||||
|
height: 7rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #fff;
|
||||||
|
&:hover{
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
> .btn{
|
||||||
.footer {
|
display: flex;
|
||||||
// position: fixed;
|
gap: 6.6rem;
|
||||||
// margin-top: 4.4rem;
|
justify-content: center;
|
||||||
// padding: 4rem 4rem 0 0;
|
> div {
|
||||||
margin-top: auto;
|
border-radius: .96rem;
|
||||||
margin-bottom: 5.6rem;
|
width: 33.7rem;
|
||||||
margin-right: 4rem;
|
font-size: 4.8rem;
|
||||||
display: flex;
|
font-family: satoshiMedium;
|
||||||
align-items: center;
|
line-height: 9.2rem;
|
||||||
justify-content: flex-end;
|
display: flex;
|
||||||
// position: absolute;
|
justify-content: center;
|
||||||
// right: 4rem;
|
&.style1{
|
||||||
// bottom: 4rem;
|
--borderRadius: .96rem;
|
||||||
height: 6.7rem;
|
--borderWidth: 2px;
|
||||||
// background-color: #f6f6f6;
|
.text{
|
||||||
&.placeholder{
|
width: 100%;
|
||||||
position: relative;
|
text-align: center;
|
||||||
}
|
> .icon{
|
||||||
> button {
|
left: 4rem;
|
||||||
// margin-right: 5rem;
|
top: 50%;
|
||||||
border-radius: .7rem;
|
transform: translateY(-50%);
|
||||||
border: 3px solid #000;
|
position: absolute;
|
||||||
background-color: #000;
|
}
|
||||||
text-align: center;
|
}
|
||||||
color: #fff;
|
}
|
||||||
font-family: satoshiMedium;
|
&.style2{
|
||||||
font-size: 3.6rem;
|
color: #fff;
|
||||||
width: 24.6rem;
|
background-color: #000;
|
||||||
height: 6.7rem;
|
}
|
||||||
box-sizing: border-box;
|
}
|
||||||
line-height: 6.7rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -4,12 +4,19 @@
|
|||||||
<img src="@/assets/images/chat_loading.png" alt="Loading" class="loading-image" />
|
<img src="@/assets/images/chat_loading.png" alt="Loading" class="loading-image" />
|
||||||
<!-- 阴影效果 -->
|
<!-- 阴影效果 -->
|
||||||
<div class="loading-shadow"></div>
|
<div class="loading-shadow"></div>
|
||||||
<div class="loading-text">{{ title }}</div>
|
<div class="loading-text" ref="textBox">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
<div class="loading-dot" ref="dotBox"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { onMounted, watch, reactive, toRefs, nextTick, ref } from "vue";
|
||||||
|
import { gsap, TweenMax } from "gsap";
|
||||||
|
|
||||||
|
|
||||||
// 这个组件只负责显示loading动画
|
// 这个组件只负责显示loading动画
|
||||||
|
|
||||||
// 定义组件props类型
|
// 定义组件props类型
|
||||||
@@ -20,6 +27,76 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const dotBox = ref(null)
|
||||||
|
const textBox = ref(null)
|
||||||
|
let tl1 = null;
|
||||||
|
const text = ref('')
|
||||||
|
|
||||||
|
watch(() => props.title, (newVal, oldVal) => {
|
||||||
|
if (newVal !== oldVal) {
|
||||||
|
destroyAnimation()
|
||||||
|
fadeOut(newVal)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function fadeOut(newVal) {
|
||||||
|
gsap.to(textBox.value,.5, {
|
||||||
|
opacity: 0,
|
||||||
|
duration: 1,
|
||||||
|
ease: "power2.in",
|
||||||
|
onComplete: () => {
|
||||||
|
// 消失后更换文字
|
||||||
|
text.value = newVal
|
||||||
|
// 然后出现
|
||||||
|
fadeIn();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 出现动画
|
||||||
|
function fadeIn() {
|
||||||
|
gsap.to(textBox.value,.5, {
|
||||||
|
opacity: 1,
|
||||||
|
duration: 1,
|
||||||
|
onComplete:()=>{
|
||||||
|
setTl1();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const setTl1 = ()=>{
|
||||||
|
nextTick(()=>{
|
||||||
|
let el = dotBox.value
|
||||||
|
let width = el.offsetWidth + el.parentElement.offsetWidth
|
||||||
|
let time = el.parentElement.offsetWidth / 35
|
||||||
|
console.log(time,width)
|
||||||
|
tl1 = gsap.timeline();
|
||||||
|
tl1.to(el,time,
|
||||||
|
{
|
||||||
|
ease: "power1.in",
|
||||||
|
left:width,
|
||||||
|
onComplete:()=>{
|
||||||
|
setTimeout(() => {
|
||||||
|
tl1.restart()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
tl1.progress(0);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function destroyAnimation() {
|
||||||
|
if (tl1) {
|
||||||
|
tl1.progress(0);
|
||||||
|
tl1.kill();
|
||||||
|
tl1 = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
text.value = props.title
|
||||||
|
setTl1()
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -54,6 +131,18 @@ const props = defineProps({
|
|||||||
font-size: 4.8rem;
|
font-size: 4.8rem;
|
||||||
letter-spacing: 0.02em;
|
letter-spacing: 0.02em;
|
||||||
line-height: 124%;
|
line-height: 124%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-dot{
|
||||||
|
height: 100%;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
background: radial-gradient(ellipse 150% 150% at center, #ffffff,rgba(255,255,255,.4), transparent);
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translate(-100%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rotate {
|
@keyframes rotate {
|
||||||
|
|||||||
@@ -3,32 +3,26 @@
|
|||||||
<div class="header">
|
<div class="header">
|
||||||
<HeaderTitle hasSetting styleType="3" />
|
<HeaderTitle hasSetting styleType="3" />
|
||||||
</div>
|
</div>
|
||||||
<div class="loading-container" v-if="isLoading">
|
<div class="content flex-1">
|
||||||
<GenerateLoading />
|
<NoticeList
|
||||||
|
ref="noticeListRef"
|
||||||
|
:list="messageList"
|
||||||
|
:is-streaming="isStreaming"
|
||||||
|
:streaming-message="currentStreamingMessage"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<div class="footer">
|
||||||
<div class="content flex-1" v-if="!isLoading">
|
<InputArea @send-message="handleSendMessage" />
|
||||||
<NoticeList
|
<div class="continue flex">
|
||||||
ref="noticeListRef"
|
<div class="btn flex flex-center" @click="handleContinue">Continue</div>
|
||||||
:list="messageList"
|
|
||||||
:is-streaming="isStreaming"
|
|
||||||
:streaming-message="currentStreamingMessage"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="footer" v-if="!isLoading">
|
</div>
|
||||||
<InputArea @send-message="handleSendMessage" />
|
|
||||||
<div class="continue flex">
|
|
||||||
<div class="btn flex flex-center" @click="handleContinue">Continue</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import HeaderTitle from '@/components/HeaderTitle.vue'
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
import NoticeList from './components/NoticeList.vue'
|
import NoticeList from './components/NoticeList.vue'
|
||||||
import InputArea from './components/InputArea.vue'
|
import InputArea from './components/InputArea.vue'
|
||||||
import GenerateLoading from './components/GenerateLoading.vue'
|
|
||||||
import { ref, onMounted, onUnmounted, onActivated } from 'vue'
|
import { ref, onMounted, onUnmounted, onActivated } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { useUserInfoStore, useGenerateStore } from '@/stores'
|
import { useUserInfoStore, useGenerateStore } from '@/stores'
|
||||||
@@ -60,7 +54,6 @@ interface ChatMessage {
|
|||||||
self?: boolean
|
self?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const isLoading = ref<boolean>(false)
|
|
||||||
const noticeListRef = ref<NoticeListRef | null>(null)
|
const noticeListRef = ref<NoticeListRef | null>(null)
|
||||||
const messageList = ref<ChatMessage[]>([])
|
const messageList = ref<ChatMessage[]>([])
|
||||||
|
|
||||||
@@ -273,12 +266,8 @@ const handleFetchMessage = (message: string) => {
|
|||||||
const handleContinue = () => {
|
const handleContinue = () => {
|
||||||
// router.push('/workshop/selectStyle')
|
// router.push('/workshop/selectStyle')
|
||||||
// 模拟接口之后再跳转
|
// 模拟接口之后再跳转
|
||||||
isLoading.value = true
|
|
||||||
generateStore.clearProductData()
|
generateStore.clearProductData()
|
||||||
setTimeout(() => {
|
router.push('/workshop/selectStyle')
|
||||||
router.push('/workshop/selectStyle')
|
|
||||||
isLoading.value = false
|
|
||||||
}, 1000)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@@ -315,12 +304,4 @@ const handleContinue = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-container {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Profile ref="profileRef" @selected-customer="handleSelectCustomer" />
|
<Profile ref="profileRef" @selected-customer="handleSelectCustomer" is-customer />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -66,8 +66,10 @@ import { ref, computed } from 'vue'
|
|||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useGenerateStore, useUserInfoStore } from '@/stores'
|
import { useGenerateStore, useUserInfoStore } from '@/stores'
|
||||||
import { showToast } from 'vant'
|
import { showToast } from 'vant'
|
||||||
import { customerCheckin } from '@/api/workshop'
|
import { customerCheckin, createCustomer, type CreateCustomerParams } from '@/api/workshop'
|
||||||
import Profile from '../Workshop/profile.vue'
|
import Profile from '../Workshop/profile.vue'
|
||||||
|
import MyEvent from '@/utils/myEvent'
|
||||||
|
|
||||||
|
|
||||||
const profileRef = ref<typeof Profile>(null)
|
const profileRef = ref<typeof Profile>(null)
|
||||||
const handleOpenProfile = () => {
|
const handleOpenProfile = () => {
|
||||||
@@ -94,21 +96,43 @@ const customerData = ref({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
if (customerData.value.vipId === '') {
|
|
||||||
showToast({
|
|
||||||
message: 'please input name and email',
|
|
||||||
position: 'top'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (pageMode.value === 'form') {
|
if (pageMode.value === 'form') {
|
||||||
await customerCheckin({ nickname: customerData.value.nickname }).then((res) => {
|
if (customerData.value.nickname === '') {
|
||||||
|
showToast({
|
||||||
|
message: 'please input the nickname'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
customerCheckin({ nickname: customerData.value.nickname }).then((res) => {
|
||||||
useUserInfoStore().resetGenerateParams()
|
useUserInfoStore().resetGenerateParams()
|
||||||
generateStore.setCustomerInfo(res)
|
generateStore.setCustomerInfo(res)
|
||||||
router.push('/workshop/home')
|
router.push('/workshop/home')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 创建接口
|
if (customerData.value.vipId === '') {
|
||||||
|
showToast({
|
||||||
|
message: 'please input the VIP ID'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (customerData.value.nickname === '') {
|
||||||
|
showToast({
|
||||||
|
message: 'please input the nickname'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createCustomer({
|
||||||
|
nickname: customerData.value.nickname,
|
||||||
|
vipId: customerData.value.vipId
|
||||||
|
} as CreateCustomerParams).then((res) => {
|
||||||
|
showToast({
|
||||||
|
message: 'Customer created successfully'
|
||||||
|
})
|
||||||
|
handleBack()
|
||||||
|
MyEvent.emit('update-customer-list')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,15 +142,16 @@ const handleShowPopup = (flag: Boolean) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSelectCustomer = (value) => {
|
const handleSelectCustomer = (value) => {
|
||||||
console.log(value)
|
if (value) {
|
||||||
// if (selected) {
|
customerData.value.nickname = value.name
|
||||||
// customerData.value.nickname = selected.nickname
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleBack = (e?: Event) => {
|
const handleBack = (e?: Event) => {
|
||||||
e.stopPropagation()
|
if (e) {
|
||||||
e.preventDefault()
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
if (pageMode.value !== 'entry') {
|
if (pageMode.value !== 'entry') {
|
||||||
pageMode.value = 'entry'
|
pageMode.value = 'entry'
|
||||||
customerData.value = {
|
customerData.value = {
|
||||||
|
|||||||
Reference in New Issue
Block a user