mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
synced 2026-11-06 17:09:01 +08:00
Merge branch 'feat/appointment-goods'
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
### 说明 https://ext.dcloud.net.cn/plugin?id=3237
|
||||
@@ -1,200 +0,0 @@
|
||||
<template>
|
||||
|
||||
<div class="index">
|
||||
<u-modal v-model:show="show" :show-title="false" :show-confirm-button="false" mask-close-able>
|
||||
<view class="slot-content">
|
||||
<image @click="downLoad()" class="img" :src="imgUrl" />
|
||||
<div class="canvas-hide">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<canvas id="canvas" type="2d" style="width: 600px; height: 960px" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<canvas canvas-id="canvas" id="canvas" style="width: 600px; height: 960px" />
|
||||
<!-- #endif -->
|
||||
</div>
|
||||
</view>
|
||||
</u-modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, getCurrentInstance } from 'vue'
|
||||
// 引入绘制插件
|
||||
import DrawPoster from "@/js_sdk/u-draw-poster"
|
||||
import logoImg from "@/pages/passport/static/logo-title.png"
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
}>()
|
||||
|
||||
const imgUrl = ref("")
|
||||
const show = ref(false)
|
||||
const dp = ref<any>({})
|
||||
const logo = logoImg
|
||||
|
||||
/**
|
||||
* 解决微信小程序中图片模糊问题
|
||||
*/
|
||||
// #ifdef MP-WEIXIN
|
||||
const st2 = (size: number) => size * 2
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
const st2 = (size: number) => size
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 保存图片
|
||||
*/
|
||||
const downLoad = () => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: imgUrl.value,
|
||||
success: function () {
|
||||
uni.showToast({
|
||||
title: "保存成功!",
|
||||
icon: "none",
|
||||
})
|
||||
},
|
||||
fail: function () {
|
||||
uni.showToast({
|
||||
title: "保存失败,请稍后重试!",
|
||||
icon: "none",
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建canvas
|
||||
*/
|
||||
const init = async () => {
|
||||
show.value = true
|
||||
dp.value = await DrawPoster.build({
|
||||
selector: "canvas",
|
||||
componentThis: instance?.proxy,
|
||||
loading: true,
|
||||
debugging: true,
|
||||
})
|
||||
let dpVal = dp.value
|
||||
// #ifdef MP-WEIXIN
|
||||
// 用于微信小程序中画布错乱问题
|
||||
dpVal.canvas.width = st2(600)
|
||||
dpVal.canvas.height = st2(960)
|
||||
// #endif
|
||||
await draw(dpVal)
|
||||
}
|
||||
|
||||
const draw = async (dp: any) => {
|
||||
const { width, height, background, title } = props.res.container
|
||||
const { code, img, price } = props.res.bottom
|
||||
|
||||
// /** 绘制背景 */
|
||||
await dp.draw((ctx: any) => {
|
||||
ctx.fillStyle = background
|
||||
ctx.fillRoundRect(
|
||||
st2(0),
|
||||
st2(0),
|
||||
st2(width),
|
||||
st2(height),
|
||||
st2(12)
|
||||
)
|
||||
ctx.clip()
|
||||
})
|
||||
/** 绘制图片 */
|
||||
dp.draw(async (ctx: any) => {
|
||||
await Promise.all([
|
||||
// 绘制Logo
|
||||
ctx.drawImage(
|
||||
logo,
|
||||
st2(175),
|
||||
st2(0),
|
||||
st2(256),
|
||||
st2(144)
|
||||
),
|
||||
// 中间图片
|
||||
ctx.drawImage(
|
||||
img,
|
||||
st2(100),
|
||||
st2(150),
|
||||
st2(400),
|
||||
st2(400)
|
||||
),
|
||||
// 二维码
|
||||
ctx.drawImage(
|
||||
code,
|
||||
st2(39),
|
||||
st2(750),
|
||||
st2(150),
|
||||
st2(150)
|
||||
),
|
||||
])
|
||||
})
|
||||
|
||||
/** 绘制中间文字*/
|
||||
await dp.draw((ctx: any) => {
|
||||
ctx.fillStyle = "#333"
|
||||
ctx.font = `bold ${st2(24)}px PingFang SC`
|
||||
ctx.textAlign = "center"
|
||||
ctx.fillWarpText({
|
||||
text: title,
|
||||
maxWidth: st2(500),
|
||||
x: st2(300),
|
||||
y: st2(600),
|
||||
layer: 1,
|
||||
})
|
||||
|
||||
ctx.fillStyle = "#ff3c2a"
|
||||
ctx.font = `${st2(38)}px PingFang SC`
|
||||
ctx.textAlign = "center"
|
||||
ctx.fillText(price, st2(300), st2(680))
|
||||
})
|
||||
|
||||
// /** 绘制底部文字 */
|
||||
await dp.draw((ctx: any) => {
|
||||
ctx.fillStyle = "#666"
|
||||
ctx.font = `${st2(24)}px PingFang SC`
|
||||
ctx.fillText("长按图片,识别二维码", st2(200), st2(866))
|
||||
ctx.fillStyle = "#666"
|
||||
ctx.font = `${st2(24)}px PingFang SC`
|
||||
ctx.fillText("查看商品详情", st2(200), st2(900))
|
||||
})
|
||||
|
||||
imgUrl.value = await dp.createImagePath()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page,
|
||||
.index {
|
||||
height: 100%;
|
||||
}
|
||||
.canvas-hide {
|
||||
/* 1 */
|
||||
position: fixed;
|
||||
right: 100vw;
|
||||
bottom: 100vh;
|
||||
/* 2 */
|
||||
z-index: -9999;
|
||||
/* 3 */
|
||||
opacity: 0;
|
||||
}
|
||||
.index {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
background: rgba($color: grey, $alpha: 0.2);
|
||||
}
|
||||
|
||||
image {
|
||||
display: block;
|
||||
}
|
||||
.img {
|
||||
width: 600rpx;
|
||||
height: 960rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,199 +0,0 @@
|
||||
<template>
|
||||
<view class="index">
|
||||
<view v-model="show" class="slot-content">
|
||||
<image @click="downLoad()" class="img" :src="imgUrl" />
|
||||
<div class="canvas-hide">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<canvas id="canvas" type="2d" style="width: 560px; height: 800px" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<canvas canvas-id="canvas" id="canvas" style="width: 560px; height: 800px" />
|
||||
<!-- #endif -->
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, getCurrentInstance } from 'vue'
|
||||
// 引入绘制插件
|
||||
import DrawPoster from "@/js_sdk/u-draw-poster"
|
||||
// 生成二维码
|
||||
import uQRCode from '@/components/Sansnn-uQRCode/uqrcode.js'
|
||||
import logoImg from "@/pages/passport/static/logo-title.png"
|
||||
import myFaceImg from "@/pages/passport/static/missing-face.png"
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
|
||||
const props = defineProps<{
|
||||
res?: any
|
||||
}>()
|
||||
|
||||
const imgUrl = ref("")
|
||||
const show = ref(false)
|
||||
const dp = ref<any>({})
|
||||
const logo = logoImg
|
||||
const myFace = myFaceImg
|
||||
const sharingLink = ref('')
|
||||
|
||||
/** 解决微信小程序中图片模糊问题 */
|
||||
// #ifdef MP-WEIXIN
|
||||
const st2 = (size: number) => size * 2
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
const st2 = (size: number) => size
|
||||
// #endif
|
||||
|
||||
/** 保存图片 */
|
||||
const downLoad = () => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: imgUrl.value,
|
||||
success: function () {
|
||||
uni.showToast({title: "保存成功!",icon: "none"})
|
||||
},
|
||||
fail: function () {
|
||||
uni.showToast({title: "保存失败,请稍后重试!",icon: "none"})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/** 创建canvas */
|
||||
const init = async () => {
|
||||
show.value = true
|
||||
dp.value = await DrawPoster.build({
|
||||
selector: "canvas",
|
||||
componentThis: instance?.proxy,
|
||||
loading: true,
|
||||
debugging: true,
|
||||
})
|
||||
let dpVal = dp.value
|
||||
// #ifdef MP-WEIXIN
|
||||
// 用于微信小程序中画布错乱问题
|
||||
dpVal.canvas.width = st2(560)
|
||||
dpVal.canvas.height = st2(800)
|
||||
// #endif
|
||||
await showQRCode(dpVal)
|
||||
}
|
||||
|
||||
/** 生成二维码 */
|
||||
const showQRCode = async (dp: any) => {
|
||||
await uQRCode.make({
|
||||
canvasId: 'canvas',
|
||||
componentInstance: instance?.proxy,
|
||||
text: props.res.bottom.code,
|
||||
size: 130,
|
||||
margin: 5,
|
||||
backgroundColor: '#ffffff',
|
||||
foregroundColor: '#000000',
|
||||
fileType: 'jpg',
|
||||
errorCorrectLevel: 0,
|
||||
success: (res: any) => {
|
||||
sharingLink.value = res
|
||||
draw(dp)
|
||||
},
|
||||
fail: (_res: any) => {
|
||||
// console.log('失败',res)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const draw = async (dp: any) => {
|
||||
const { face, nickName, desc } = props.res.memberInfo
|
||||
const { width, height, background, title } = props.res.container
|
||||
const { img, price } = props.res.bottom
|
||||
|
||||
/** 绘制背景 */
|
||||
await dp.draw((ctx: any) => {
|
||||
ctx.fillStyle = background
|
||||
ctx.fillRoundRect(st2(0), st2(0), st2(width), st2(height), st2(12))
|
||||
ctx.clip()
|
||||
})
|
||||
/** 绘制圆角矩形 */
|
||||
await dp.draw(async (ctx: any) => {
|
||||
ctx.fillStyle = "#ffffff"
|
||||
ctx.strokeStyle = "#ffffff"
|
||||
ctx.lineWidth = st2(1)
|
||||
ctx.fillRoundRect(30, 150, 500, 620, 0)
|
||||
})
|
||||
/** 绘制图片 */
|
||||
dp.draw(async (ctx: any) => {
|
||||
await Promise.all([
|
||||
ctx.drawImage(face ? face : myFace, st2(30), st2(30), st2(90), st2(90)),
|
||||
ctx.drawImage(img, st2(60), st2(170), st2(440), st2(440)),
|
||||
ctx.drawImage(sharingLink.value, st2(375), st2(625), st2(130), st2(130))
|
||||
])
|
||||
})
|
||||
/** 绘制顶部文字(昵称 简述) */
|
||||
await dp.draw((ctx: any) => {
|
||||
ctx.fillStyle = "#666"
|
||||
ctx.font = `${st2(24)}px PingFang SC`
|
||||
ctx.fillText(nickName, st2(150), st2(65))
|
||||
ctx.fillStyle = "#666"
|
||||
ctx.font = `${st2(24)}px PingFang SC`
|
||||
ctx.fillText(desc, st2(150), st2(105))
|
||||
})
|
||||
/** 绘制中间文字(商品名称 价格) */
|
||||
await dp.draw((ctx: any) => {
|
||||
ctx.fillStyle = "#333"
|
||||
ctx.font = `bold ${st2(24)}px PingFang SC`
|
||||
ctx.textAlign = "left"
|
||||
ctx.fillWarpText({
|
||||
text: title,
|
||||
lineHeight: st2(32),
|
||||
maxWidth: st2(280),
|
||||
x: st2(60),
|
||||
y: st2(710),
|
||||
layer: 2,
|
||||
})
|
||||
ctx.fillStyle = "#ff3c2a"
|
||||
ctx.font = `${st2(38)}px PingFang SC`
|
||||
ctx.textAlign = "left"
|
||||
ctx.fillText(price, st2(60), st2(665))
|
||||
})
|
||||
|
||||
// 绘制生成本地地址
|
||||
imgUrl.value = await dp.createImagePath()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
page,
|
||||
.index {
|
||||
height: 100%;
|
||||
}
|
||||
.canvas-hide {
|
||||
/* 1 */
|
||||
position: fixed;
|
||||
right: 100vw;
|
||||
bottom: 100vh;
|
||||
/* 2 */
|
||||
z-index: -9999;
|
||||
/* 3 */
|
||||
opacity: 0;
|
||||
}
|
||||
.index {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
background: rgba($color: grey, $alpha: 0.2);
|
||||
}
|
||||
|
||||
image {
|
||||
display: block;
|
||||
}
|
||||
.img {
|
||||
width: 560rpx;
|
||||
height: 800rpx;
|
||||
}
|
||||
|
||||
.qrcode-content {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,331 +0,0 @@
|
||||
<template>
|
||||
<view class="shadow" :class="!show?'':'shadow-show'" :style="{backgroundColor:show?maskBg:'rgba(0,0,0,0)'}" @tap="tapMask">
|
||||
<view class="popups" :class="[theme]" :style="{top: popupsTop ,left: popupsLeft,flexDirection:direction}">
|
||||
<text :class="dynPlace" :style="{width:'0px',height:'0px'}" v-if="triangle"></text>
|
||||
<view v-for="(item,index) in popData" :key="index" @tap.stop="tapItem(item)" class="itemChild view" :class="[direction=='row'?'solid-right':'solid-bottom',item.disabled?'disabledColor':'']">
|
||||
<view class="popup-icon" v-if="item.icon">
|
||||
<u-icon size="35rpx" :name="item.icon"></u-icon>
|
||||
</view>
|
||||
<span class="title">{{item.title}}</span>
|
||||
</view>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, getCurrentInstance } from 'vue'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
maskBg?: string
|
||||
placement?: string
|
||||
direction?: string
|
||||
x?: number
|
||||
y?: number
|
||||
modelValue?: boolean
|
||||
popData?: any[]
|
||||
theme?: string
|
||||
dynamic?: boolean
|
||||
gap?: number
|
||||
triangle?: boolean
|
||||
}>(), {
|
||||
maskBg: "rgba(0,0,0,0)",
|
||||
placement: "default",
|
||||
direction: "column",
|
||||
x: 0,
|
||||
y: 0,
|
||||
modelValue: false,
|
||||
popData: () => [],
|
||||
theme: "light",
|
||||
dynamic: false,
|
||||
gap: 20,
|
||||
triangle: true,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'tapPopup'])
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
|
||||
const popupsTop = ref("0rpx")
|
||||
const popupsLeft = ref("0rpx")
|
||||
const show = ref(false)
|
||||
const dynPlace = ref("")
|
||||
|
||||
onMounted(() => {
|
||||
popupsPosition()
|
||||
})
|
||||
|
||||
const tapMask = () => {
|
||||
emit("update:modelValue", !props.modelValue)
|
||||
}
|
||||
|
||||
const tapItem = (item: any) => {
|
||||
if (item.disabled) return
|
||||
emit("tapPopup", item)
|
||||
emit("update:modelValue", !props.modelValue)
|
||||
}
|
||||
|
||||
const getStatusBar = () => {
|
||||
const windowInfo = uni.getWindowInfo()
|
||||
// #ifdef H5
|
||||
return Promise.resolve(
|
||||
(windowInfo.statusBarHeight || 0) + (windowInfo.windowTop || 0)
|
||||
)
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
return Promise.resolve(windowInfo.statusBarHeight || 0)
|
||||
// #endif
|
||||
}
|
||||
|
||||
const popupsPosition = async () => {
|
||||
let statusBar = await getStatusBar()
|
||||
await new Promise<void>((resolve) => {
|
||||
let popupsDom = uni.createSelectorQuery().in(instance!.proxy).select(".popups")
|
||||
popupsDom
|
||||
.fields(
|
||||
{
|
||||
size: true,
|
||||
},
|
||||
(data: any) => {
|
||||
if (!data) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
let width = data.width
|
||||
let height = data.height
|
||||
|
||||
let y = props.dynamic
|
||||
? dynamicGetY(props.y, props.gap)
|
||||
: transformRpx(props.y)
|
||||
|
||||
let x = props.dynamic
|
||||
? dynamicGetX(props.x, props.gap)
|
||||
: transformRpx(props.x)
|
||||
|
||||
// #ifdef H5
|
||||
y = props.dynamic
|
||||
? props.y + statusBar
|
||||
: transformRpx(props.y + statusBar)
|
||||
// #endif
|
||||
|
||||
dynPlace.value =
|
||||
props.placement == "default"
|
||||
? getPlacement(x, y)
|
||||
: props.placement
|
||||
|
||||
switch (dynPlace.value) {
|
||||
case "top-start":
|
||||
popupsTop.value = `${y + 9}rpx`
|
||||
popupsLeft.value = `${x - 15}rpx`
|
||||
break
|
||||
case "top-end":
|
||||
popupsTop.value = `${y + 9}rpx`
|
||||
popupsLeft.value = `${x + 15 - width}rpx`
|
||||
break
|
||||
case "bottom-start":
|
||||
popupsTop.value = `${y - 18 - height}rpx`
|
||||
popupsLeft.value = `${x - 15}rpx`
|
||||
break
|
||||
case "bottom-end":
|
||||
popupsTop.value = `${y - 9 - height}rpx`
|
||||
popupsLeft.value = `${x + 15 - width}rpx`
|
||||
break
|
||||
}
|
||||
resolve()
|
||||
}
|
||||
)
|
||||
.exec()
|
||||
})
|
||||
}
|
||||
|
||||
const getPlacement = (x: number, y: number) => {
|
||||
const { windowWidth: width, windowHeight: height } = uni.getWindowInfo()
|
||||
if (x > width / 2 && y > height / 2) {
|
||||
return "bottom-end"
|
||||
} else if (x < width / 2 && y < height / 2) {
|
||||
return "top-start"
|
||||
} else if (x > width / 2 && y < height / 2) {
|
||||
return "top-end"
|
||||
} else if (x < width / 2 && y > height / 2) {
|
||||
return "bottom-start"
|
||||
} else if (x > width / 2) {
|
||||
return "top-end"
|
||||
} else {
|
||||
return "top-start"
|
||||
}
|
||||
}
|
||||
|
||||
const dynamicGetY = (y: number, gap: number) => {
|
||||
const { windowHeight: height } = uni.getWindowInfo()
|
||||
y = y < gap ? gap : y
|
||||
y = height - y < gap ? height - gap : y
|
||||
return y
|
||||
}
|
||||
|
||||
const dynamicGetX = (x: number, gap: number) => {
|
||||
const { windowWidth: width } = uni.getWindowInfo()
|
||||
x = x < gap ? gap : x
|
||||
x = width - x < gap ? width - gap : x
|
||||
return x
|
||||
}
|
||||
|
||||
const transformRpx = (params: number) => {
|
||||
const { screenWidth } = uni.getWindowInfo()
|
||||
return (params * screenWidth) / 375
|
||||
}
|
||||
|
||||
watch(() => props.modelValue, async (newVal) => {
|
||||
if (newVal) await popupsPosition()
|
||||
show.value = newVal
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => props.placement, (newVal) => {
|
||||
dynPlace.value = newVal
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
.shadow {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
z-index: 9999;
|
||||
transition: background 0.3s ease-in-out;
|
||||
visibility: hidden;
|
||||
|
||||
&.shadow-show {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.popups {
|
||||
position: absolute;
|
||||
padding: 20rpx;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
.view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15rpx 10rpx;
|
||||
font-size: 25rpx;
|
||||
}
|
||||
.popup-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
.image {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
.dark {
|
||||
background-color: #4c4c4c;
|
||||
color: #fff;
|
||||
.top-start:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -18rpx;
|
||||
left: 10rpx;
|
||||
border-width: 0 20rpx 20rpx;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent #4c4c4c;
|
||||
}
|
||||
.top-end:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -18rpx;
|
||||
right: 10rpx;
|
||||
border-width: 0 20rpx 20rpx;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent #4c4c4c;
|
||||
}
|
||||
.bottom-start:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -18rpx;
|
||||
left: 10rpx;
|
||||
border-width: 20rpx 20rpx 0;
|
||||
border-style: solid;
|
||||
border-color: #4c4c4c transparent transparent;
|
||||
}
|
||||
.bottom-end:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -18rpx;
|
||||
right: 10rpx;
|
||||
border-width: 20rpx 20rpx 0;
|
||||
border-style: solid;
|
||||
border-color: #4c4c4c transparent transparent;
|
||||
}
|
||||
.disabledColor {
|
||||
color: #c5c8ce;
|
||||
}
|
||||
}
|
||||
.light {
|
||||
color: #515a6e;
|
||||
box-shadow: 0upx 0upx 30upx rgba(0, 0, 0, 0.2);
|
||||
background: #fff;
|
||||
.top-start:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -18rpx;
|
||||
left: 10rpx;
|
||||
border-width: 0 20rpx 20rpx;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent #fff;
|
||||
}
|
||||
.top-end:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -18rpx;
|
||||
right: 10rpx;
|
||||
border-width: 0 20rpx 20rpx;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent #fff;
|
||||
}
|
||||
.bottom-start:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -18rpx;
|
||||
left: 10rpx;
|
||||
border-width: 20rpx 20rpx 0;
|
||||
border-style: solid;
|
||||
border-color: #fff transparent transparent;
|
||||
}
|
||||
.bottom-end:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -18rpx;
|
||||
right: 10rpx;
|
||||
border-width: 20rpx 20rpx 0;
|
||||
border-style: solid;
|
||||
border-color: #fff transparent transparent;
|
||||
}
|
||||
.disabledColor {
|
||||
color: #c5c8ce;
|
||||
}
|
||||
}
|
||||
.solid-bottom {
|
||||
border-bottom: 1px solid #f3f5f7;
|
||||
}
|
||||
.solid-right {
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
.popups .itemChild:last-child {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
@@ -4,12 +4,9 @@
|
||||
v-if="!state.hid"
|
||||
class="flex-row-center"
|
||||
:style="{ top: state.scHight }"
|
||||
style="width: 750rpx; position: fixed; z-index: 100; left: 0"
|
||||
style="width: 750rpx; position: fixed; z-index: 100; left: 0; background-color: #ffffff; padding: 40rpx 0"
|
||||
>
|
||||
<view
|
||||
class="flex-column-center"
|
||||
style="background-color: #fcfcfc; padding: 30rpx; border-radius: 10rpx"
|
||||
>
|
||||
<view class="flex-column-center">
|
||||
<movable-area
|
||||
class="flex"
|
||||
style="width: 100%"
|
||||
@@ -43,63 +40,47 @@
|
||||
:src="state.img"
|
||||
mode="aspectFit"
|
||||
:style="{ height: state.originalHeight, width: state.originalWidth }"
|
||||
style="border-radius: 10rpx"
|
||||
style="border-radius: 24rpx"
|
||||
></image>
|
||||
</movable-area>
|
||||
|
||||
<movable-area
|
||||
class="flex-row-start"
|
||||
style="
|
||||
width: 100%;
|
||||
background-color: #efefef;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
margin-top: 30rpx;
|
||||
"
|
||||
>
|
||||
<movable-area class="v-track" animation="false">
|
||||
<view class="v-fill" :style="{ width: fillWidth }"></view>
|
||||
<text class="v-track-text" :style="{ color: state.col }">{{
|
||||
state.hasImg
|
||||
}}</text>
|
||||
<movable-view
|
||||
scale-value="1"
|
||||
animation="false"
|
||||
damping="50"
|
||||
:x="state.movePv"
|
||||
class="flex-row-center"
|
||||
style="
|
||||
border-radius: 50%;
|
||||
height: 100rpx;
|
||||
width: 100rpx;
|
||||
background-color: #ffffff;
|
||||
border: 2rpx solid #e3e3e3;
|
||||
margin-top: -13rpx;
|
||||
"
|
||||
class="v-handle"
|
||||
:style="handleStyle"
|
||||
direction="horizontal"
|
||||
@change="moveChange"
|
||||
@touchend="end"
|
||||
>
|
||||
<u-icon
|
||||
:color="mainColor"
|
||||
size="40"
|
||||
color="#ffffff"
|
||||
size="38"
|
||||
v-if="state.endLoad"
|
||||
name="arrow-right"
|
||||
></u-icon>
|
||||
<u-icon :color="mainColor" size="40" v-else name="reload"></u-icon>
|
||||
<u-icon color="#ffffff" size="38" v-else name="reload"></u-icon>
|
||||
</movable-view>
|
||||
|
||||
<text style="padding-left: 140rpx" :style="{ color: state.col }">{{
|
||||
state.hasImg
|
||||
}}</text>
|
||||
</movable-area>
|
||||
<view class="flex-row-around padding-top" style="width: 100%">
|
||||
<u-icon
|
||||
@click="hide"
|
||||
:color="mainColor"
|
||||
size="40"
|
||||
name="close"
|
||||
></u-icon>
|
||||
|
||||
<text class="cu-tag round" @click="getCode">刷新拼图</text>
|
||||
<text class="my-neirong-sm cuIcon-safe" style="color: #c1c1c1"
|
||||
>Lili-FRAMEWORK</text
|
||||
>
|
||||
<view class="v-foot">
|
||||
<view class="v-icon-btn" @click="getCode">
|
||||
<u-icon color="#888888" size="32" name="reload"></u-icon>
|
||||
</view>
|
||||
<view class="v-icon-btn" @click="hide">
|
||||
<u-icon color="#888888" size="30" name="close"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="v-mark">
|
||||
<text class="cuIcon-safe v-mark-icon"></text>
|
||||
<text>Lili-FRAMEWORK 安全验证</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -133,6 +114,13 @@ const phone = uni.getSystemInfoSync()
|
||||
const l = phone.screenWidth / 750
|
||||
|
||||
const mainColor = computed(() => store.getters.mainColor)
|
||||
const fillWidth = computed(() => `${state.moveX + 42 * l}px`)
|
||||
const handleStyle = computed(() => {
|
||||
const glow = /^#[0-9a-fA-F]{6}$/.test(mainColor.value)
|
||||
? mainColor.value + '59'
|
||||
: 'rgba(0, 0, 0, 0.18)'
|
||||
return { background: mainColor.value, boxShadow: `0 6rpx 20rpx ${glow}` }
|
||||
})
|
||||
const state = reactive({
|
||||
flage: false,
|
||||
key: '', // key
|
||||
@@ -284,6 +272,79 @@ defineExpose({
|
||||
@import "./animation.css";
|
||||
@import "./icon.css";
|
||||
// @import './main.css';
|
||||
|
||||
.v-track {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 84rpx;
|
||||
margin-top: 36rpx;
|
||||
background-color: #f7f7f8;
|
||||
border-radius: 42rpx;
|
||||
}
|
||||
|
||||
.v-fill {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: #ffe9e5;
|
||||
border-radius: 42rpx;
|
||||
}
|
||||
|
||||
.v-track-text {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
line-height: 84rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
.v-handle {
|
||||
width: 84rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.v-foot {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
margin-top: 28rpx;
|
||||
}
|
||||
|
||||
.v-icon-btn {
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f4f4f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.v-mark {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 32rpx;
|
||||
font-size: 22rpx;
|
||||
color: #d2d2d2;
|
||||
}
|
||||
|
||||
.v-mark-icon {
|
||||
margin-right: 8rpx;
|
||||
font-size: 22rpx;
|
||||
color: #d9d9d9;
|
||||
}
|
||||
.dh-wt {
|
||||
animation: at 1.1s ease;
|
||||
animation-iteration-count: infinite;
|
||||
|
||||
Reference in New Issue
Block a user