feat: 获取顾客列表&新建顾客
This commit is contained in:
@@ -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,
|
||||
})
|
||||
}
|
||||
return request({
|
||||
url: '/api/try-on-effects/add-comment',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<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([
|
||||
{ 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 })
|
||||
</script>
|
||||
|
||||
@@ -185,16 +259,16 @@ defineExpose({ open, close, openSwitchCustomerPopup })
|
||||
<div class="title-txt">Saved Customer ID</div>
|
||||
<SvgIcon name="close_nocolor" color="#a1a1a1" size="40" @click="handleShowPopup(false)" />
|
||||
</div>
|
||||
<div class="cusomter-list">
|
||||
<div ref="customerListEl" class="cusomter-list" @scroll="onScroll">
|
||||
<div
|
||||
class="customer-item flex flex-align-center flex-between"
|
||||
v-for="item in customerList"
|
||||
:key="item.id"
|
||||
v-for="(item, index) in customerList"
|
||||
:key="index + 'customer'"
|
||||
@click="handleChangeChecked(item)"
|
||||
>
|
||||
<div class="info">
|
||||
<div class="name">{{ item.nickname }}</div>
|
||||
<div class="id">{{ item.id }}</div>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div class="id">{{ item.vipId }}</div>
|
||||
</div>
|
||||
<div class="select-box">
|
||||
<div class="check-box flex flex-center" v-show="!item.checked">
|
||||
@@ -204,6 +278,10 @@ defineExpose({ open, close, openSwitchCustomerPopup })
|
||||
</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>
|
||||
</van-popup>
|
||||
</template>
|
||||
@@ -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;
|
||||
|
||||
@@ -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<typeof Profile>(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 = {
|
||||
|
||||
Reference in New Issue
Block a user