添加接口
This commit is contained in:
@@ -1,4 +1,12 @@
|
|||||||
import request from '@/utils/request'
|
// import request from '@/utils/request'
|
||||||
|
// 测试 模拟请求
|
||||||
|
const request = (config: any) => {
|
||||||
|
return new Promise(res => {
|
||||||
|
setTimeout(() => {
|
||||||
|
res({})
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}
|
||||||
//创建用户
|
//创建用户
|
||||||
export function userCreate(params: Object) {
|
export function userCreate(params: Object) {
|
||||||
return request({
|
return request({
|
||||||
@@ -27,7 +35,7 @@ export function getQueryPage(data: Object) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data,
|
data,
|
||||||
// repeatRequest: true // 配置为true,则可以同一时间多次调用
|
// repeatRequest: true // 配置为true,则可以同一时间多次调用
|
||||||
}as any)
|
} as any)
|
||||||
}
|
}
|
||||||
|
|
||||||
//查报告
|
//查报告
|
||||||
@@ -37,3 +45,127 @@ export function getCalculateReport() {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成试穿效果
|
||||||
|
* @param data 试穿效果数据
|
||||||
|
* @param data.customerId 顾客ID
|
||||||
|
* @param data.visitRecordId 进店记录id
|
||||||
|
* @param data.styleId 样式id
|
||||||
|
* @param data.modelPhotoId 模型照片id
|
||||||
|
* @param data.customerPhotoId 顾客照片id
|
||||||
|
* @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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上传图片-AI换脸
|
||||||
|
* @param data 图片数据
|
||||||
|
* @param data.customerId 顾客ID
|
||||||
|
* @param data.visitRecordId 进店记录id
|
||||||
|
* @param data.file 顾客照片文件
|
||||||
|
*/
|
||||||
|
export function uploadCustomerPhoto(data: FormData) {
|
||||||
|
return request({
|
||||||
|
url: '/api/customer-photos/upload',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置喜欢
|
||||||
|
* @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',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 取消喜欢
|
||||||
|
* @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',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询进店记录-library
|
||||||
|
* @param customerId 客户id
|
||||||
|
*/
|
||||||
|
export function getCustomerPhotos(customerId: string | number) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve([{ visitRecordId: 1 }, { visitRecordId: 2 }, { visitRecordId: 3 }])
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/** 查询收藏列表
|
||||||
|
* @param visitRecordId 进店记录id
|
||||||
|
*/
|
||||||
|
export function getTryOnEffectFavoriteList(visitRecordId: string | number) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve([
|
||||||
|
{ tryOnId: 1, tryOnUrl: 'http://118.31.39.42:3000/falls/1.png', styleUrl: 'http://118.31.39.42:3000/falls/1.png' },
|
||||||
|
{ tryOnId: 2, tryOnUrl: 'http://118.31.39.42:3000/falls/2.png', styleUrl: 'http://118.31.39.42:3000/falls/2.png' },
|
||||||
|
{ tryOnId: 3, tryOnUrl: 'http://118.31.39.42:3000/falls/3.png', styleUrl: 'http://118.31.39.42:3000/falls/3.png' },
|
||||||
|
{ tryOnId: 4, tryOnUrl: 'http://118.31.39.42:3000/falls/4.png', styleUrl: 'http://118.31.39.42:3000/falls/4.png' }
|
||||||
|
])
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
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) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve([
|
||||||
|
{ tryOnId: 1, tryOnUrl: 'http://118.31.39.42:3000/falls/1.png', styleUrl: 'http://118.31.39.42:3000/falls/1.png' },
|
||||||
|
{ tryOnId: 2, tryOnUrl: 'http://118.31.39.42:3000/falls/2.png', styleUrl: 'http://118.31.39.42:3000/falls/2.png' },
|
||||||
|
{ tryOnId: 3, tryOnUrl: 'http://118.31.39.42:3000/falls/3.png', styleUrl: 'http://118.31.39.42:3000/falls/3.png' },
|
||||||
|
{ tryOnId: 4, tryOnUrl: 'http://118.31.39.42:3000/falls/4.png', styleUrl: 'http://118.31.39.42:3000/falls/4.png' }
|
||||||
|
])
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
if (!styleId) return Promise.reject('服装id不能为空');
|
||||||
|
return request({
|
||||||
|
url: `/api/try-on-effects/style/${styleId}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { Dialog } from 'vant'
|
|
||||||
import { showConfirmDialog } from 'vant'
|
import { showConfirmDialog } from 'vant'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|||||||
@@ -10,34 +10,34 @@ function getUniversalZoomLevel() {
|
|||||||
// 备用方案2(不精确)
|
// 备用方案2(不精确)
|
||||||
return window.outerWidth / window.innerWidth;
|
return window.outerWidth / window.innerWidth;
|
||||||
}
|
}
|
||||||
const getMousePosition = (e:any,bor:any) => {
|
const getMousePosition = (e: any, bor: any) => {
|
||||||
// if(e?.stopPropagation)e.stopPropagation()
|
// if(e?.stopPropagation)e.stopPropagation()
|
||||||
// if(e?.preventDefault)e.preventDefault();
|
// if(e?.preventDefault)e.preventDefault();
|
||||||
let event:any
|
let event: any
|
||||||
if(bor){
|
if (bor) {
|
||||||
const touch = e.changedTouches[0] as any;
|
const touch = e.changedTouches[0] as any;
|
||||||
event = {
|
event = {
|
||||||
offsetX:touch.clientX - e.target.getBoundingClientRect().left,
|
offsetX: touch.clientX - e.target.getBoundingClientRect().left,
|
||||||
offsetY: touch.clientY - e.target.getBoundingClientRect().top,
|
offsetY: touch.clientY - e.target.getBoundingClientRect().top,
|
||||||
clientX:touch.clientX,
|
clientX: touch.clientX,
|
||||||
clientY:touch.clientY,
|
clientY: touch.clientY,
|
||||||
screenX:touch.screenX,
|
screenX: touch.screenX,
|
||||||
screenY:touch.screenY,
|
screenY: touch.screenY,
|
||||||
target:e.target,
|
target: e.target,
|
||||||
}
|
}
|
||||||
// if(dom){
|
// if(dom){
|
||||||
// event.offsetX = touch.clientX - dom.getBoundingClientRect().left
|
// event.offsetX = touch.clientX - dom.getBoundingClientRect().left
|
||||||
// event.offsetY = touch.clientY - dom.getBoundingClientRect().top
|
// event.offsetY = touch.clientY - dom.getBoundingClientRect().top
|
||||||
// }
|
// }
|
||||||
}else{
|
} else {
|
||||||
event = {
|
event = {
|
||||||
offsetX:e.offsetX,
|
offsetX: e.offsetX,
|
||||||
offsetY:e.offsetY,
|
offsetY: e.offsetY,
|
||||||
clientX:e.clientX,
|
clientX: e.clientX,
|
||||||
clientY:e.clientY,
|
clientY: e.clientY,
|
||||||
screenX:e.screenX,
|
screenX: e.screenX,
|
||||||
screenY:e.screenY,
|
screenY: e.screenY,
|
||||||
target:e.target,
|
target: e.target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return event
|
return event
|
||||||
@@ -48,6 +48,41 @@ export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** 时间格式化-自定义格式
|
||||||
|
* @param value 时间对象|时间戳|时间字符串
|
||||||
|
* @param format 格式化字符串,默认值为 'yyyy-MM-dd HH:mm:ss'
|
||||||
|
* @returns 格式化后的时间字符串
|
||||||
|
*/
|
||||||
|
export function FormatDate(value: Date | number | string, format: string = 'yyyy-MM-dd HH:mm:ss') {
|
||||||
|
const date = new Date(value);
|
||||||
|
const yyyy = String(date.getFullYear());
|
||||||
|
const yy = String(date.getFullYear()).slice(-2);
|
||||||
|
const MM = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const M = String(date.getMonth() + 1);
|
||||||
|
const dd = String(date.getDate()).padStart(2, '0');
|
||||||
|
const d = String(date.getDate());
|
||||||
|
const HH = String(date.getHours()).padStart(2, '0');
|
||||||
|
const H = String(date.getHours());
|
||||||
|
const mm = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const m = String(date.getMinutes());
|
||||||
|
const ss = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
const s = String(date.getSeconds());
|
||||||
|
const str = format.replaceAll('yyyy', yyyy)
|
||||||
|
.replaceAll('yy', yy)
|
||||||
|
.replaceAll('MM', MM)
|
||||||
|
.replaceAll('M', M)
|
||||||
|
.replaceAll('dd', dd)
|
||||||
|
.replaceAll('d', d)
|
||||||
|
.replaceAll('HH', HH)
|
||||||
|
.replaceAll('H', H)
|
||||||
|
.replaceAll('mm', mm)
|
||||||
|
.replaceAll('m', m)
|
||||||
|
.replaceAll('ss', ss)
|
||||||
|
.replaceAll('s', s);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载图片
|
* 下载图片
|
||||||
* @param list 图片列表
|
* @param list 图片列表
|
||||||
@@ -55,7 +90,7 @@ export {
|
|||||||
* @param onError 下载错误回调
|
* @param onError 下载错误回调
|
||||||
* @param onSuccess 下载成功回调
|
* @param onSuccess 下载成功回调
|
||||||
*/
|
*/
|
||||||
export async function DownloadImages(list:Array<{url:string,name:string}>, onProgress?:(count:number,total:number,item:any)=>void, onError?:(count:number,total:number,item:any)=>void, onSuccess?:(successCount:number,errCount:number)=>void) {
|
export async function DownloadImages(list: Array<{ url: string, name: string }>, onProgress?: (count: number, total: number, item: any) => void, onError?: (count: number, total: number, item: any) => void, onSuccess?: (successCount: number, errCount: number) => void) {
|
||||||
const total = list.length;
|
const total = list.length;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let successCount = 0;
|
let successCount = 0;
|
||||||
@@ -74,22 +109,22 @@ export async function DownloadImages(list:Array<{url:string,name:string}>, onPro
|
|||||||
a.download = list[i].name || list[i].url;
|
a.download = list[i].name || list[i].url;
|
||||||
a.click();
|
a.click();
|
||||||
successCount++;
|
successCount++;
|
||||||
typeof onProgress === "function" && onProgress(count,total,list[i]);
|
typeof onProgress === "function" && onProgress(count, total, list[i]);
|
||||||
resolve(blob);
|
resolve(blob);
|
||||||
} else {
|
} else {
|
||||||
errCount++;
|
errCount++;
|
||||||
typeof onError === "function" && onError(count,total,list[i]);
|
typeof onError === "function" && onError(count, total, list[i]);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
xhr.onerror = function () {
|
xhr.onerror = function () {
|
||||||
count++;
|
count++;
|
||||||
errCount++;
|
errCount++;
|
||||||
typeof onError === "function" && onError(count,total,list[i]);
|
typeof onError === "function" && onError(count, total, list[i]);
|
||||||
resolve(true);
|
resolve(true);
|
||||||
};
|
};
|
||||||
xhr.send();
|
xhr.send();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
typeof onSuccess === "function" && onSuccess(successCount,errCount);
|
typeof onSuccess === "function" && onSuccess(successCount, errCount);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,13 @@
|
|||||||
import { DownloadImages } from '@/utils/tools'
|
import { DownloadImages } from '@/utils/tools'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const query = computed(() => router.currentRoute.value.query)
|
const query = computed(() => router.currentRoute.value.query)
|
||||||
|
const styleUrl = computed(() => query.value.styleUrl)
|
||||||
|
|
||||||
onMounted(() => {})
|
onMounted(() => {})
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const onDownload = () => {
|
const onDownload = () => {
|
||||||
DownloadImages([{
|
DownloadImages([{
|
||||||
url: 'http://118.31.39.42:3000/falls/2.png',
|
url: styleUrl.value,
|
||||||
name: 'lane-crawford.png'
|
name: 'lane-crawford.png'
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
<div class="creation-details">
|
<div class="creation-details">
|
||||||
<div class="title">Lane Crawford</div>
|
<div class="title">Lane Crawford</div>
|
||||||
<p class="tip">Business Casual Suits</p>
|
<p class="tip">Business Casual Suits</p>
|
||||||
<div class="image"><img src="@/assets/images/workshop/creation-details.png" /></div>
|
<div class="image"><img :src="styleUrl" /></div>
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<div class="icon" @click="onDownload"><SvgIcon name="download" size="33" /></div>
|
<div class="icon" @click="onDownload"><SvgIcon name="download" size="33" /></div>
|
||||||
<button @click="onEdit">Edit</button>
|
<button @click="onEdit">Edit</button>
|
||||||
|
|||||||
@@ -2,11 +2,18 @@
|
|||||||
import { ref, reactive, onMounted, computed } from 'vue'
|
import { ref, reactive, onMounted, computed } from 'vue'
|
||||||
import MyList from '@/components/myList.vue'
|
import MyList from '@/components/myList.vue'
|
||||||
import { DownloadImages } from '@/utils/tools'
|
import { DownloadImages } from '@/utils/tools'
|
||||||
|
import {
|
||||||
|
getTryOnEffectFavoriteList,
|
||||||
|
getTryOnEffectStyleList,
|
||||||
|
setTryOnEffectFavorite,
|
||||||
|
cancelTryOnEffectFavorite
|
||||||
|
} from '@/api/workshop'
|
||||||
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const emit = defineEmits(['view-type'])
|
const emit = defineEmits(['view-type'])
|
||||||
const query = router.currentRoute.value.query
|
const query = computed(() => router.currentRoute.value.query)
|
||||||
|
const visitRecordId = computed(() => query.value.visitRecordId)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
emit('view-type', 1)
|
emit('view-type', 1)
|
||||||
@@ -20,35 +27,55 @@
|
|||||||
|
|
||||||
const onLoad = () => {
|
const onLoad = () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
setTimeout(() => {
|
const http = visitRecordId.value ? getTryOnEffectFavoriteList : getTryOnEffectStyleList
|
||||||
for (var i = 0; i < 10; i++)
|
http(visitRecordId.value)
|
||||||
list.push({
|
.then((data) => {
|
||||||
id: list.length,
|
data?.forEach((v) => {
|
||||||
love: Math.random() > 0.5,
|
const obj = {
|
||||||
isAi: Math.random() > 0.5,
|
tryOnId: v.tryOnId,
|
||||||
|
tryOnUrl: v.tryOnUrl,
|
||||||
|
styleUrl: v.styleUrl,
|
||||||
|
isFavorite: !!v.isFavorite,
|
||||||
|
isRegenerated: !!v.isRegenerated,
|
||||||
|
|
||||||
selected: list.length < maxSelectCount,
|
selected: list.length < maxSelectCount,
|
||||||
loading: false,
|
loading: false,
|
||||||
downloaded: false
|
downloaded: false
|
||||||
|
}
|
||||||
|
list.push(obj)
|
||||||
})
|
})
|
||||||
loading.value = false
|
loading.value = false
|
||||||
if (list.length >= 30) {
|
|
||||||
finish.value = true
|
finish.value = true
|
||||||
}
|
})
|
||||||
}, 500)
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
loading.value = false
|
||||||
|
finish.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const onItem = (v) => {
|
const onItem = (v) => {
|
||||||
isChooseSave.value ? onSelectItem(v) : onDetailsItem(v)
|
isChooseSave.value ? onSelectItem(v) : onDetailsItem(v)
|
||||||
}
|
}
|
||||||
|
// 详情页
|
||||||
const onDetailsItem = (v) => {
|
const onDetailsItem = (v) => {
|
||||||
if (v.isAi) return
|
if (v.isRegenerated) return
|
||||||
console.log('详情', v)
|
router.push({ query: { ...query.value, styleUrl: v.styleUrl } })
|
||||||
router.push({ query: { did: v.id } })
|
|
||||||
}
|
}
|
||||||
|
// 喜欢
|
||||||
|
const isLoveLoading = ref(false)
|
||||||
const onLoveItem = (v) => {
|
const onLoveItem = (v) => {
|
||||||
// Outfit暂时不可以like
|
if (isLoveLoading.value) return
|
||||||
console.log('喜欢', v)
|
const http = v.isFavorite ? cancelTryOnEffectFavorite : setTryOnEffectFavorite
|
||||||
v.love = !v.love
|
isLoveLoading.value = true
|
||||||
|
v.isFavorite = !v.isFavorite
|
||||||
|
http(v.tryOnId)
|
||||||
|
.then(() => {
|
||||||
|
isLoveLoading.value = false
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
isLoveLoading.value = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const onDownloadItem = (v) => {
|
const onDownloadItem = (v) => {
|
||||||
// console.log('保存', v)
|
// console.log('保存', v)
|
||||||
@@ -56,8 +83,8 @@
|
|||||||
v.loading = true
|
v.loading = true
|
||||||
v.selected = false
|
v.selected = false
|
||||||
const obj = {
|
const obj = {
|
||||||
url: 'http://118.31.39.42:3000/falls/1.png',
|
url: v.tryOnUrl,
|
||||||
name: v.id + '.png'
|
name: v.tryOnUrl.split('/').pop()
|
||||||
}
|
}
|
||||||
DownloadImages([obj], null, null, () => {
|
DownloadImages([obj], null, null, () => {
|
||||||
v.loading = false
|
v.loading = false
|
||||||
@@ -74,6 +101,7 @@
|
|||||||
const onBackChooseSave = () => {
|
const onBackChooseSave = () => {
|
||||||
isChooseSave.value = false
|
isChooseSave.value = false
|
||||||
}
|
}
|
||||||
|
// 下载选中项
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
const downloadList = []
|
const downloadList = []
|
||||||
if (selectCount.value > 0) {
|
if (selectCount.value > 0) {
|
||||||
@@ -83,8 +111,8 @@
|
|||||||
v.loading = true
|
v.loading = true
|
||||||
downloadList.push({
|
downloadList.push({
|
||||||
index: i,
|
index: i,
|
||||||
url: 'http://118.31.39.42:3000/falls/1.png',
|
url: v.tryOnUrl,
|
||||||
name: i + 1 + '.png'
|
name: v.tryOnUrl.split('/').pop()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -124,14 +152,14 @@
|
|||||||
<div class="list">
|
<div class="list">
|
||||||
<my-list v-model:loading="loading" v-model:finish="finish" @load="onLoad">
|
<my-list v-model:loading="loading" v-model:finish="finish" @load="onLoad">
|
||||||
<div class="item" v-for="(v, i) in list" :key="i" @click="onItem(v)">
|
<div class="item" v-for="(v, i) in list" :key="i" @click="onItem(v)">
|
||||||
<img src="@/assets/images/workshop/posture/posture_1.png" />
|
<img :src="v.tryOnUrl" />
|
||||||
<div class="corner">
|
<div class="corner">
|
||||||
<div class="ai" v-if="v.isAi">Gen-AI</div>
|
<div class="ai" v-if="v.isRegenerated">Gen-AI</div>
|
||||||
<div class="tryon" v-else>Try-on</div>
|
<div class="tryon" v-else>Try-on</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="icons">
|
<div class="icons">
|
||||||
<div @click.stop="onLoveItem(v)">
|
<div @click.stop="onLoveItem(v)">
|
||||||
<SvgIcon :name="`love_${v.love ? '1' : '0'}`" size="27" />
|
<SvgIcon :name="`love_${v.isFavorite ? '1' : '0'}`" size="27" />
|
||||||
</div>
|
</div>
|
||||||
<div @click.stop="onDownloadItem(v)">
|
<div @click.stop="onDownloadItem(v)">
|
||||||
<SvgIcon name="download" size="27" v-show="!v.loading" />
|
<SvgIcon name="download" size="27" v-show="!v.loading" />
|
||||||
@@ -146,7 +174,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</my-list>
|
</my-list>
|
||||||
</div>
|
</div>
|
||||||
<div class="btns" v-show="!query.date">
|
<div class="btns" v-show="!visitRecordId">
|
||||||
<template v-if="!isChooseSave">
|
<template v-if="!isChooseSave">
|
||||||
<button @click="onChooseSave">Choose to Save</button>
|
<button @click="onChooseSave">Choose to Save</button>
|
||||||
<button @click="onContinue">Continue</button>
|
<button @click="onContinue">Continue</button>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const detailsID = computed(() => router.currentRoute.value.query.did);
|
const styleUrl = computed(() => router.currentRoute.value.query.styleUrl);
|
||||||
const emit = defineEmits(['view-type'])
|
const emit = defineEmits(['view-type'])
|
||||||
watch(
|
watch(
|
||||||
() => router.currentRoute.value,
|
() => router.currentRoute.value,
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header-title style-type="2" />
|
<header-title style-type="2" />
|
||||||
<creation-list v-show="!detailsID" />
|
<creation-list v-show="!styleUrl" />
|
||||||
<creation-details v-if="detailsID" />
|
<creation-details v-if="styleUrl" />
|
||||||
<footer-navigation is-placeholder />
|
<footer-navigation is-placeholder />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
import HeaderTitle from '@/components/HeaderTitle.vue'
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
import FooterNavigation from '@/components/FooterNavigation.vue'
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
import GenerateLoading from '@/views/asistant/components/GenerateLoading.vue'
|
import GenerateLoading from '@/views/asistant/components/GenerateLoading.vue'
|
||||||
import { ref,onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { setTryOnEffectFavorite, cancelTryOnEffectFavorite } from '@/api/workshop'
|
||||||
const emit = defineEmits(['viewType'])
|
const emit = defineEmits(['viewType'])
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -12,7 +13,7 @@
|
|||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}, 500);
|
}, 500)
|
||||||
const onSend = () => {
|
const onSend = () => {
|
||||||
if (inputText.value === '') return
|
if (inputText.value === '') return
|
||||||
const text = inputText.value
|
const text = inputText.value
|
||||||
@@ -75,7 +76,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.loading{
|
.loading {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 36.6rem;
|
margin-top: 36.6rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
import FooterNavigation from '@/components/FooterNavigation.vue'
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
import MyList from '@/components/myList.vue'
|
import MyList from '@/components/myList.vue'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
import { FormatDate } from '@/utils/tools'
|
||||||
|
import { getCustomerPhotos, deleteCustomerPhoto } from '@/api/workshop'
|
||||||
const emit = defineEmits(['view-type'])
|
const emit = defineEmits(['view-type'])
|
||||||
|
import { showConfirmDialog } from 'vant'
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
emit('view-type', 1)
|
emit('view-type', 1)
|
||||||
@@ -15,26 +18,50 @@
|
|||||||
|
|
||||||
const onLoad = () => {
|
const onLoad = () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
setTimeout(() => {
|
const customerId = '123123123'
|
||||||
for (var i = 0; i < 10; i++) {
|
getCustomerPhotos(customerId)
|
||||||
list.push({
|
.then((data) => {
|
||||||
id: list.length + 1,
|
data?.forEach((v) => {
|
||||||
userID: 10000000 + list.length,
|
const obj = {
|
||||||
datetime: '7/22/2025 18:20',
|
visitRecordId: v.visitRecordId,
|
||||||
lastopened: '18:20'
|
defaultImageUrl: v.defaultImageUrl,
|
||||||
|
datetime: FormatDate(v.visitTime, 'dd-MM-yyyy HH:mm'),
|
||||||
|
lastopened: FormatDate(v.visitTime, 'HH:mm')
|
||||||
|
}
|
||||||
|
list.push(obj)
|
||||||
|
})
|
||||||
|
loading.value = false
|
||||||
|
finish.value = true
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
loading.value = false
|
||||||
|
finish.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
loading.value = false
|
// 删除项
|
||||||
if (list.length >= 50) finish.value = true
|
const deleteItem = async (obj: any, i: number) => {
|
||||||
}, 500)
|
const res = await showConfirmDialog({
|
||||||
|
title: 'Delete',
|
||||||
|
message: 'Are you sure you want to delete this item?',
|
||||||
|
confirmButtonText: 'Yes',
|
||||||
|
cancelButtonText: 'Cancel'
|
||||||
|
}).catch(() => 0)
|
||||||
|
if (res === 0) return
|
||||||
|
console.log(obj,i)
|
||||||
|
deleteCustomerPhoto(obj.visitRecordId)
|
||||||
|
.then(() => {
|
||||||
|
list.splice(i, 1)
|
||||||
|
console.log('删除成功')
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
// 详情项
|
||||||
const onDetailsItem = (v) => {
|
const onDetailsItem = (v) => {
|
||||||
// console.log('检索' + i)
|
// console.log('检索' + i)
|
||||||
router.push({ name: 'creation', query: { date: v.datetime } })
|
router.push({ name: 'creation', query: { visitRecordId: v.visitRecordId } })
|
||||||
}
|
|
||||||
|
|
||||||
const deleteItem = (i: number) => {
|
|
||||||
list.splice(i, 1)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -44,9 +71,9 @@
|
|||||||
<div class="title">Library</div>
|
<div class="title">Library</div>
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<my-list v-model:loading="loading" v-model:finish="finish" @load="onLoad">
|
<my-list v-model:loading="loading" v-model:finish="finish" @load="onLoad">
|
||||||
<div class="item" v-for="(v, i) in list" :key="v.id">
|
<div class="item" v-for="(v, i) in list" :key="v.visitRecordId">
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img src="@/assets/images/workshop/posture/posture_1.png" />
|
<img :src="v.defaultImageUrl" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!-- <span class="userID">User ID: {{ v.userID }}</span> -->
|
<!-- <span class="userID">User ID: {{ v.userID }}</span> -->
|
||||||
@@ -54,7 +81,7 @@
|
|||||||
<span class="lastopened">Last opened {{ v.lastopened }}</span>
|
<span class="lastopened">Last opened {{ v.lastopened }}</span>
|
||||||
<button @click="onDetailsItem(v)">Details</button>
|
<button @click="onDetailsItem(v)">Details</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="delete" @click="deleteItem(i)"><SvgIcon name="delete2" size="30" /></div>
|
<div class="delete" @click="deleteItem(v, i)"><SvgIcon name="delete2" size="30" /></div>
|
||||||
</div>
|
</div>
|
||||||
</my-list>
|
</my-list>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
if (!form[item]) return
|
if (!form[item]) return
|
||||||
form[item].edit = false
|
form[item].edit = false
|
||||||
}
|
}
|
||||||
const logout = () => {}
|
const logout = () => {
|
||||||
|
router.push({ path: '/' })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -39,7 +41,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="profile">
|
<div class="profile">
|
||||||
<div class="edit"><SvgIcon name="edit" size="37" /></div>
|
<!-- <div class="edit"><SvgIcon name="edit" size="37" /></div> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="title">Momo Fashion</div>
|
<div class="title">Momo Fashion</div>
|
||||||
<p class="sub">Fashion Design</p>
|
<p class="sub">Fashion Design</p>
|
||||||
@@ -53,12 +55,12 @@
|
|||||||
v-model="form.name.value"
|
v-model="form.name.value"
|
||||||
:readonly="!form.name.edit"
|
:readonly="!form.name.edit"
|
||||||
/>
|
/>
|
||||||
<div class="icon" v-if="form.name.edit" @click.stop="onSaveItem('name')">
|
<!-- <div class="icon" v-if="form.name.edit" @click.stop="onSaveItem('name')">
|
||||||
<SvgIcon name="confirmation" size="37" />
|
<SvgIcon name="confirmation" size="37" />
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" v-else @click="onEditItem('name')">
|
<div class="icon" v-else @click="onEditItem('name')">
|
||||||
<SvgIcon name="edit" size="37" />
|
<SvgIcon name="edit" size="37" />
|
||||||
</div>
|
</div> -->
|
||||||
</label>
|
</label>
|
||||||
<p class="error" v-show="form.name.msg">{{ form.name.msg }}</p>
|
<p class="error" v-show="form.name.msg">{{ form.name.msg }}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,12 +75,12 @@
|
|||||||
:readonly="!form.email.edit"
|
:readonly="!form.email.edit"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<div class="icon" v-if="form.email.edit" @click.stop="onSaveItem('email')">
|
<!-- <div class="icon" v-if="form.email.edit" @click.stop="onSaveItem('email')">
|
||||||
<SvgIcon name="confirmation" size="37" />
|
<SvgIcon name="confirmation" size="37" />
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" v-else @click="onEditItem('email')">
|
<div class="icon" v-else @click="onEditItem('email')">
|
||||||
<SvgIcon name="edit" size="37" />
|
<SvgIcon name="edit" size="37" />
|
||||||
</div>
|
</div> -->
|
||||||
</label>
|
</label>
|
||||||
<p class="error" v-show="form.email.msg">{{ form.email.msg }}</p>
|
<p class="error" v-show="form.email.msg">{{ form.email.msg }}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,12 +96,12 @@
|
|||||||
v-model="form.password.value"
|
v-model="form.password.value"
|
||||||
:readonly="!form.password.edit"
|
:readonly="!form.password.edit"
|
||||||
/>
|
/>
|
||||||
<div class="icon" v-if="form.password.edit" @click.stop="onSaveItem('password')">
|
<!-- <div class="icon" v-if="form.password.edit" @click.stop="onSaveItem('password')">
|
||||||
<SvgIcon name="confirmation" size="37" />
|
<SvgIcon name="confirmation" size="37" />
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" v-else @click="onEditItem('password')">
|
<div class="icon" v-else @click="onEditItem('password')">
|
||||||
<SvgIcon name="edit" size="37" />
|
<SvgIcon name="edit" size="37" />
|
||||||
</div>
|
</div> -->
|
||||||
</label>
|
</label>
|
||||||
<p class="error" v-show="form.password.msg">{{ form.password.msg }}</p>
|
<p class="error" v-show="form.password.msg">{{ form.password.msg }}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,8 +178,16 @@
|
|||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 2.5rem;
|
||||||
|
> * {
|
||||||
|
margin-right: 2.5rem;
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
> .icon {
|
> .icon {
|
||||||
margin: 0 2.5rem;
|
// margin: 0 2.5rem;
|
||||||
--svg-icon-color: #ababab;
|
--svg-icon-color: #ababab;
|
||||||
}
|
}
|
||||||
> input {
|
> input {
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import HeaderTitle from '@/components/HeaderTitle.vue'
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
import FooterNavigation from '@/components/FooterNavigation.vue'
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
import { uploadCustomerPhoto } from '@/api/workshop'
|
||||||
const emit = defineEmits(['view-type'])
|
const emit = defineEmits(['view-type'])
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
emit('view-type', 1)
|
emit('view-type', 1)
|
||||||
})
|
})
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const faceUrl = ref('')
|
const fileData = reactive({
|
||||||
|
url:"",
|
||||||
|
file: null,
|
||||||
|
});
|
||||||
|
console.log(fileData)
|
||||||
// 上传照片
|
// 上传照片
|
||||||
const handleUploadFace = () => {
|
const handleUploadFace = () => {
|
||||||
const input = document.createElement('input')
|
const input = document.createElement('input')
|
||||||
@@ -19,17 +24,28 @@
|
|||||||
input.onchange = (e: any) => {
|
input.onchange = (e: any) => {
|
||||||
const file = e.target.files[0]
|
const file = e.target.files[0]
|
||||||
if (!file) return
|
if (!file) return
|
||||||
const reader = new FileReader()
|
const url = URL.createObjectURL(file)
|
||||||
reader.readAsDataURL(file)
|
fileData.url = url
|
||||||
reader.onload = () => {
|
fileData.file = file
|
||||||
faceUrl.value = reader.result as string
|
// const reader = new FileReader()
|
||||||
}
|
// reader.readAsDataURL(file)
|
||||||
|
// reader.onload = () => {
|
||||||
|
// faceUrl.value = reader.result as string
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 生成照片
|
// 生成照片
|
||||||
const handleGenerate = () => {
|
const handleGenerate = () => {
|
||||||
console.log('生成照片')
|
console.log('生成照片')
|
||||||
router.push({ name: 'customize' })
|
if (!fileData.file) return
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('customerId', "1")
|
||||||
|
formData.append('visitRecordId', "1")
|
||||||
|
formData.append('file', fileData.file)
|
||||||
|
uploadCustomerPhoto(formData).then(res => {
|
||||||
|
console.log(res)
|
||||||
|
// router.push({ name: 'customize' })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -44,11 +60,11 @@
|
|||||||
to Try-on
|
to Try-on
|
||||||
</div>
|
</div>
|
||||||
<!-- 照片 -->
|
<!-- 照片 -->
|
||||||
<div class="picture" v-if="faceUrl">
|
<div class="picture" v-if="fileData.url">
|
||||||
<img :src="faceUrl" />
|
<img :src="fileData.url" />
|
||||||
</div>
|
</div>
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<template v-if="faceUrl">
|
<template v-if="fileData.url">
|
||||||
<button class="sandblasted-blurred" @click="handleUploadFace"><span>Re-try</span></button>
|
<button class="sandblasted-blurred" @click="handleUploadFace"><span>Re-try</span></button>
|
||||||
<button class="sandblasted-blurred" @click="handleGenerate"><span>Generate</span></button>
|
<button class="sandblasted-blurred" @click="handleGenerate"><span>Generate</span></button>
|
||||||
</template>
|
</template>
|
||||||
@@ -108,7 +124,7 @@
|
|||||||
height: 79.2rem;
|
height: 79.2rem;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
border: 0.2rem solid #d9d9d9;
|
border: 0.2rem solid #d9d9d9;
|
||||||
object-fit: contain;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .btns {
|
> .btns {
|
||||||
|
|||||||
Reference in New Issue
Block a user