- What’s your Style?
+ Outfit Result
- Select the outfit that matches you the most.
+ Refine your Look
-
+
+
+
+
![]()
+
+
-
+
+
+
\ No newline at end of file
From b17637b2bc303aaf1abe6035ce8f9bb5e78348be Mon Sep 17 00:00:00 2001
From: zhangyahui
Date: Tue, 23 Dec 2025 14:19:00 +0800
Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E8=8E=B7=E5=8F=96=E9=A1=BE?=
=?UTF-8?q?=E5=AE=A2=E5=88=97=E8=A1=A8&=E6=96=B0=E5=BB=BA=E9=A1=BE?=
=?UTF-8?q?=E5=AE=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/workshop.ts | 192 +++++++++++++++++++--------------
src/utils/myEvent.js | 1 +
src/utils/request.ts | 2 +-
src/views/Workshop/profile.vue | 112 ++++++++++++++++---
src/views/login/customer.vue | 57 +++++++---
5 files changed, 254 insertions(+), 110 deletions(-)
diff --git a/src/api/workshop.ts b/src/api/workshop.ts
index aa88cb9..7236d3c 100644
--- a/src/api/workshop.ts
+++ b/src/api/workshop.ts
@@ -8,26 +8,26 @@ import request from '@/utils/request'
* @param data.stylist 提示词
* @param data.gender 原始试穿效果id
* @param data.num 是否重新生成 0-否,1-是
-*/
+ */
export function generateRequestOutfit(data: Object) {
- return request({
- url: '/api/style/requestOutfit',
- method: 'post',
- data,
- })
+ return request({
+ url: '/api/style/requestOutfit',
+ method: 'post',
+ data
+ })
}
/**
* 获取传达风格
* @param data 获取传达风格数据
* @param data.requestIDs 获取生成结果的taskId
-*/
+ */
export function getRequestOutfit(data: Object) {
- return request({
- url: '/api/style/getOutfitResult',
- method: 'get',
- params:data
- })
+ return request({
+ url: '/api/style/getOutfitResult',
+ method: 'get',
+ params: data
+ })
}
/**
@@ -41,13 +41,13 @@ export function getRequestOutfit(data: Object) {
* @param data.prompt 提示词
* @param data.originalTryOnId 原始试穿效果id
* @param data.isRegenerated 是否重新生成 0-否,1-是
-*/
+ */
export function generateTryOnEffect(data: Object) {
- return request({
- url: '/api/try-on-effects/generate',
- method: 'post',
- data,
- })
+ return request({
+ url: '/api/try-on-effects/generate',
+ method: 'post',
+ data
+ })
}
/**
* 生成试穿效果-演示
@@ -55,13 +55,13 @@ export function generateTryOnEffect(data: Object) {
* @param data.customerPhotoId 顾客照片id
* @param data.prompt 提示词
* @param data.tryonUrl AI魔改url
-*/
+ */
export function generateTryOnEffectDemo(data: Object) {
- return request({
- url: '/api/try-on-effects/reFace',
- method: 'post',
- data,
- })
+ return request({
+ url: '/api/try-on-effects/reFace',
+ method: 'post',
+ data
+ })
}
/** 上传图片-AI换脸
@@ -71,96 +71,130 @@ export function generateTryOnEffectDemo(data: Object) {
* @param data.file 顾客照片文件
*/
export function uploadCustomerPhoto(data: FormData) {
- return request({
- url: '/api/customer-photos/upload',
- method: 'post',
- data,
- loading: true,
- })
+ return request({
+ url: '/api/customer-photos/upload',
+ method: 'post',
+ data,
+ loading: true
+ })
}
/**
* 设置喜欢
* @param tryOnId 试穿效果id
-*/
+ */
export function setTryOnEffectFavorite(tryOnId: string | number) {
- if (!tryOnId) return Promise.reject('试穿效果id不能为空');
- return request({
- url: `/api/try-on-effects/set-favorite/${tryOnId}`,
- method: 'post',
- })
+ if (!tryOnId) return Promise.reject('试穿效果id不能为空')
+ return request({
+ url: `/api/try-on-effects/set-favorite/${tryOnId}`,
+ method: 'post'
+ })
}
/**
* 取消喜欢
* @param tryOnId 试穿效果id
-*/
+ */
export function cancelTryOnEffectFavorite(tryOnId: string | number) {
- if (!tryOnId) return Promise.reject('试穿效果id不能为空');
- return request({
- url: `/api/try-on-effects/cancel-favorite/${tryOnId}`,
- method: 'post',
- })
+ if (!tryOnId) return Promise.reject('试穿效果id不能为空')
+ return request({
+ url: `/api/try-on-effects/cancel-favorite/${tryOnId}`,
+ method: 'post'
+ })
}
/** 查询进店记录-library
* @param customerId 客户id
*/
export function getCustomerPhotos(customerId: string | number) {
- if (!customerId) return Promise.reject('客户id不能为空');
- return request({
- url: `/api/visit-records/customer/${customerId}`,
- method: 'get',
- })
+ if (!customerId) return Promise.reject('客户id不能为空')
+ return request({
+ url: `/api/visit-records/customer/${customerId}`,
+ method: 'get'
+ })
}
/** 删除进店记录-library
* @param visitRecordId 进店记录id
*/
export function deleteCustomerPhoto(visitRecordId: string | number) {
- if (!visitRecordId) return Promise.reject('进店记录id不能为空');
- return request({
- url: `/api/visit-records/${visitRecordId}`,
- method: 'delete',
- // loading: true,
- })
+ 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',
- })
+ 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',
- })
+ 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({
+ url: '/api/customers/createCustomer',
+ method: 'get',
+ params: data
+ })
+}
// 选择顾客
interface CustomerInfo {
vipId: string
}
-export const customerCheckin = (data: CustomerInfo) => {
- return request({
- url: '/api/customers/checkIn',
- method: 'get',
- params: data,
- })
+export const customerCheckin = (data: CustomerInfo) => {
+ return request({
+ url: '/api/customers/checkIn',
+ method: 'get',
+ params: data
+ })
}
// AI对话
interface AIConversation {
- message: string
- sessionId: string | number //用户ID
- gender: 'male' | 'female' //性别
+ message: string
+ sessionId: string | number //用户ID
+ gender: 'male' | 'female' //性别
}
export const streamChatAddress = '/api/llm/streamChat'
@@ -171,11 +205,11 @@ export const streamChatAddress = '/api/llm/streamChat'
* @param data.visitRecordId 进店记录id
* @param data.customerId 顾客id
* @param data.suggestion 意见和建议
-*/
+ */
export function addTryOnEffectComment(data: Object) {
- return request({
- url: '/api/try-on-effects/add-comment',
- method: 'post',
- data,
- })
-}
\ No newline at end of file
+ return request({
+ url: '/api/try-on-effects/add-comment',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/utils/myEvent.js b/src/utils/myEvent.js
index e3c4e1b..78bf9cc 100644
--- a/src/utils/myEvent.js
+++ b/src/utils/myEvent.js
@@ -7,6 +7,7 @@ class MyEvent {
MyEvent.list = MyEvent.list.filter(item => item.name != name && item.call != call)
}
emit(name, data) {
+ console.log('Myevent触发--',name)
MyEvent.list.forEach(item => {
if (item.name == name) item.call(data)
})
diff --git a/src/utils/request.ts b/src/utils/request.ts
index e047ce9..9a6e98c 100644
--- a/src/utils/request.ts
+++ b/src/utils/request.ts
@@ -80,7 +80,7 @@ service.interceptors.response.use(
}
const res = response.data
// 处理异常的情况
- console.log(res)
+ // console.log(res)
if (res.code != 0) {
showToast({
message: res.errMsg || res.message,
diff --git a/src/views/Workshop/profile.vue b/src/views/Workshop/profile.vue
index e3dc126..c221087 100644
--- a/src/views/Workshop/profile.vue
+++ b/src/views/Workshop/profile.vue
@@ -4,6 +4,9 @@ import router from '@/router'
import { showConfirmDialog } from 'vant'
import { useUserInfoStore, useOverallStore } from '@/stores'
import { LogOut } from '@/api/login'
+import { getCustomerList, type CustomerListParams } from '@/api/workshop'
+import MyEvent from '@/utils/myEvent'
+
const userInfoStore = useUserInfoStore()
const overallStore = useOverallStore()
const emit = defineEmits(['view-type', 'selected-customer'])
@@ -60,22 +63,84 @@ const logout = () => {
}
const showSwitchCustomerPopup = ref(false)
+const custmerParams = ref({
+ current: 1,
+ size: 5,
+ desc: true
+})
+const customerList = ref([])
+const pager = reactive({
+ loading: false,
+ noMore: false,
+ total: null as number | null
+})
+const customerListEl = ref(null)
-const customerList = ref([
- { id: 'CUST001', nickname: 'Customer One', checked: true },
- { id: 'CUST002', nickname: 'Customer Two', checked: false },
- { id: 'CUST003', nickname: 'Customer Three', checked: false },
- { id: 'CUST004', nickname: 'Customer Four', checked: false },
- { id: 'CUST005', nickname: 'Customer Five', checked: false }
-])
+const loadCustomers = async (reset = false) => {
+ if (pager.loading) return
+ if (reset) {
+ custmerParams.value.current = 1
+ pager.noMore = 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弹窗
const handleShowPopup = (flag: boolean) => {
showSwitchCustomerPopup.value = flag
- show.value = !flag
+ show.value = !flag
+ if (flag) {
+ loadCustomers(true)
+ }
}
const handleChangeChecked = (item) => {
customerList.value.forEach((customer) => {
- customer.checked = customer.id === item.id
+ customer.checked = customer.vipId === item.vipId
})
}
const handleSelectCustomer = () => {
@@ -86,10 +151,19 @@ const handleSelectCustomer = () => {
showSwitchCustomerPopup.value = false
}
+const handleFetchCustomerList = () => {
+ loadCustomers(true)
+}
+MyEvent.add('update-customer-list', handleFetchCustomerList)
+
const openSwitchCustomerPopup = (flag = true) => {
showSwitchCustomerPopup.value = flag
}
+onMounted(() => {
+ handleFetchCustomerList()
+})
+
defineExpose({ open, close, openSwitchCustomerPopup })
@@ -185,16 +259,16 @@ defineExpose({ open, close, openSwitchCustomerPopup })
Saved Customer ID
+
-
{{ item.nickname }}
-
{{ item.id }}
+
{{ item.name }}
+
{{ item.vipId }}
@@ -204,6 +278,10 @@ defineExpose({ open, close, openSwitchCustomerPopup })
+
Confirm
@@ -375,6 +453,12 @@ defineExpose({ open, close, openSwitchCustomerPopup })
}
}
}
+ .list-footer {
+ text-align: center;
+ padding: 2rem 0;
+ font-size: 3rem;
+ color: #9b9b9b;
+ }
.confirm-btn {
margin: 4.9rem 12.7rem 0 13.3rem;
border: 0.25rem solid #3b3b3b;
diff --git a/src/views/login/customer.vue b/src/views/login/customer.vue
index ada4ffd..0e49d5d 100644
--- a/src/views/login/customer.vue
+++ b/src/views/login/customer.vue
@@ -66,8 +66,10 @@ import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { useGenerateStore, useUserInfoStore } from '@/stores'
import { showToast } from 'vant'
-import { customerCheckin } from '@/api/workshop'
+import { customerCheckin, createCustomer, type CreateCustomerParams } from '@/api/workshop'
import Profile from '../Workshop/profile.vue'
+import MyEvent from '@/utils/myEvent'
+
const profileRef = ref
(null)
const handleOpenProfile = () => {
@@ -94,21 +96,43 @@ const customerData = ref({
})
const handleConfirm = async () => {
- if (customerData.value.vipId === '') {
- showToast({
- message: 'please input name and email',
- position: 'top'
- })
- return
- }
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()
generateStore.setCustomerInfo(res)
router.push('/workshop/home')
})
} 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) => {
- console.log(value)
- // if (selected) {
- // customerData.value.nickname = selected.nickname
- // }
+ if (value) {
+ customerData.value.nickname = value.name
+ }
}
const handleBack = (e?: Event) => {
- e.stopPropagation()
- e.preventDefault()
+ if (e) {
+ e.stopPropagation()
+ e.preventDefault()
+ }
if (pageMode.value !== 'entry') {
pageMode.value = 'entry'
customerData.value = {
From 65617baa96b1341239bc0ca69370f94c5afcde78 Mon Sep 17 00:00:00 2001
From: zhangyahui
Date: Tue, 23 Dec 2025 14:41:09 +0800
Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E5=88=87=E6=8D=A2customer?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/views/Workshop/home.vue | 4 ++--
src/views/Workshop/profile.vue | 14 +++++++++++++-
src/views/login/customer.vue | 2 +-
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/src/views/Workshop/home.vue b/src/views/Workshop/home.vue
index 783c6c2..29dc2b2 100644
--- a/src/views/Workshop/home.vue
+++ b/src/views/Workshop/home.vue
@@ -8,7 +8,7 @@ import { FlowType } from '@/types/enum'
//const props = defineProps({
//})
const emit = defineEmits([
- 'view-type'
+ 'viewType'
])
// const data = reactive({
@@ -23,7 +23,7 @@ const historicalReview = ()=>{
}
onMounted(()=>{
- emit('view-type', 1)
+ emit('viewType', 1)
})
onUnmounted(()=>{
})
diff --git a/src/views/Workshop/profile.vue b/src/views/Workshop/profile.vue
index c221087..ae7eafa 100644
--- a/src/views/Workshop/profile.vue
+++ b/src/views/Workshop/profile.vue
@@ -4,9 +4,13 @@ import router from '@/router'
import { showConfirmDialog } from 'vant'
import { useUserInfoStore, useOverallStore } from '@/stores'
import { LogOut } from '@/api/login'
-import { getCustomerList, type CustomerListParams } from '@/api/workshop'
+import { getCustomerList, type CustomerListParams,customerCheckin } from '@/api/workshop'
import MyEvent from '@/utils/myEvent'
+const props = defineProps<{
+ isCustomer?: boolean
+}>()
+
const userInfoStore = useUserInfoStore()
const overallStore = useOverallStore()
const emit = defineEmits(['view-type', 'selected-customer'])
@@ -148,6 +152,14 @@ const handleSelectCustomer = () => {
if (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
}
diff --git a/src/views/login/customer.vue b/src/views/login/customer.vue
index 0e49d5d..4df7116 100644
--- a/src/views/login/customer.vue
+++ b/src/views/login/customer.vue
@@ -58,7 +58,7 @@
-
+