forked from natuka/web.puabadge.com
单图徽章代码提交
This commit is contained in:
1 parent
754b6f3834
commit
96f5bcec51
20 files changed
+1186
-672
No files matched your search
@@ -1,329 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from '@vue/runtime-dom'
|
||||
import type { PropType } from '@vue/runtime-dom'
|
||||
|
||||
interface Style {
|
||||
width?: string
|
||||
height?: string
|
||||
top?: string
|
||||
left?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
const tabHeight = 70
|
||||
export default defineComponent({
|
||||
name: 'Cropper',
|
||||
props: {
|
||||
avatarSrc: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
avatarStyle: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
selWidth: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
selHeight: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
expWidth: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
expHeight: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
minScale: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
maxScale: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
canScale: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
noTab: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
quality: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
index: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cvsStyleHeight: '0px',
|
||||
styleDisplay: 'none',
|
||||
styleTop: '-10000px',
|
||||
prvTop: '-10000px',
|
||||
imgStyle: {} as Style,
|
||||
selStyle: {} as Style,
|
||||
showOper: true,
|
||||
imgSrc: {
|
||||
imgSrc: '',
|
||||
},
|
||||
qlty: 0.9,
|
||||
postWidthFirst: {},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
avatarSrc() {
|
||||
this.imgSrc.imgSrc = this.avatarSrc
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const canvas = document.getElementById('avatar-canvas')
|
||||
const operCanvas = document.getElementById('oper-canvas')
|
||||
this.ctxCanvas = canvas.getContext('2d')
|
||||
this.ctxCanvasOper = operCanvas.getContext('2d')
|
||||
|
||||
this.qlty = parseInt(this.quality) || 0.9
|
||||
this.imgSrc.imgSrc = this.avatarSrc
|
||||
this.letScale = this.canScale === 'false' ? 0 : 1
|
||||
this.indx = this.index || undefined
|
||||
this.mnScale = this.minScale || 0.3
|
||||
this.mxScale = this.maxScale || 4
|
||||
this.noBar = this.noTab === 'true' ? 1 : 0
|
||||
if (this.noBar) {
|
||||
this.moreHeight = 0
|
||||
this.fWindowResize()
|
||||
} else {
|
||||
this.moreHeight = 50
|
||||
this.fWindowResize()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fWindowResize() {
|
||||
const sysInfo = {
|
||||
platform: navigator.platform,
|
||||
pixelRatio: window.devicePixelRatio,
|
||||
windowWidth: window.innerWidth,
|
||||
windowHeight: window.innerHeight,
|
||||
windowTop: window.scrollY,
|
||||
windowBottom: 0,
|
||||
statusBarHeight: 0,
|
||||
screenHeight: screen.height,
|
||||
}
|
||||
|
||||
this.platform = sysInfo.platform
|
||||
this.pixelRatio = sysInfo.pixelRatio
|
||||
this.windowWidth = sysInfo.windowWidth
|
||||
this.drawTop = sysInfo.windowTop
|
||||
this.windowHeight = sysInfo.windowHeight + sysInfo.windowBottom
|
||||
this.cvsStyleHeight = `${this.windowHeight - tabHeight}px`
|
||||
|
||||
this.pxRatio = this.windowWidth / 750
|
||||
|
||||
const style = this.avatarStyle
|
||||
console.log(style)
|
||||
this.imgStyle = style
|
||||
this.expWidth && (this.exportWidth = this.expWidth.includes('rpx')
|
||||
? parseInt(this.expWidth) * this.pxRatio
|
||||
: parseInt(this.expWidth))
|
||||
this.expHeight && (this.exportHeight = this.expHeight.includes('rpx')
|
||||
? parseInt(this.expHeight) * this.pxRatio
|
||||
: parseInt(this.expHeight))
|
||||
|
||||
if (this.styleDisplay === 'flex')
|
||||
this.fDrawInit(true)
|
||||
|
||||
this.fHideImg()
|
||||
},
|
||||
fSelect() {
|
||||
if (this.fSelecting)
|
||||
return
|
||||
this.fSelecting = true
|
||||
setTimeout(() => {
|
||||
this.fSelecting = false
|
||||
}, 500)
|
||||
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = 'image/*'
|
||||
input.onchange = (e) => {
|
||||
const file = e.target.files[0]
|
||||
if (!file)
|
||||
return
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.onload = (e) => {
|
||||
const path = e.target.result
|
||||
this.imgPath = path
|
||||
|
||||
const img = new Image()
|
||||
img.onload = () => {
|
||||
this.imgWidth = img.width
|
||||
this.imgHeight = img.height
|
||||
this.path = path
|
||||
|
||||
if (!this.hasSel) {
|
||||
const style = this.selStyle || {}
|
||||
if (this.selWidth && this.selHeight) {
|
||||
const selWidth = this.selWidth.includes('rpx')
|
||||
? parseInt(this.selWidth) * this.pxRatio
|
||||
: parseInt(this.selWidth)
|
||||
const selHeight = this.selHeight.includes('rpx')
|
||||
? parseInt(this.selHeight) * this.pxRatio
|
||||
: parseInt(this.selHeight)
|
||||
style.width = `${parseInt(selWidth)}px`
|
||||
style.height = `${parseInt(selHeight)}px`
|
||||
style.top = `${parseInt((this.windowHeight - parseInt(style.height) - tabHeight) / 2)}px`
|
||||
style.left = `${parseInt((this.windowWidth - parseInt(style.width)) / 2)}px`
|
||||
} else {
|
||||
alert('裁剪框的宽或高没有设置')
|
||||
return
|
||||
}
|
||||
this.selStyle = style
|
||||
}
|
||||
|
||||
this.fDrawInit(true)
|
||||
}
|
||||
img.src = path
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
input.click()
|
||||
},
|
||||
fUpload() {
|
||||
if (this.fUploading)
|
||||
return
|
||||
this.fUploading = true
|
||||
setTimeout(() => {
|
||||
this.fUploading = false
|
||||
}, 1000)
|
||||
|
||||
const style = this.selStyle
|
||||
let x = parseInt(style.left)
|
||||
let y = parseInt(style.top)
|
||||
const width = parseInt(style.width)
|
||||
const height = parseInt(style.height)
|
||||
let expWidth = this.exportWidth || width
|
||||
let expHeight = this.exportHeight || height
|
||||
|
||||
x *= this.pixelRatio
|
||||
y *= this.pixelRatio
|
||||
expWidth = width
|
||||
expHeight = height
|
||||
|
||||
this.styleDisplay = 'none'
|
||||
this.styleTop = '-10000px'
|
||||
this.hasSel = false
|
||||
this.fHideImg()
|
||||
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.drawImage(this.ctxCanvas.canvas, x, y, width, height, 0, 0, expWidth, expHeight)
|
||||
|
||||
canvas.toBlob((blob) => {
|
||||
const url = URL.createObjectURL(blob)
|
||||
this.$emit('upload', {
|
||||
avatar: this.imgSrc,
|
||||
path: url,
|
||||
index: this.indx,
|
||||
})
|
||||
}, 'image/png', this.qlty)
|
||||
},
|
||||
// ... 其他方法保持不变
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template name="cropper">
|
||||
<view>
|
||||
<image :src="imgSrc.imgSrc" class="my-avatar" mode="aspectFill" :style="imgStyle" @click="fSelect" />
|
||||
<!-- 上传图片 -->
|
||||
<canvas
|
||||
id="avatar-canvas" canvas-id="avatar-canvas" class="my-canvas" :style="{ top: styleTop, height: cvsStyleHeight }"
|
||||
disable-scroll="false"
|
||||
/>
|
||||
<!-- 截取边框 -->
|
||||
<canvas
|
||||
id="oper-canvas" canvas-id="oper-canvas" class="oper-canvas" :style="{ top: styleTop, height: cvsStyleHeight }"
|
||||
disable-scroll="false" @touchstart="fStart" @touchmove="fMove" @touchend="fEnd"
|
||||
/>
|
||||
<view class="oper-wrapper" :style="{ display: styleDisplay }">
|
||||
<view v-if="showOper" class="btn-wrapper">
|
||||
<view hover-class="hover" @click="fClose">
|
||||
取消
|
||||
</view>
|
||||
<view hover-class="hover" @click="fUpload">
|
||||
选取
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.my-canvas {
|
||||
display: flex;
|
||||
position: fixed !important;
|
||||
background: #000000;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.my-avatar {
|
||||
width: 100vw;
|
||||
height: 100vw;
|
||||
}
|
||||
|
||||
.oper-canvas {
|
||||
display: flex;
|
||||
position: fixed !important;
|
||||
left: 0;
|
||||
z-index: 101;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.oper-wrapper {
|
||||
height: 71px;
|
||||
position: fixed !important;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 200;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.btn-wrapper {
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-wrapper view {
|
||||
width: 160rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
z-index: 300;
|
||||
}
|
||||
|
||||
.hover {
|
||||
color: #f1f1f1;
|
||||
}
|
||||
</style>
|
||||
+133
-44
@@ -1,19 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import H5Cropper from 'vue-cropper-h5'
|
||||
import "vue-cropper-h5/dist/style.css"
|
||||
import * as badgeApi from '@/api/badge'
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const show = ref(false)
|
||||
const imgShow = ref(false)
|
||||
const router = useRouter()
|
||||
const imgurl = ref('') // 头像地址
|
||||
const fileInput = ref<HTMLInputElement | null>(null)
|
||||
function onUploadClick() {
|
||||
if (fileInput.value)
|
||||
fileInput.value.click()
|
||||
}
|
||||
function myUpload(rsp) {
|
||||
const self = this
|
||||
self.imgurl = rsp.path // 更新头像方式一
|
||||
}
|
||||
const option = ref({})
|
||||
const options = ref({})
|
||||
const imgurl = ref('')
|
||||
const imgBgUrl = ref('')
|
||||
const isBgShow = ref(true)
|
||||
function goToRecord() {
|
||||
router.push('/badge/record')
|
||||
}
|
||||
@@ -23,7 +22,59 @@ function goToMyOrder() {
|
||||
function goToPreview() {
|
||||
router.push('/badge/preview')
|
||||
}
|
||||
function onFileChange
|
||||
function getbase64Data(data) {
|
||||
imgurl.value = data;
|
||||
console.log('图片地址', data)
|
||||
}
|
||||
function getBgbase64Data(data) {
|
||||
imgBgUrl.value = data;
|
||||
console.log('背景图片地址', data)
|
||||
}
|
||||
const getKindList = () => {
|
||||
badgeApi.getKindList({
|
||||
page: 1,
|
||||
size: 20,
|
||||
scale: 20,
|
||||
}).then((res: any) => {
|
||||
const data = res || []
|
||||
}).catch((err) => {
|
||||
|
||||
}).finally((err) => {
|
||||
|
||||
})
|
||||
}
|
||||
const getSundryList = () => {
|
||||
badgeApi.getSundryList({
|
||||
page: 1,
|
||||
size: 6,
|
||||
group: 'gp',
|
||||
}).then((res: any) => {
|
||||
const data = res || []
|
||||
}).catch((err) => {
|
||||
|
||||
}).finally((err) => {
|
||||
|
||||
})
|
||||
}
|
||||
const getList = () => {
|
||||
badgeApi.getSundryList({
|
||||
page: 1,
|
||||
size: 5,
|
||||
group: 'case',
|
||||
ids: '6,7,8,9,19'
|
||||
}).then((res: any) => {
|
||||
const data = res || []
|
||||
}).catch((err) => {
|
||||
|
||||
}).finally((err) => {
|
||||
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
getKindList()
|
||||
getSundryList()
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -98,31 +149,30 @@ function onFileChange
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="photo-upload-box">
|
||||
<div class="photo-upload-header" @click="imgShow = true">
|
||||
<van-icon name="question-o" size="16px" class="photo-upload-guide-icon" />
|
||||
<span class="photo-upload-guide-text">图片上传指南</span>
|
||||
</div>
|
||||
<div class="photo-upload-area" @click="onUploadClick">
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
style="display: none"
|
||||
@change="onFileChange"
|
||||
>
|
||||
<div class="photo-upload-plus">
|
||||
+
|
||||
<div class="photo-upload-body">
|
||||
<div v-if="!imgurl" class="photo-upload-box">
|
||||
<div class="photo-upload-header" @click="imgShow = true">
|
||||
<van-icon name="question-o" size="16px" class="photo-upload-guide-icon" />
|
||||
<span class="photo-upload-guide-text">图片上传指南</span>
|
||||
</div>
|
||||
<div class="photo-upload-text">
|
||||
点击上传照片
|
||||
<div class="photo-upload-area">
|
||||
<div class="photo-upload-plus">
|
||||
+
|
||||
</div>
|
||||
<div class="photo-upload-text">
|
||||
点击上传照片
|
||||
</div>
|
||||
<div class="photo-upload-tip">
|
||||
*上传照片时建议勾选[原图]
|
||||
</div>
|
||||
</div>
|
||||
<div class="photo-upload-tip">
|
||||
*上传照片时建议勾选[原图]
|
||||
<div class="photo-upload-footer">
|
||||
请确定您对上传的照片拥有合法使用权利或已取得他人合法授权,且同意本平台分析图片信息以提供生成服务
|
||||
</div>
|
||||
</div>
|
||||
<div class="photo-upload-footer">
|
||||
请确定您对上传的照片拥有合法使用权利或已取得他人合法授权,且同意本平台分析图片信息以提供生成服务
|
||||
<img class="photo-upload-img" v-if="imgurl" :src="imgurl" alt="" srcset="">
|
||||
<div class="photo-upload-box-1">
|
||||
<h5-cropper :option="option" @getbase64Data="getbase64Data"></h5-cropper>
|
||||
</div>
|
||||
</div>
|
||||
<div class="style-section">
|
||||
@@ -198,38 +248,40 @@ function onFileChange
|
||||
</div>
|
||||
<div class="bg-style-tabs">
|
||||
<button
|
||||
class="bg-style-tab active"
|
||||
type="button"
|
||||
class="bg-style-tab" :class="isBgShow == true ? 'active' : ''"
|
||||
type="button" @click="isBgShow = true"
|
||||
>
|
||||
照片原图背景
|
||||
</button>
|
||||
<button
|
||||
class="bg-style-tab"
|
||||
type="button"
|
||||
disabled
|
||||
class="bg-style-tab" :class="isBgShow == false ? 'active' : ''"
|
||||
type="button" @click="isBgShow = false"
|
||||
>
|
||||
补充背景照片
|
||||
</button>
|
||||
</div>
|
||||
<div class="bg-style-tip">
|
||||
<div v-if="isBgShow == true" class="bg-style-tip">
|
||||
选择该选项设计的徽章会根据上传的肖像照片背景进行生成效果
|
||||
</div>
|
||||
<div class="bg-style-tip">
|
||||
<div v-if="isBgShow == false" class="bg-style-tip">
|
||||
选择该选项需要额外上传一张照片作为背景
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-photo-upload-section">
|
||||
<div class="bg-photo-upload-section" v-if="isBgShow == false">
|
||||
<div class="bg-photo-upload-header">
|
||||
<span>补充背景照片</span>
|
||||
</div>
|
||||
<div class="bg-photo-upload-area">
|
||||
<label class="bg-photo-upload-label">
|
||||
<input type="file" accept="image/*" style="display:none">
|
||||
<div v-if="!imgBgUrl" class="bg-photo-upload-label">
|
||||
<div class="bg-photo-upload-box">
|
||||
<div class="bg-photo-upload-plus">+</div>
|
||||
<div class="bg-photo-upload-text">上传照片</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<img v-if="imgBgUrl" class="bg-photo-upload-img" :src="imgBgUrl" alt="">
|
||||
<div class="bg-photo-upload-label-1">
|
||||
<h5-cropper :option="options" @getbase64Data="getBgbase64Data"></h5-cropper>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 90px;" />
|
||||
@@ -477,6 +529,12 @@ function onFileChange
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.photo-upload-body {
|
||||
position: relative;
|
||||
width: 80vw;
|
||||
height: 80vw;
|
||||
margin: 16px auto 0 auto;
|
||||
}
|
||||
.photo-upload-box {
|
||||
margin: 16px auto 0 auto;
|
||||
width: 80vw;
|
||||
@@ -489,6 +547,22 @@ function onFileChange
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.photo-upload-box-1 {
|
||||
width: 80vw;
|
||||
height: 70vw;
|
||||
border-radius: 12px;
|
||||
/* background: #F0F2F5; */
|
||||
background: rgba(0, 0, 0, 0);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.photo-upload-img {
|
||||
width: 80vw;
|
||||
height: 80vw;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.photo-upload-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -687,10 +761,20 @@ function onFileChange
|
||||
.bg-photo-upload-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
.bg-photo-upload-label {
|
||||
display: inline-block;
|
||||
}
|
||||
.bg-photo-upload-label-1 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background: none;
|
||||
}
|
||||
.bg-photo-upload-box {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
@@ -704,6 +788,11 @@ function onFileChange
|
||||
background: #fafafa;
|
||||
transition: border 0.2s;
|
||||
}
|
||||
.bg-photo-upload-img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.bg-photo-upload-plus {
|
||||
font-size: 32px;
|
||||
color: #b0b0b0;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="my-order">
|
||||
<div class="header" @click="goBack">
|
||||
<span class="back-icon"><van-icon name="arrow-left" size="16px" /> 返回</span>
|
||||
<span class="back-icon"><van-icon name="arrow-left" size="16px" color="#333" /> 我的订单</span>
|
||||
</div>
|
||||
<div class="order-list">
|
||||
<div class="order-item" @click="OrderDetail">
|
||||
<div class="order-item" @click="OrderDetail(item.id)" v-for="item in orders" :key="item.id">
|
||||
<img class="order-img" src="@/assets/badge/suiji.png" alt="order1" />
|
||||
<span class="order-status status-processing">生产中</span>
|
||||
</div>
|
||||
@@ -16,13 +16,48 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouter } from 'vue-router'
|
||||
import * as badgeApi from '@/api/badge'
|
||||
import { onMounted, ref } from 'vue'
|
||||
const page = ref(1)
|
||||
const loading = ref(false)
|
||||
const finished = ref(false)
|
||||
const orders = ref([])
|
||||
onMounted(() => {
|
||||
getOrder()
|
||||
})
|
||||
function getOrder() {
|
||||
if(loading.value) return
|
||||
loading.value = true
|
||||
badgeApi.getMyOrder({
|
||||
page: page.value,
|
||||
pageSize: 10,
|
||||
}).then(res => {
|
||||
if(page.value === 1) {
|
||||
orders.value = res.data.list
|
||||
} else {
|
||||
orders.value.push(...res.data.list)
|
||||
}
|
||||
if(res.data.list.length < 10) {
|
||||
finished.value = true
|
||||
} else {
|
||||
page.value++
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
const router = useRouter();
|
||||
function goBack() {
|
||||
router.push('/badge');
|
||||
}
|
||||
function OrderDetail() {
|
||||
router.push('/badge/orderDetail')
|
||||
function OrderDetail(id: number) {
|
||||
router.push({
|
||||
path: '/badge/orderDetail',
|
||||
query: {
|
||||
id: id,
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="my-order">
|
||||
<div class="header" @click="goBack">
|
||||
<span class="back-icon"><van-icon name="arrow-left" size="16px" /> 返回</span>
|
||||
<span class="back-icon"><van-icon name="arrow-left" size="16px" color="#333" /> 订单详情</span>
|
||||
</div>
|
||||
<div class="order-status">
|
||||
<div class="avatar-wrapper">
|
||||
@@ -68,8 +68,24 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import * as badgeApi from '@/api/badge';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
const route = useRoute();
|
||||
const order = ref({})
|
||||
const id = ref(0)
|
||||
onMounted(() => {
|
||||
id.value = route.query.id
|
||||
getOrderDetail()
|
||||
})
|
||||
function getOrderDetail() {
|
||||
badgeApi.getOrderDetail({
|
||||
id: id.value,
|
||||
}).then(res => {
|
||||
order.value = res.data
|
||||
})
|
||||
}
|
||||
const router = useRouter();
|
||||
function goBack() {
|
||||
router.push('/badge/myOrder');
|
||||
|
||||
+278
-17
@@ -20,13 +20,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-section">
|
||||
<div v-if="!imageUrl" class="progress-section">
|
||||
<div class="progress-bar-bg">
|
||||
<div class="progress-bar-fg" :style="{ width: '12%' }"></div>
|
||||
<div class="progress-bar-fg" :style="{ width: progress + '%' }"></div>
|
||||
</div>
|
||||
<div class="progress-text">照片数据分析中 12%</div>
|
||||
<div class="progress-text">照片数据分析中 {{progress}}%</div>
|
||||
<div class="progress-desc">总计大约需要60秒,请耐心等待...</div>
|
||||
</div>
|
||||
<div v-else class="progress-section">
|
||||
<img class="progress-section-img" :src="imageUrl" alt="">
|
||||
</div>
|
||||
<div class="info-section">
|
||||
<div class="info-item">
|
||||
<div class="info-title">芯比风格</div>
|
||||
@@ -54,40 +57,230 @@
|
||||
<span class="order-size">4cm</span>
|
||||
<span class="order-free">(剩余兑换:1)</span>
|
||||
<div class="order-ctrl">
|
||||
<button class="order-btn" disabled>-</button>
|
||||
<span class="order-count">1</span>
|
||||
<button class="order-btn">+</button>
|
||||
<van-stepper v-model="value" @change="changeValue" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-item">
|
||||
<span class="order-size">5cm</span>
|
||||
<span class="order-free">(剩余兑换:2)</span>
|
||||
<div class="order-ctrl">
|
||||
<button class="order-btn" disabled>-</button>
|
||||
<span class="order-count">1</span>
|
||||
<button class="order-btn">+</button>
|
||||
<van-stepper v-model="value" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="confirm-box">
|
||||
<div class="action-section">
|
||||
<button class="action-btn"><img class="action-img" src="@/assets/badge/reload.png" alt=""> 再次生成</button>
|
||||
<button class="action-btn"><img class="action-img" src="@/assets/badge/duibi.png" alt=""> 前后对比</button>
|
||||
<button class="action-btn"><img class="action-img" src="@/assets/badge/down.png" alt=""> 保存图片</button>
|
||||
<button @click="showReload = true" class="action-btn"><img class="action-img" src="@/assets/badge/reload.png" alt=""> 再次生成</button>
|
||||
<button @click="compare" :disabled="flag < 2" class="action-btn"><img class="action-img" src="@/assets/badge/duibi.png" alt=""> 前后对比</button>
|
||||
<button @click="save" :disabled="flag < 2" class="action-btn"><img class="action-img" src="@/assets/badge/down.png" alt=""> 保存图片</button>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<button class="confirm-btn">确认选择</button>
|
||||
<button @click="confirm" :disabled="flag < 2" class="confirm-btn">确认选择</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<van-action-sheet v-model:show="showReload" title="风格样式选择" :close-on-click-overlay="true" closeable>
|
||||
<div class="style-selection">
|
||||
<div class="style-grid">
|
||||
<div class="style-item" :class="{'active': style == 'suiji'}" @click="changeStyle('suiji')">
|
||||
<img src="@/assets/badge/suiji.png" alt="随机风格盲盒" class="style-img">
|
||||
<div class="style-label">随机风格盲盒</div>
|
||||
<span class="style-selected" v-if="style == 'suiji'" style="display: inline-block;">
|
||||
<van-icon name="checked" color="#50cf54" size="21px" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="style-item" :class="{'active': style == 'qban'}" @click="changeStyle('qban')">
|
||||
<img src="@/assets/badge/suiji.png" alt="Q版国风动漫" class="style-img">
|
||||
<div class="style-label">Q版国风动漫</div>
|
||||
<span class="style-selected" v-if="style == 'qban'">
|
||||
<van-icon name="checked" color="#50cf54" size="21px" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="style-item" :class="{'active': style == 'qkant'}" @click="changeStyle('qkant')">
|
||||
<img src="@/assets/badge/suiji.png" alt="Q版卡通" class="style-img">
|
||||
<div class="style-label">Q版卡通</div>
|
||||
<span class="style-selected" v-if="style == 'qkant'">
|
||||
<van-icon name="checked" color="#50cf54" size="21px" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="style-item" :class="{'active': style == 'babifeng'}" @click="changeStyle('babifeng')">
|
||||
<img src="@/assets/badge/suiji.png" alt="芭比风" class="style-img">
|
||||
<div class="style-label">芭比风</div>
|
||||
<span class="style-selected" v-if="style == 'babifeng'">
|
||||
<van-icon name="checked" color="#50cf54" size="21px" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="style-item">
|
||||
<img src="@/assets/badge/suiji.png" alt="迪士尼皮克斯" class="style-img">
|
||||
<div class="style-label">迪士尼皮克斯</div>
|
||||
</div>
|
||||
<div class="style-item">
|
||||
<img src="@/assets/badge/suiji.png" alt="写实肖像" class="style-img">
|
||||
<div class="style-label">写实肖像</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="confirm-wrapper">
|
||||
<button class="confirm-button">
|
||||
确认再次生成
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
<van-action-sheet v-model:show="showCompare" title="前后对比" :close-on-click-overlay="true" closeable>
|
||||
<div style="padding: 16px;">
|
||||
<div style="display: flex; align-items: center; justify-content: center; gap: 20px;">
|
||||
<div style="text-align: center;">
|
||||
<img src="@/assets/badge/suiji.png" alt="随机风格盲盒" style="width: 120px; height: 120px; border-radius: 8px;">
|
||||
</div>
|
||||
<div style="font-size: 24px; color: #333;">
|
||||
<van-icon name="arrow" size="20px" />
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<img src="@/assets/badge/suiji.png" alt="随机风格盲盒" style="width: 120px; height: 120px; border-radius: 8px;">
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: center; margin-top: 16px; color: #999; font-size: 12px;">
|
||||
温馨提示:<br/>
|
||||
AI设计的徽章效果图是根据用户提供的照片机器学习生成的,<br/>
|
||||
多试几次就能找到你满意的徽章~
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
|
||||
<van-action-sheet v-model:show="showBgCompare" title="前后对比" :close-on-click-overlay="true" closeable>
|
||||
<div style="padding: 16px;">
|
||||
<div style="display: flex; align-items: center; justify-content: center; gap: 20px;">
|
||||
<div style="text-align: center;">
|
||||
<img src="@/assets/badge/suiji.png" alt="背景对比图" style="width: 120px; height: 120px; border-radius: 8px;">
|
||||
</div>
|
||||
<div style="font-size: 24px; color: #333;">
|
||||
<van-icon name="plus" size="20px" />
|
||||
</div>
|
||||
<div style="text-align: center;">
|
||||
<img src="@/assets/badge/suiji.png" alt="背景对比图" style="width: 120px; height: 120px; border-radius: 8px;">
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size: 24px; color: #333;display: flex; align-items: center; justify-content: center; margin: 16px 0;">
|
||||
<van-icon name="arrow-down" size="20px" />
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; justify-content: center; gap: 20px;">
|
||||
<div style="text-align: center;">
|
||||
<img src="@/assets/badge/suiji.png" alt="背景对比图" style="width: 120px; height: 120px; border-radius: 8px;">
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: center; margin-top: 16px; color: #999; font-size: 12px;">
|
||||
温馨提示:<br/>
|
||||
AI设计的图案效果图是根据用户提供的照片机器学习生成的,<br/>
|
||||
多试几次就能找到你满意的效果~
|
||||
</div>
|
||||
</div>
|
||||
</van-action-sheet>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import * as badgeApi from '@/api/badge'
|
||||
const router = useRouter();
|
||||
const value = ref(0);
|
||||
const showReload = ref(false)
|
||||
const showCompare = ref(false)
|
||||
const showBgCompare = ref(false)
|
||||
function compare() {
|
||||
// showCompare.value = true
|
||||
showBgCompare.value = true
|
||||
}
|
||||
function save() {
|
||||
// 下载图片到本地
|
||||
const downloadImage = (url: string) => {
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = '徽章效果图.png'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
if (imageUrl.value) {
|
||||
downloadImage(imageUrl.value)
|
||||
} else {
|
||||
showReload.value = true
|
||||
}
|
||||
}
|
||||
const style = ref('suiji')
|
||||
function changeStyle(style: string) {
|
||||
console.log(style)
|
||||
style.value = style
|
||||
}
|
||||
function confirm() {
|
||||
console.log('confirm')
|
||||
}
|
||||
function goBack() {
|
||||
router.push('/badge');
|
||||
}
|
||||
|
||||
const changeValue = (value: number) => {
|
||||
console.log(value)
|
||||
}
|
||||
|
||||
const imageUrl = ref('')
|
||||
const group = ref(1);
|
||||
// 轮询获取图片
|
||||
const flag = ref(1)
|
||||
const timer = ref()
|
||||
const progress = ref(0)
|
||||
const progressTimer = ref()
|
||||
const progressList = () => {
|
||||
// 启动进度条计时器
|
||||
progress.value = 0
|
||||
if (!progressTimer.value) {
|
||||
progressTimer.value = setInterval(() => {
|
||||
if (progress.value < 90) {
|
||||
progress.value += 1
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
const getImageList = () => {
|
||||
badgeApi.getKindList({
|
||||
pid: 0,
|
||||
group: group.value
|
||||
}).then((res: any) => {
|
||||
const data = res || []
|
||||
flag.value = data.flag || 1
|
||||
|
||||
if (flag.value === 2) {
|
||||
// 清除轮询和进度条计时器
|
||||
clearInterval(timer.value)
|
||||
clearInterval(progressTimer.value)
|
||||
|
||||
// 进度条到100%
|
||||
progress.value = 100
|
||||
|
||||
// 显示图片
|
||||
imageUrl.value = data.url
|
||||
}
|
||||
}).catch((err) => {
|
||||
clearInterval(progressTimer.value)
|
||||
progress.value = 0
|
||||
}).finally((err) => {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getImageList()
|
||||
progressList()
|
||||
timer.value = setInterval(() => {
|
||||
getImageList()
|
||||
}, 10000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(timer.value)
|
||||
clearInterval(progressTimer.value)
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.preview-container {
|
||||
@@ -214,6 +407,11 @@ function goBack() {
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.progress-section-img {
|
||||
width: 80vw;
|
||||
height: 80vw;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.progress-bar-bg {
|
||||
width: 70%;
|
||||
height: 10px;
|
||||
@@ -354,9 +552,6 @@ function goBack() {
|
||||
height: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.action-btn:hover {
|
||||
background: #e6f7ea;
|
||||
}
|
||||
.btn-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -378,4 +573,70 @@ function goBack() {
|
||||
.confirm-btn:active {
|
||||
background: linear-gradient(90deg, #5ccf7a 0%, #8fdca0 100%);
|
||||
}
|
||||
.style-selection {
|
||||
padding: 16px;
|
||||
}
|
||||
.style-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
.style-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
width: 28vw;
|
||||
}
|
||||
.style-img {
|
||||
width: 28vw;
|
||||
height: 28vw;
|
||||
border-radius: 8px;
|
||||
object-fit: cover;
|
||||
background: #f5f5f5;
|
||||
border: 2px solid transparent;
|
||||
transition: border 0.2s;
|
||||
}
|
||||
.style-item .style-selected {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
bottom: 30px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.style-label {
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.confirm-wrapper {
|
||||
margin-top: 24px;
|
||||
}
|
||||
.confirm-button {
|
||||
width: 100%;
|
||||
background: linear-gradient(90deg, #D1ED8E 0%, #55E668 100%);
|
||||
color: #000;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
border-radius: 24px;
|
||||
padding: 12px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.confirm-button:active {
|
||||
background: linear-gradient(90deg, #5ccf7a 0%, #8fdca0 100%);
|
||||
}
|
||||
.style-item.active .style-img {
|
||||
border: 2px solid #50cf54;
|
||||
}
|
||||
.style-item.active .style-label {
|
||||
color: #50cf54;
|
||||
}
|
||||
|
||||
</style>
|
||||
+64
-44
@@ -1,20 +1,22 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="header" @click="goBack">
|
||||
<span class="back-icon"><van-icon name="arrow-left" size="16px" /> 返回</span>
|
||||
<div class="header" @click="goBack" style="text-align: center;">
|
||||
<span class="back-icon"><van-icon name="arrow-left" size="16px" color="#333" /> 设计记录</span>
|
||||
</div>
|
||||
<div class="record-container">
|
||||
<div class="record-note">
|
||||
注:可点击效果图进行下单打印
|
||||
</div>
|
||||
<div class="record-note">注:可点击效果图进行下单打印</div>
|
||||
<div class="record-images">
|
||||
<div
|
||||
v-for="(item, idx) in images"
|
||||
:key="idx"
|
||||
@click="onImageClick(item)"
|
||||
class="record-image-item"
|
||||
>
|
||||
<img :src="item" class="record-image" />
|
||||
<div class="record-image-item">
|
||||
<img src="@/assets/badge/suiji.png" alt="效果图" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;">
|
||||
</div>
|
||||
<div class="record-image-item">
|
||||
<img src="@/assets/badge/suiji.png" alt="效果图" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;">
|
||||
</div>
|
||||
<div class="record-image-item">
|
||||
<img src="@/assets/badge/suiji.png" alt="效果图" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;">
|
||||
</div>
|
||||
<div class="record-image-item">
|
||||
<img src="@/assets/badge/suiji.png" alt="效果图" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -22,6 +24,43 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router';
|
||||
import * as badgeApi from '@/api/badge';
|
||||
import { onMounted, ref } from 'vue';
|
||||
const images = ref([]);
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
const page = ref(1)
|
||||
const loading = ref(false)
|
||||
const finished = ref(false)
|
||||
|
||||
function getList() {
|
||||
if(loading.value) return
|
||||
loading.value = true
|
||||
|
||||
badgeApi.getLogOage({
|
||||
page: page.value,
|
||||
pageSize: 10,
|
||||
}).then(res => {
|
||||
if(page.value === 1) {
|
||||
images.value = res.data.list
|
||||
} else {
|
||||
images.value.push(...res.data.list)
|
||||
}
|
||||
|
||||
if(res.data.list.length < 10) {
|
||||
finished.value = true
|
||||
} else {
|
||||
page.value++
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
getList()
|
||||
}
|
||||
const router = useRouter();
|
||||
function goBack() {
|
||||
router.push('/badge');
|
||||
@@ -43,51 +82,32 @@ function goBack() {
|
||||
cursor: pointer;
|
||||
}
|
||||
.record-container {
|
||||
max-width: 500px;
|
||||
margin: 24px auto;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 2px 12px rgba(0,0,0,0.06);
|
||||
}
|
||||
|
||||
.record-note {
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
margin-bottom: 18px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.record-images {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24px;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.record-image-item {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
width: 100%;
|
||||
padding-bottom: 100%;
|
||||
position: relative;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
background: #f7f7f7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.record-image-item:hover {
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.14);
|
||||
}
|
||||
|
||||
.record-image {
|
||||
.record-image-item img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -1,29 +0,0 @@
|
||||
function googleToNormalize(data: any) {
|
||||
return {
|
||||
unionid: data.id,
|
||||
social_type: 'google',
|
||||
nickname: (data.last_name + data.first_name) || '',
|
||||
email: data.email || '',
|
||||
headimgurl: data.thumbnail || '',
|
||||
}
|
||||
}
|
||||
|
||||
function twitterToNormalize(data: any) {
|
||||
return {
|
||||
unionid: data.id_str || data.id,
|
||||
social_type: 'twitter',
|
||||
nickname: data.name || '',
|
||||
email: data.email || '',
|
||||
headimgurl: data.thumbnail || '',
|
||||
}
|
||||
}
|
||||
|
||||
export function normalize(socialType: string, data: any) {
|
||||
switch (socialType) {
|
||||
case 'google':
|
||||
return googleToNormalize(data)
|
||||
case 'twitter':
|
||||
return twitterToNormalize(data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import hello from 'hellojs'
|
||||
import type { Ref } from 'vue'
|
||||
import { normalize } from './helpers/transfer'
|
||||
// import { useUserStore } from '@/stores/user'
|
||||
import router from '@/router'
|
||||
import {useStore} from '@/stores'
|
||||
import { useTokenStore } from '@/stores/token'
|
||||
|
||||
import * as authApi from '@/api/auth'
|
||||
|
||||
interface Item {
|
||||
icon: string
|
||||
name: string
|
||||
text: string
|
||||
}
|
||||
|
||||
const logins: Ref<Item[]> = ref([
|
||||
// {
|
||||
// icon: 'microsoft',
|
||||
// name: 'windows',
|
||||
// text: 'windows',
|
||||
// },
|
||||
{
|
||||
icon: 'googleplus',
|
||||
name: 'google',
|
||||
text: 'G+',
|
||||
},
|
||||
// {
|
||||
// icon: 'facebook',
|
||||
// name: 'facebook',
|
||||
// text: 'Facebook',
|
||||
// },
|
||||
// {
|
||||
// icon: 'apple',
|
||||
// name: 'apple',
|
||||
// text: 'apple',
|
||||
// },
|
||||
{
|
||||
icon: 'twitter',
|
||||
name: 'twitter',
|
||||
text: 'twitter',
|
||||
},
|
||||
// {
|
||||
// icon: 'wechat',
|
||||
// name: 'wechat',
|
||||
// text: 'wechat',
|
||||
// },
|
||||
])
|
||||
|
||||
function onBtn(item: Item) {
|
||||
switch (item.name) {
|
||||
case 'wechat':
|
||||
window.location.href = `https://wechat.api.suwa3d.com/api/auth/page?callback${encodeURIComponent(window.location.href)}`
|
||||
return
|
||||
}
|
||||
|
||||
hello(item.name).login().then((d: any) => {
|
||||
console.log('d', d)
|
||||
// hello(item.name).api('me').then((d: any) => {
|
||||
// console.log('d', d)
|
||||
// const data: any = normalize(item.name, d)
|
||||
// // const user = useUserStore()
|
||||
// // user.login(d)
|
||||
// // useRouter().replace('/')
|
||||
// }, (e: any) => {
|
||||
// console.log('/me error', e)
|
||||
// })
|
||||
}, () => {
|
||||
// console.log('login failed')
|
||||
})
|
||||
}
|
||||
|
||||
const stores = useStore();
|
||||
|
||||
hello.on('auth.login', (r: any) => {
|
||||
hello(r.network).api('/me', 'get').then((d) => {
|
||||
const data: any = normalize(r.network, d)
|
||||
authApi.getUser(data).then((res: any) => {
|
||||
useTokenStore().login(res)
|
||||
let url = stores.redirectUrl();
|
||||
if (url) {
|
||||
stores.setRedirect('')
|
||||
router.replace(url)
|
||||
return
|
||||
}
|
||||
|
||||
router.replace('/')
|
||||
}, (e: any) => {
|
||||
console.log('auth.login /me error', e)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: 这边需要进行配置
|
||||
hello.init({
|
||||
facebook: '1875721406193406',
|
||||
windows: '000000004403AD10',
|
||||
google: '495792315385-mj44iuov1bupumvl6evmmcvag39mi38t.apps.googleusercontent.com',
|
||||
twitter: 'ICw3GtdIivmHPI5qTLD0gZDbN',
|
||||
}, {
|
||||
redirect_uri: './oauth.html',
|
||||
scope: 'email',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<van-divider>Social Login</van-divider>
|
||||
<div v-for="(item, i) in logins" :key="i" class="l-btn">
|
||||
<van-button plain icon-prefix="iconfont" :icon="item.icon" type="primary" size="large" @click="onBtn(item)">
|
||||
{{ item.text }}
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.l-btn{
|
||||
margin: .4rem;
|
||||
width: 100%;
|
||||
}
|
||||
.container{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user