chore(components): 只增加组件
This commit is contained in:
6
components/ai-chat-message/ai-chat-message.json
Normal file
6
components/ai-chat-message/ai-chat-message.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"ns-loading": "../ns-loading/ns-loading"
|
||||||
|
}
|
||||||
|
}
|
||||||
2766
components/ai-chat-message/ai-chat-message.vue
Normal file
2766
components/ai-chat-message/ai-chat-message.vue
Normal file
File diff suppressed because it is too large
Load Diff
276
components/diy-components/diy-digit.vue
Normal file
276
components/diy-components/diy-digit.vue
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
<template>
|
||||||
|
<view :style="componentStyle">
|
||||||
|
<scroll-view
|
||||||
|
:class="['graphic-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle]"
|
||||||
|
:scroll-x="value.showStyle == 'singleSlide'"
|
||||||
|
>
|
||||||
|
<view class="uni-scroll-view-content">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in value.list"
|
||||||
|
:key="index"
|
||||||
|
:class="['graphic-nav-item', value.mode, value.mode === 'text' ? 'newright' : '']"
|
||||||
|
:style="{ width: (100 / value.rowCount + '%') + ';' }"
|
||||||
|
>
|
||||||
|
<view style="display:flex;">
|
||||||
|
<view :style="{
|
||||||
|
'line-height': '1.2;',
|
||||||
|
'font-size': (value.font.titlesize * 2 + 'rpx') + ';',
|
||||||
|
'font-weight': '600;',
|
||||||
|
'color': value.font.titlecolor + ';'
|
||||||
|
}">
|
||||||
|
<uv-count-to
|
||||||
|
:ref="`countTo-${index}`"
|
||||||
|
:autoplay="true"
|
||||||
|
:startVal="30"
|
||||||
|
:endVal="item.title"
|
||||||
|
:decimals="getvalue(item.title)"
|
||||||
|
decimal="."
|
||||||
|
></uv-count-to>
|
||||||
|
<text :style="{
|
||||||
|
'margin-left': '4rpx;',
|
||||||
|
'font-size': (value.font.unitsize * 2 + 'rpx') + ';',
|
||||||
|
'font-weight': value.font.weight + ';',
|
||||||
|
'color': value.font.unitcolor + ';'
|
||||||
|
}">{{ item.unit }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="graphic-text">
|
||||||
|
<text :style="{
|
||||||
|
'font-size': (value.font.descsize * 2 + 'rpx') + ';',
|
||||||
|
'font-weight': value.font.weight + ';',
|
||||||
|
'color': value.font.desccolor + ';'
|
||||||
|
}">{{ item.desc }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<ns-login ref="login"></ns-login>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import uvCountTo from '@/components/uv-count-to/uv-count-to.vue'
|
||||||
|
import nsLogin from '@/components/ns-login/ns-login.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'diy-digit',
|
||||||
|
components: {
|
||||||
|
uvCountTo,
|
||||||
|
nsLogin
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageWidth: '',
|
||||||
|
indicatorDots: false,
|
||||||
|
swiperCurrent: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 组件创建时的逻辑
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
componentRefresh(newValue) {
|
||||||
|
// 监听组件刷新
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
componentStyle() {
|
||||||
|
let style = '';
|
||||||
|
style += 'background-image:url(' + this.$util.img(this.value.imageUrl) + ');background-size:100% 100%;';
|
||||||
|
|
||||||
|
if (this.value.componentAngle == 'round') {
|
||||||
|
style += 'border-top-left-radius:' + (2 * this.value.topAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-top-right-radius:' + (2 * this.value.topAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-bottom-left-radius:' + (2 * this.value.bottomAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-bottom-right-radius:' + (2 * this.value.bottomAroundRadius) + 'rpx;';
|
||||||
|
}
|
||||||
|
|
||||||
|
style += 'box-shadow:' + (this.value.ornament.type == 'shadow' ? '0 0 10rpx ' + this.value.ornament.color : '') + ';';
|
||||||
|
style += 'border:' + (this.value.ornament.type == 'stroke' ? '2rpx solid ' + this.value.ornament.color : '') + ';';
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 获取小数位数
|
||||||
|
getvalue(value) {
|
||||||
|
return value % 1 !== 0 ? 2 : 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 页面跳转
|
||||||
|
redirectTo(item) {
|
||||||
|
if (!item.wap_url || this.$util.getCurrRoute() != 'pages/member/index' || this.storeToken) {
|
||||||
|
console.log(item);
|
||||||
|
this.$util.diyRedirectTo(item);
|
||||||
|
} else {
|
||||||
|
this.$refs.login.open(item.wap_url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 轮播切换
|
||||||
|
swiperChange(event) {
|
||||||
|
this.swiperCurrent = event.detail.current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.graphic-nav {
|
||||||
|
padding: 16rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&.fixed-layout {
|
||||||
|
.uni-scroll-view-content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.singleSlide {
|
||||||
|
.uni-scroll-view-content {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graphic-nav-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pageSlide {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.uni-swiper-dots-horizontal {
|
||||||
|
bottom: 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.straightLine {
|
||||||
|
.uni-swiper-dot {
|
||||||
|
width: 30rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
.uni-swiper-dot {
|
||||||
|
width: 14rpx;
|
||||||
|
height: 14rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.graphic-nav-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graphic-nav-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14rpx 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.graphic-text {
|
||||||
|
line-height: 1.3;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.alone {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.text {
|
||||||
|
.graphic-text {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.graphic-img {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
font-size: 90rpx;
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
position: absolute;
|
||||||
|
top: -10rpx;
|
||||||
|
right: -24rpx;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
-webkit-transform: scale(0.8);
|
||||||
|
transform: scale(0.8);
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 50rpx;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pageSlide {
|
||||||
|
.graphic-nav-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.newright {
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-dot-box {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: -20rpx;
|
||||||
|
padding-bottom: 8rpx;
|
||||||
|
|
||||||
|
.swiper-dot {
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
margin: 8rpx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.straightLine {
|
||||||
|
.swiper-dot {
|
||||||
|
width: 30rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
.swiper-dot {
|
||||||
|
width: 15rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 15rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
290
components/diy-components/diy-image-nav.vue
Normal file
290
components/diy-components/diy-image-nav.vue
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
<template>
|
||||||
|
<view :style="componentStyle">
|
||||||
|
<scroll-view
|
||||||
|
:class="['image-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle]"
|
||||||
|
:scroll-x="value.showStyle == 'singleSlide'"
|
||||||
|
>
|
||||||
|
<view class="uni-scroll-view-content">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in value.list"
|
||||||
|
:key="index"
|
||||||
|
:class="['image-nav-item', value.mode]"
|
||||||
|
style="margin-right: 28rpx;"
|
||||||
|
>
|
||||||
|
<!-- 图片部分 -->
|
||||||
|
<view v-if="value.mode != 'text'" class="image-img" :style="{
|
||||||
|
'font-size': (value.imageSize * 2 + 'rpx') + ';',
|
||||||
|
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
||||||
|
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
||||||
|
}">
|
||||||
|
<image
|
||||||
|
v-if="item.link.wap_url"
|
||||||
|
:style="{
|
||||||
|
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
||||||
|
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
||||||
|
}"
|
||||||
|
:src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
||||||
|
:show-menu-by-longpress="true"
|
||||||
|
@tap="redirectTo(item.link)"
|
||||||
|
></image>
|
||||||
|
<image
|
||||||
|
v-else
|
||||||
|
:style="{
|
||||||
|
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
||||||
|
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
||||||
|
}"
|
||||||
|
:src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
||||||
|
:show-menu-by-longpress="true"
|
||||||
|
@tap="previewImg(item.imageUrl)"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 文字部分 -->
|
||||||
|
<text class="image-text" :style="{
|
||||||
|
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
||||||
|
'font-size': (value.font.size * 2 + 'rpx') + ';',
|
||||||
|
'font-weight': value.font.weight + ';',
|
||||||
|
'color': value.font.color + ';'
|
||||||
|
}">{{ item.title }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<ns-login ref="login"></ns-login>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import nsLogin from '@/components/ns-login/ns-login.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'diy-image-nav',
|
||||||
|
components: {
|
||||||
|
nsLogin
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageWidth: '',
|
||||||
|
indicatorDots: false,
|
||||||
|
swiperCurrent: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 组件创建时的逻辑
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
componentRefresh(newValue) {
|
||||||
|
// 监听组件刷新
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
componentStyle() {
|
||||||
|
let style = '';
|
||||||
|
style += 'background-color:' + this.value.componentBgColor + ';';
|
||||||
|
|
||||||
|
if (this.value.componentAngle == 'round') {
|
||||||
|
style += 'border-top-left-radius:' + (2 * this.value.topAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-top-right-radius:' + (2 * this.value.topAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-bottom-left-radius:' + (2 * this.value.bottomAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-bottom-right-radius:' + (2 * this.value.bottomAroundRadius) + 'rpx;';
|
||||||
|
}
|
||||||
|
|
||||||
|
style += 'box-shadow:' + (this.value.ornament.type == 'shadow' ? '0 0 10rpx ' + this.value.ornament.color : '') + ';';
|
||||||
|
style += 'border:' + (this.value.ornament.type == 'stroke' ? '2rpx solid ' + this.value.ornament.color : '') + ';';
|
||||||
|
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
|
swiperHeight() {
|
||||||
|
let height = 0;
|
||||||
|
|
||||||
|
if (this.value.mode == 'graphic') {
|
||||||
|
height = (49 + this.value.imageSize) * this.value.pageCount;
|
||||||
|
} else if (this.value.mode == 'img') {
|
||||||
|
height = (22 + this.value.imageSize) * this.value.pageCount;
|
||||||
|
} else if (this.value.mode == 'text') {
|
||||||
|
height = 43 * this.value.pageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'height:' + (2 * height) + 'rpx';
|
||||||
|
},
|
||||||
|
|
||||||
|
isIndicatorDots() {
|
||||||
|
return this.value.carousel.type != 'hide' &&
|
||||||
|
1 != Math.ceil(this.value.list.length / (this.value.pageCount * this.value.rowCount));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 预览图片
|
||||||
|
previewImg(imageUrl) {
|
||||||
|
uni.previewImage({
|
||||||
|
current: 0,
|
||||||
|
urls: [this.$util.img(imageUrl)],
|
||||||
|
success: (res) => {},
|
||||||
|
fail: (res) => {},
|
||||||
|
complete: (res) => {}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 页面跳转
|
||||||
|
redirectTo(link) {
|
||||||
|
if (!link.wap_url || this.$util.getCurrRoute() != 'pages/member/index' || this.storeToken) {
|
||||||
|
this.$util.diyRedirectTo(link);
|
||||||
|
} else {
|
||||||
|
this.$refs.login.open(link.wap_url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 轮播切换
|
||||||
|
swiperChange(event) {
|
||||||
|
this.swiperCurrent = event.detail.current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.image-nav {
|
||||||
|
padding: 16rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&.fixed-layout {
|
||||||
|
.uni-scroll-view-content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.singleSlide {
|
||||||
|
.uni-scroll-view-content {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-nav-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pageSlide {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.uni-swiper-dots-horizontal {
|
||||||
|
bottom: 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.straightLine {
|
||||||
|
.uni-swiper-dot {
|
||||||
|
width: 30rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
.uni-swiper-dot {
|
||||||
|
width: 14rpx;
|
||||||
|
height: 14rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-nav-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-nav-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14rpx 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.image-text {
|
||||||
|
padding-top: 12rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.alone {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.text {
|
||||||
|
.image-text {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-img {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 90rpx;
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
position: absolute;
|
||||||
|
top: -10rpx;
|
||||||
|
right: -24rpx;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
-webkit-transform: scale(0.8);
|
||||||
|
transform: scale(0.8);
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 50rpx;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-dot-box {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: -20rpx;
|
||||||
|
padding-bottom: 8rpx;
|
||||||
|
|
||||||
|
.swiper-dot {
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
margin: 8rpx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.straightLine {
|
||||||
|
.swiper-dot {
|
||||||
|
width: 30rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
.swiper-dot {
|
||||||
|
width: 15rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 15rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
704
components/diy-components/diy-video-list.vue
Normal file
704
components/diy-components/diy-video-list.vue
Normal file
@@ -0,0 +1,704 @@
|
|||||||
|
<template>
|
||||||
|
<view :style="componentStyle">
|
||||||
|
<!-- 固定布局模式 -->
|
||||||
|
<view v-if="value.showStyle == 'fixed'" :class="['goods-list', 'row1-of' + value.rowCount]" style="padding:20rpx;">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in value.list"
|
||||||
|
:key="index"
|
||||||
|
class="goods-item"
|
||||||
|
@tap="showVideo(item)"
|
||||||
|
>
|
||||||
|
<view class="goods-img-wrap">
|
||||||
|
<image
|
||||||
|
class="goods-img"
|
||||||
|
style="border-radius:10rpx 10rpx 0 0;"
|
||||||
|
:src="$util.img(item.imageUrl)"
|
||||||
|
mode="widthFix"
|
||||||
|
@error="imgError(index)"
|
||||||
|
></image>
|
||||||
|
<view style="position:absolute;top:10rpx;right:10rpx;">
|
||||||
|
<image style="width:30rpx;" :src="$util.img('addon/personnel/shop/view/enterprise/play.png')" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="info-wrap">
|
||||||
|
<view
|
||||||
|
class="goods-name"
|
||||||
|
:style="{
|
||||||
|
'font-size': (value.font.size * 2 + 'rpx') + ';',
|
||||||
|
'font-weight': value.font.weight + ';',
|
||||||
|
'color': value.font.color + ';'
|
||||||
|
}"
|
||||||
|
>{{ item.title }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 其他布局模式 -->
|
||||||
|
<scroll-view
|
||||||
|
v-else
|
||||||
|
:class="['video-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle]"
|
||||||
|
:scroll-x="value.showStyle == 'singleSlide'"
|
||||||
|
>
|
||||||
|
<view class="uni-scroll-view-content">
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in value.list"
|
||||||
|
:key="index"
|
||||||
|
:class="['video-nav-item', value.mode]"
|
||||||
|
:style="{ width: (100 / value.rowCount + '%') + ';' }"
|
||||||
|
@tap="showVideo(item)"
|
||||||
|
>
|
||||||
|
<view class="video-img">
|
||||||
|
<image
|
||||||
|
v-if="item.iconType == 'img'"
|
||||||
|
:style="{
|
||||||
|
'max-width': '200rpx;',
|
||||||
|
'max-height': '200rpx;',
|
||||||
|
'border-radius': '8rpx;'
|
||||||
|
}"
|
||||||
|
:src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
||||||
|
mode="widthFix"
|
||||||
|
:show-menu-by-longpress="true"
|
||||||
|
></image>
|
||||||
|
<view style="position:absolute;top:10rpx;right:10rpx;">
|
||||||
|
<image style="width:30rpx;" :src="$util.img('addon/personnel/shop/view/enterprise/play.png')" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="video-text"
|
||||||
|
:style="{
|
||||||
|
'margin-left': '16rpx;',
|
||||||
|
'font-size': (value.font.size * 2 + 'rpx') + ';',
|
||||||
|
'font-weight': value.font.weight + ';',
|
||||||
|
'color': value.font.color + ';'
|
||||||
|
}"
|
||||||
|
>{{ item.title }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 视频播放弹窗 -->
|
||||||
|
<uni-popup
|
||||||
|
ref="videoPopup"
|
||||||
|
type="center"
|
||||||
|
style="background:transparent;width:100%;height:100%;"
|
||||||
|
>
|
||||||
|
<view class="video-container" style="position:fixed;top:30%;width:100%;left:0;">
|
||||||
|
<video
|
||||||
|
class="adaptive-video"
|
||||||
|
:autoPauseIfNavigate="true"
|
||||||
|
:autoPauseIfOpenNative="true"
|
||||||
|
:autoplay="false"
|
||||||
|
:enableAutoRotation="true"
|
||||||
|
id="myVideo"
|
||||||
|
:src="video_url"
|
||||||
|
:controls="true"
|
||||||
|
></video>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import uniPopup from '@/components/uni-popup/uni-popup.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'diy-video-list',
|
||||||
|
components: {
|
||||||
|
uniPopup
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageWidth: '',
|
||||||
|
indicatorDots: false,
|
||||||
|
swiperCurrent: 0,
|
||||||
|
video_url: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 组件创建时的逻辑
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
componentRefresh(newValue) {
|
||||||
|
// 监听组件刷新
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
componentStyle() {
|
||||||
|
let style = '';
|
||||||
|
style += 'background-color:' + this.value.componentBgColor + ';';
|
||||||
|
|
||||||
|
if (this.value.componentAngle == 'round') {
|
||||||
|
style += 'border-top-left-radius:' + (2 * this.value.topAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-top-right-radius:' + (2 * this.value.topAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-bottom-left-radius:' + (2 * this.value.bottomAroundRadius) + 'rpx;';
|
||||||
|
style += 'border-bottom-right-radius:' + (2 * this.value.bottomAroundRadius) + 'rpx;';
|
||||||
|
}
|
||||||
|
|
||||||
|
style += 'box-shadow:' + (this.value.ornament.type == 'shadow' ? '0 0 10rpx ' + this.value.ornament.color : '') + ';';
|
||||||
|
style += 'border:' + (this.value.ornament.type == 'stroke' ? '2rpx solid ' + this.value.ornament.color : '') + ';';
|
||||||
|
|
||||||
|
console.log(this.value);
|
||||||
|
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
|
swiperHeight() {
|
||||||
|
let height = 0;
|
||||||
|
|
||||||
|
if (this.value.mode == 'graphic') {
|
||||||
|
height = (49 + this.value.imageSize) * this.value.pageCount;
|
||||||
|
} else if (this.value.mode == 'img') {
|
||||||
|
height = (22 + this.value.imageSize) * this.value.pageCount;
|
||||||
|
} else if (this.value.mode == 'text') {
|
||||||
|
height = 43 * this.value.pageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'height:' + (2 * height) + 'rpx';
|
||||||
|
},
|
||||||
|
|
||||||
|
isIndicatorDots() {
|
||||||
|
return this.value.carousel.type != 'hide' &&
|
||||||
|
1 != Math.ceil(this.value.list.length / (this.value.pageCount * this.value.rowCount));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 显示视频播放弹窗
|
||||||
|
showVideo(item) {
|
||||||
|
this.video_url = item.videoUrl;
|
||||||
|
this.$refs.videoPopup.open();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 图片加载错误处理
|
||||||
|
imgError(index) {
|
||||||
|
// 图片加载失败的处理逻辑
|
||||||
|
console.log('图片加载失败:', index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.goods-name {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-list {
|
||||||
|
&.row1-of3 {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.goods-item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
width: calc(33.3333333% - 14rpx);
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:nth-child(3n + 3) {
|
||||||
|
width: calc(33.33% - 15rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(1), &:nth-of-type(2), &:nth-of-type(3) {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3n) {
|
||||||
|
width: calc(33.3333333% - 15rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3n-1) {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.shadow {
|
||||||
|
width: calc(33.3333333% - 18rpx);
|
||||||
|
|
||||||
|
&:nth-of-type(1), &:nth-of-type(2), &:nth-of-type(3) {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(1n) {
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3n-1) {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3n) {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-img-wrap {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 220rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.pro-info {
|
||||||
|
margin-top: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.discount-price {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.price-wrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
font-size: 24rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
font-size: 32rpx;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-price {
|
||||||
|
text-decoration: line-through;
|
||||||
|
flex: 1;
|
||||||
|
line-height: 28rpx;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-1 {
|
||||||
|
.pro-info {
|
||||||
|
.price-wrap {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-price {
|
||||||
|
justify-content: unset !important;
|
||||||
|
align-items: baseline !important;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-price {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-2 {
|
||||||
|
.pro-info {
|
||||||
|
position: relative;
|
||||||
|
flex-direction: row !important;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.price-wrap {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-price {
|
||||||
|
align-items: flex-end !important;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-price {
|
||||||
|
margin: 20rpx 0;
|
||||||
|
flex-basis: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-btn {
|
||||||
|
min-width: 112rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
line-height: 52rpx;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sell-out {
|
||||||
|
text {
|
||||||
|
font-size: 150rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.row1-of2 {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.goods-item {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
width: calc(50% - 10rpx);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:nth-child(2n) {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(1), &:nth-of-type(2) {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.shadow {
|
||||||
|
width: calc(50% - 18rpx);
|
||||||
|
|
||||||
|
&:nth-child(2n-1) {
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2n) {
|
||||||
|
margin-right: 8rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(1), &:nth-of-type(2) {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-img-wrap {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 340rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.sale {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pro-info {
|
||||||
|
margin-top: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.discount-price {
|
||||||
|
.price-wrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 24rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 32rpx !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-price {
|
||||||
|
text-decoration: line-through;
|
||||||
|
flex: 1;
|
||||||
|
line-height: 28rpx;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-1 {
|
||||||
|
.pro-info {
|
||||||
|
.discount-price {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
|
.price-wrap {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-price {
|
||||||
|
margin-top: 6rpx;
|
||||||
|
flex-basis: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-2 {
|
||||||
|
.pro-info {
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.price-wrap {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-price {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-price {
|
||||||
|
margin-top: 4rpx;
|
||||||
|
flex-basis: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sale {
|
||||||
|
line-height: 1;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-btn {
|
||||||
|
min-width: 140rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
line-height: 52rpx;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.style-3 {
|
||||||
|
.pro-info {
|
||||||
|
.member-price {
|
||||||
|
margin-right: auto;
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-bottom: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sale {
|
||||||
|
line-height: 1;
|
||||||
|
align-self: center;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount-price {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
align-content: center;
|
||||||
|
|
||||||
|
.price-wrap {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
line-height: 1;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sell-out {
|
||||||
|
text {
|
||||||
|
font-size: 250rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adaptive-video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-nav {
|
||||||
|
padding: 16rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&.fixed-layout {
|
||||||
|
.uni-scroll-view-content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.singleSlide {
|
||||||
|
.uni-scroll-view-content {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-nav-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pageSlide {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.uni-swiper-dots-horizontal {
|
||||||
|
bottom: 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.straightLine {
|
||||||
|
.uni-swiper-dot {
|
||||||
|
width: 30rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
.uni-swiper-dot {
|
||||||
|
width: 14rpx;
|
||||||
|
height: 14rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-nav-wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-nav-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14rpx 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.video-text {
|
||||||
|
padding-top: 12rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.alone {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.text {
|
||||||
|
.video-text {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-img {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 90rpx;
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
position: absolute;
|
||||||
|
top: -10rpx;
|
||||||
|
right: -24rpx;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
-webkit-transform: scale(0.8);
|
||||||
|
transform: scale(0.8);
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 50rpx;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-dot-box {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: -20rpx;
|
||||||
|
padding-bottom: 8rpx;
|
||||||
|
|
||||||
|
.swiper-dot {
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
margin: 8rpx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.straightLine {
|
||||||
|
.swiper-dot {
|
||||||
|
width: 30rpx;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
.swiper-dot {
|
||||||
|
width: 15rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 15rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
25
components/ns-mp-html/ns-mp-html.vue
Normal file
25
components/ns-mp-html/ns-mp-html.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<view class="mp-html">
|
||||||
|
<mp-html :content="content"></mp-html>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
content: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.mp-html{
|
||||||
|
/deep/ img{
|
||||||
|
width:100% !important;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
933
components/ns-newform/ns-newform.vue
Normal file
933
components/ns-newform/ns-newform.vue
Normal file
@@ -0,0 +1,933 @@
|
|||||||
|
<template>
|
||||||
|
<view class="form-wrap form-component">
|
||||||
|
<view v-for="(item, index) in formData" :key="index">
|
||||||
|
<!-- 文本输入框 -->
|
||||||
|
<view v-if="item.controller == 'Text'" class="order-wrap">
|
||||||
|
<view class="order-cell">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
:placeholder="item.value.placeholder"
|
||||||
|
placeholder-class="placeholder color-tip"
|
||||||
|
v-model="item.val"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 多行文本输入框 -->
|
||||||
|
<view v-if="item.controller == 'Textarea'" class="order-wrap">
|
||||||
|
<view class="order-cell flex-box textarea">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box">
|
||||||
|
<textarea
|
||||||
|
:placeholder="item.value.placeholder"
|
||||||
|
placeholder-class="placeholder color-tip"
|
||||||
|
v-model="item.val"
|
||||||
|
></textarea>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 下拉选择器 -->
|
||||||
|
<view v-if="item.controller == 'Select'" class="order-wrap">
|
||||||
|
<picker
|
||||||
|
mode="selector"
|
||||||
|
:range="item.value.options"
|
||||||
|
@change="pickerChange($event, index)"
|
||||||
|
>
|
||||||
|
<view class="order-cell">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box">
|
||||||
|
<text v-if="item.val != ''">{{ item.val }}</text>
|
||||||
|
<text v-else class="color-tip">请选择</text>
|
||||||
|
</view>
|
||||||
|
<text class="iconfont icon-right"></text>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 复选框 -->
|
||||||
|
<view v-if="item.controller == 'Checkbox'" class="order-wrap">
|
||||||
|
<view class="order-cell">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box check-group-box">
|
||||||
|
<checkbox-group @change="checkboxChange($event, index)">
|
||||||
|
<label v-for="(v, k) in item.option_lists" :key="k">
|
||||||
|
<checkbox :value="v.value" :checked="v.checked"></checkbox>
|
||||||
|
<view class="checkbox">
|
||||||
|
<text
|
||||||
|
:class="[
|
||||||
|
'iconfont',
|
||||||
|
!v.checked ? 'icon-fuxuankuang2' : '',
|
||||||
|
v.checked ? 'icon-fuxuankuang1 color-base-text' : ''
|
||||||
|
]"
|
||||||
|
></text>
|
||||||
|
{{ v.value }}
|
||||||
|
</view>
|
||||||
|
</label>
|
||||||
|
</checkbox-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 单选框 -->
|
||||||
|
<view v-if="item.controller == 'Radio'" class="order-wrap">
|
||||||
|
<view class="order-cell">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box radio-group-box">
|
||||||
|
<radio-group @change="radioChange($event, index)">
|
||||||
|
<label v-for="(v, k) in item.option_lists" :key="k">
|
||||||
|
<radio :value="v.value" :checked="item.val == v.value"></radio>
|
||||||
|
<view class="radio-box">
|
||||||
|
<text
|
||||||
|
:class="[
|
||||||
|
'iconfont',
|
||||||
|
item.val != v.value ? 'icon-yuan_checkbox' : '',
|
||||||
|
item.val == v.value ? 'icon-yuan_checked color-base-text' : ''
|
||||||
|
]"
|
||||||
|
></text>
|
||||||
|
{{ v.value }}
|
||||||
|
</view>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 图片上传 -->
|
||||||
|
<view v-if="item.controller == 'Img'" class="order-wrap">
|
||||||
|
<view class="order-cell flex-box">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box img-boxs">
|
||||||
|
<view v-for="(v, k) in item.img_lists" :key="k" class="img-box" @tap="uploadImg(index)">
|
||||||
|
<image :src="$util.img(v)" mode="aspectFill"></image>
|
||||||
|
<text class="iconfont icon-guanbi" @tap.stop="delImg(k, index)"></text>
|
||||||
|
</view>
|
||||||
|
<view class="img-box" @tap="addImg(index)">
|
||||||
|
<text class="iconfont icon-add1"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 日期选择器 -->
|
||||||
|
<view v-if="item.controller == 'Date'" class="order-wrap">
|
||||||
|
<view class="order-cell">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box box-flex">
|
||||||
|
<picker
|
||||||
|
mode="date"
|
||||||
|
:value="item.val"
|
||||||
|
@change="bindDateChange($event, index)"
|
||||||
|
>
|
||||||
|
<view :class="['uni-input', !item.val ? 'color-tip' : '']">
|
||||||
|
{{ item.val ? item.val : item.value.placeholder }}
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<text class="iconfont icon-right"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 日期范围选择器 -->
|
||||||
|
<view v-if="item.controller == 'Datelimit'" class="order-wrap">
|
||||||
|
<view class="order-cell flex-box">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box date-boxs">
|
||||||
|
<view class="date-box">
|
||||||
|
<picker
|
||||||
|
mode="date"
|
||||||
|
:value="item.start_date"
|
||||||
|
@change="bindStartDateChange($event, index)"
|
||||||
|
>
|
||||||
|
<view class="picker-box">
|
||||||
|
<view :class="['uni-input', !item.start_date ? 'color-tip' : '']">
|
||||||
|
{{ item.start_date ? item.start_date : item.value.placeholder_start }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="interval iconfont icon-jian"></view>
|
||||||
|
<view class="date-box">
|
||||||
|
<picker
|
||||||
|
mode="date"
|
||||||
|
:value="item.end_date"
|
||||||
|
@change="bindEndDateChange($event, index)"
|
||||||
|
>
|
||||||
|
<view class="picker-box">
|
||||||
|
<view :class="['uni-input', !item.end_date ? 'color-tip' : '']">
|
||||||
|
{{ item.end_date ? item.end_date : item.value.placeholder_end }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 时间选择器 -->
|
||||||
|
<view v-if="item.controller == 'Time'" class="order-wrap">
|
||||||
|
<view class="order-cell">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box box-flex">
|
||||||
|
<picker
|
||||||
|
mode="time"
|
||||||
|
:value="item.val"
|
||||||
|
@change="bindTimeChange($event, index)"
|
||||||
|
>
|
||||||
|
<view :class="['uni-input', !item.val ? 'color-tip' : '']">
|
||||||
|
{{ item.val ? item.val : item.value.placeholder }}
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<text class="iconfont icon-right"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 时间范围选择器 -->
|
||||||
|
<view v-if="item.controller == 'Timelimit'" class="order-wrap">
|
||||||
|
<view class="order-cell flex-box">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box date-boxs">
|
||||||
|
<view class="date-box">
|
||||||
|
<picker
|
||||||
|
mode="time"
|
||||||
|
:value="item.start_time"
|
||||||
|
@change="bindStartTimeChange($event, index)"
|
||||||
|
>
|
||||||
|
<view class="picker-box">
|
||||||
|
<view :class="['uni-input', !item.start_time ? 'color-tip' : '']">
|
||||||
|
{{ item.start_time ? item.start_time : item.value.placeholder_start }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="interval iconfont icon-jian"></view>
|
||||||
|
<view class="date-box">
|
||||||
|
<picker
|
||||||
|
mode="time"
|
||||||
|
:value="item.end_time"
|
||||||
|
@change="bindEndTimeChange($event, index)"
|
||||||
|
>
|
||||||
|
<view class="picker-box">
|
||||||
|
<view :class="['uni-input', !item.end_time ? 'color-tip' : '']">
|
||||||
|
{{ item.end_time ? item.end_time : item.value.placeholder_end }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 城市选择器 -->
|
||||||
|
<view v-if="item.controller == 'City'" class="order-wrap">
|
||||||
|
<view class="order-cell box-flex">
|
||||||
|
<view class="name">
|
||||||
|
<text class="tit">{{ item.value.title }}</text>
|
||||||
|
<text class="required">{{ item.value.required ? '*' : '' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box">
|
||||||
|
<pick-regions
|
||||||
|
:defaultRegions="item.default_regions"
|
||||||
|
:selectArr="item.select_arr"
|
||||||
|
@getRegions="handleGetRegions($event, index)"
|
||||||
|
>
|
||||||
|
<view :class="['select-address', !item.val ? 'empty' : '', !item.val ? 'color-tip' : '']">
|
||||||
|
{{ item.val ? item.val : (item.select_arr == '2' ? '请选择省市' : '请选择省市区/县') }}
|
||||||
|
</view>
|
||||||
|
</pick-regions>
|
||||||
|
</view>
|
||||||
|
<text class="iconfont icon-right"></text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import pickRegions from '@/components/pick-regions/pick-regions.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ns-form',
|
||||||
|
components: {
|
||||||
|
pickRegions
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
customAttr: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: this.data
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.setFormData();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
data: {
|
||||||
|
handler() {
|
||||||
|
this.setFormData();
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setFormData() {
|
||||||
|
this.formData = this.data;
|
||||||
|
this.formData.forEach((item) => {
|
||||||
|
// 初始化默认值
|
||||||
|
if (!item.val) {
|
||||||
|
item.val = item.value.default ? item.value.default : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理选项列表
|
||||||
|
if (item.value.options) {
|
||||||
|
item.option_lists = [];
|
||||||
|
item.value.options.forEach((option, index) => {
|
||||||
|
let optionItem = {};
|
||||||
|
optionItem.value = option;
|
||||||
|
optionItem.checked = false;
|
||||||
|
|
||||||
|
if (item.controller == 'Radio') {
|
||||||
|
if ((!item.val && index == 0) || (item.val && item.val == option)) {
|
||||||
|
optionItem.checked = true;
|
||||||
|
item.val = option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.controller == 'Checkbox' && item.val) {
|
||||||
|
let valArray = item.val.split(',');
|
||||||
|
optionItem.checked = valArray.indexOf(option) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.option_lists.push(optionItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理图片列表
|
||||||
|
if (item.controller == 'Img') {
|
||||||
|
item.img_lists = item.val ? item.val.split(',') : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理日期
|
||||||
|
if (item.controller == 'Date' && !item.val) {
|
||||||
|
if (item.value.is_show_default) {
|
||||||
|
if (item.value.is_current) {
|
||||||
|
item.val = this.getDate();
|
||||||
|
} else {
|
||||||
|
item.val = item.value.default;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.val = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理日期范围
|
||||||
|
if (item.controller == 'Datelimit') {
|
||||||
|
if (item.val) {
|
||||||
|
let dateArray = item.val.split(' - ');
|
||||||
|
item.start_date = dateArray[0];
|
||||||
|
item.end_date = dateArray[1];
|
||||||
|
} else {
|
||||||
|
item.val = '';
|
||||||
|
|
||||||
|
// 开始日期
|
||||||
|
if (item.value.is_show_default_start) {
|
||||||
|
if (item.value.is_current_start) {
|
||||||
|
item.start_date = this.getDate();
|
||||||
|
} else {
|
||||||
|
item.start_date = item.value.default_start;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.start_date = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结束日期
|
||||||
|
if (item.value.is_show_default_end) {
|
||||||
|
if (item.value.is_current_end) {
|
||||||
|
item.end_date = this.getDate();
|
||||||
|
} else {
|
||||||
|
item.end_date = item.value.default_end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.end_date = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.start_date && item.end_date) {
|
||||||
|
item.val = item.start_date + ' - ' + item.end_date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时间
|
||||||
|
if (item.controller == 'Time' && !item.val) {
|
||||||
|
if (item.value.is_show_default) {
|
||||||
|
if (item.value.is_current) {
|
||||||
|
item.val = this.getTime();
|
||||||
|
} else {
|
||||||
|
item.val = item.value.default;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.val = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时间范围
|
||||||
|
if (item.controller == 'Timelimit') {
|
||||||
|
if (item.val) {
|
||||||
|
let timeArray = item.val.split(' - ');
|
||||||
|
item.start_time = timeArray[0];
|
||||||
|
item.end_time = timeArray[1];
|
||||||
|
} else {
|
||||||
|
item.val = '';
|
||||||
|
|
||||||
|
// 开始时间
|
||||||
|
if (item.value.is_show_default_start) {
|
||||||
|
if (item.value.is_current_start) {
|
||||||
|
item.start_time = this.getTime();
|
||||||
|
} else {
|
||||||
|
item.start_time = item.value.default_start;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.start_time = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结束时间
|
||||||
|
if (item.value.is_show_default_end) {
|
||||||
|
if (item.value.is_current_end) {
|
||||||
|
item.end_time = this.getTime();
|
||||||
|
} else {
|
||||||
|
item.end_time = item.value.default_end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.end_time = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.start_time && item.end_time) {
|
||||||
|
item.val = item.start_time + ' - ' + item.end_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理城市选择
|
||||||
|
if (item.controller == 'City') {
|
||||||
|
item.full_address = '';
|
||||||
|
item.select_arr = item.value.default_type == 1 ? '2' : '3';
|
||||||
|
if (item.val) {
|
||||||
|
item.default_regions = item.val.split('-');
|
||||||
|
} else {
|
||||||
|
item.default_regions = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 表单验证
|
||||||
|
verify() {
|
||||||
|
for (let i = 0; i < this.formData.length; i++) {
|
||||||
|
let item = this.formData[i];
|
||||||
|
|
||||||
|
// 文本验证
|
||||||
|
if (item.controller == 'Text') {
|
||||||
|
if (item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请输入' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.name == 'ID_CARD' && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(item.val)) {
|
||||||
|
if (!item.value.required) {
|
||||||
|
this.$util.showToast({ title: '身份证输入不合法' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (item.val != '') {
|
||||||
|
this.$util.showToast({ title: '身份证输入不合法' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.name == 'MOBILE' && !this.$util.verifyMobile(item.val)) {
|
||||||
|
if (!item.value.required) {
|
||||||
|
this.$util.showToast({ title: '手机号输入不合法' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (item.val != '') {
|
||||||
|
this.$util.showToast({ title: '手机号输入不合法' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多行文本验证
|
||||||
|
if (item.controller == 'Textarea' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请输入' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉选择验证
|
||||||
|
if (item.controller == 'Select' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复选框验证
|
||||||
|
if (item.controller == 'Checkbox' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请至少选择一个' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片上传验证
|
||||||
|
if (item.controller == 'Img' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请至少上传一张' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期验证
|
||||||
|
if (item.controller == 'Date' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期范围验证
|
||||||
|
if (item.controller == 'Datelimit') {
|
||||||
|
if (item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.$util.timeTurnTimeStamp(item.start_date) > this.$util.timeTurnTimeStamp(item.end_date)) {
|
||||||
|
this.$util.showToast({ title: '结束日期不能小于开始日期' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间验证
|
||||||
|
if (item.controller == 'Time' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间范围验证
|
||||||
|
if (item.controller == 'Timelimit') {
|
||||||
|
if (item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.start_time >= item.end_time) {
|
||||||
|
this.$util.showToast({ title: '结束时间必须大于开始时间' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 城市选择验证
|
||||||
|
if (item.controller == 'City' && item.value.required && !item.val) {
|
||||||
|
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.formData;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下拉选择改变
|
||||||
|
pickerChange(event, index) {
|
||||||
|
this.formData[index].val = this.data[index].value.options[event.detail.value];
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 复选框改变
|
||||||
|
checkboxChange(event, index) {
|
||||||
|
this.formData[index].val = event.detail.value.toString();
|
||||||
|
this.formData[index].option_lists.forEach((option) => {
|
||||||
|
option.checked = event.detail.value.indexOf(option.value) != -1;
|
||||||
|
});
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 单选框改变
|
||||||
|
radioChange(event, index) {
|
||||||
|
this.formData[index].val = event.detail.value;
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上传图片
|
||||||
|
uploadImg(index) {
|
||||||
|
let self = this;
|
||||||
|
this.$util.upload(Number(this.formData[index].value.max_count), { path: 'evaluateimg' }, function(res) {
|
||||||
|
if (res.length > 0) {
|
||||||
|
res.forEach(function(img) {
|
||||||
|
if (self.formData[index].img_lists.length >= Number(self.formData[index].value.max_count)) {
|
||||||
|
self.$util.showToast({ title: '最多上传' + self.formData[index].value.max_count + '张图片' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.formData[index].img_lists.push(img);
|
||||||
|
});
|
||||||
|
self.formData[index].val = self.formData[index].img_lists.toString();
|
||||||
|
self.$forceUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加图片
|
||||||
|
addImg(index) {
|
||||||
|
let self = this;
|
||||||
|
if (this.formData[index].img_lists.length >= Number(this.formData[index].value.max_count)) {
|
||||||
|
this.$util.showToast({ title: '最多上传' + this.formData[index].value.max_count + '张图片' });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$util.upload(Number(this.formData[index].value.max_count), { path: 'evaluateimg' }, function(res) {
|
||||||
|
if (res.length > 0) {
|
||||||
|
res.forEach(function(img) {
|
||||||
|
self.formData[index].img_lists.push(img);
|
||||||
|
});
|
||||||
|
self.formData[index].val = self.formData[index].img_lists.toString();
|
||||||
|
self.$forceUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除图片
|
||||||
|
delImg(imgIndex, formIndex) {
|
||||||
|
this.formData[formIndex].img_lists.splice(imgIndex, 1);
|
||||||
|
this.formData[formIndex].val = this.formData[formIndex].img_lists.toString();
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取当前日期
|
||||||
|
getDate() {
|
||||||
|
let date = new Date();
|
||||||
|
let year = date.getFullYear();
|
||||||
|
let month = date.getMonth() + 1;
|
||||||
|
let day = date.getDate();
|
||||||
|
month = month > 9 ? month : '0' + month;
|
||||||
|
day = day > 9 ? day : '0' + day;
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取当前时间
|
||||||
|
getTime() {
|
||||||
|
let date = new Date();
|
||||||
|
let hours = date.getHours();
|
||||||
|
let minutes = date.getMinutes();
|
||||||
|
hours = hours > 9 ? hours : '0' + hours;
|
||||||
|
minutes = minutes > 9 ? minutes : '0' + minutes;
|
||||||
|
return `${hours}:${minutes}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 日期改变
|
||||||
|
bindDateChange(event, index) {
|
||||||
|
this.formData[index].val = event.detail.value;
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 开始日期改变
|
||||||
|
bindStartDateChange(event, index) {
|
||||||
|
this.$set(this.formData[index], 'start_date', event.detail.value);
|
||||||
|
this.$set(this.formData[index], 'val', this.formData[index].start_date + ' - ' + this.formData[index].end_date);
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 结束日期改变
|
||||||
|
bindEndDateChange(event, index) {
|
||||||
|
this.$set(this.formData[index], 'end_date', event.detail.value);
|
||||||
|
this.$set(this.formData[index], 'val', this.formData[index].start_date + ' - ' + this.formData[index].end_date);
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 时间改变
|
||||||
|
bindTimeChange(event, index) {
|
||||||
|
this.formData[index].val = event.detail.value;
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 开始时间改变
|
||||||
|
bindStartTimeChange(event, index) {
|
||||||
|
this.formData[index].start_time = event.detail.value;
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 结束时间改变
|
||||||
|
bindEndTimeChange(event, index) {
|
||||||
|
this.formData[index].end_time = event.detail.value;
|
||||||
|
this.formData[index].val = this.formData[index].start_time + ' - ' + this.formData[index].end_time;
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理地区选择
|
||||||
|
handleGetRegions(regions, index) {
|
||||||
|
this.formData[index].val = '';
|
||||||
|
this.formData[index].val += regions[0] != undefined ? regions[0].label : '';
|
||||||
|
this.formData[index].val += regions[1] != undefined ? '-' + regions[1].label : '';
|
||||||
|
this.formData[index].val += regions[2] != undefined ? '-' + regions[2].label : '';
|
||||||
|
this.$forceUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.order-wrap {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-cell {
|
||||||
|
align-items: center;
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.textarea {
|
||||||
|
align-items: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.clear-flex {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
.box {
|
||||||
|
margin-top: 16rpx;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: solid 1px #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.align-top {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
width: 160rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.tit {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #888;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.required {
|
||||||
|
color: red;
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-left: 4rpx;
|
||||||
|
width: 14rpx;
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 0rpx;
|
||||||
|
line-height: inherit;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: left;
|
||||||
|
height: 70rpx;
|
||||||
|
border: solid 2rpx #eee;
|
||||||
|
line-height: 70rpx;
|
||||||
|
padding: 0 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
font-size: 28rpx;
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 44rpx;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.img-boxs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
margin: 10rpx 20rpx 10rpx 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
border: 1rpx solid #eee;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.icon-guanbi {
|
||||||
|
position: absolute;
|
||||||
|
top: -14rpx;
|
||||||
|
right: -14rpx;
|
||||||
|
display: inline-block;
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
line-height: 28rpx;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-add1 {
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.box-flex {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.date-boxs {
|
||||||
|
padding: 0 10rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.interval {
|
||||||
|
margin: 0 12rpx;
|
||||||
|
color: #000;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-box {
|
||||||
|
.picker-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group-box {
|
||||||
|
radio {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-group-box {
|
||||||
|
checkbox {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 32rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-flex {
|
||||||
|
picker {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-right {
|
||||||
|
line-height: 1;
|
||||||
|
position: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
218
components/uv-count-to/uv-count-to.vue
Normal file
218
components/uv-count-to/uv-count-to.vue
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
<template>
|
||||||
|
<text
|
||||||
|
class="uv-count-num"
|
||||||
|
:style="textStyle"
|
||||||
|
>
|
||||||
|
{{ displayValue }}
|
||||||
|
</text>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'uv-count-to',
|
||||||
|
props: {
|
||||||
|
startVal: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
endVal: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 2000
|
||||||
|
},
|
||||||
|
autoplay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
decimals: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
useEasing: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
decimal: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: '.'
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#606266'
|
||||||
|
},
|
||||||
|
fontSize: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 22
|
||||||
|
},
|
||||||
|
bold: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
localStartVal: this.startVal,
|
||||||
|
displayValue: this.formatNumber(this.startVal),
|
||||||
|
printVal: null,
|
||||||
|
paused: false,
|
||||||
|
localDuration: Number(this.duration),
|
||||||
|
startTime: null,
|
||||||
|
timestamp: null,
|
||||||
|
remaining: null,
|
||||||
|
rAF: null,
|
||||||
|
lastTime: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
countDown() {
|
||||||
|
return this.startVal > this.endVal
|
||||||
|
},
|
||||||
|
textStyle() {
|
||||||
|
return {
|
||||||
|
fontSize: this.fontSize + 'px',
|
||||||
|
fontWeight: this.bold ? 'bold' : 'normal',
|
||||||
|
color: this.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
startVal() {
|
||||||
|
if (this.autoplay) {
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
endVal() {
|
||||||
|
console.log(123)
|
||||||
|
if (this.autoplay) {
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.autoplay) {
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
easingFn(t, b, c, d) {
|
||||||
|
return c * (1 - Math.pow(2, -10 * t / d)) * 1024 / 1023 + b
|
||||||
|
},
|
||||||
|
requestAnimationFrame(callback) {
|
||||||
|
const currTime = new Date().getTime()
|
||||||
|
const timeToCall = Math.max(0, 16 - (currTime - this.lastTime))
|
||||||
|
const id = setTimeout(() => {
|
||||||
|
callback(currTime + timeToCall)
|
||||||
|
}, timeToCall)
|
||||||
|
this.lastTime = currTime + timeToCall
|
||||||
|
return id
|
||||||
|
},
|
||||||
|
cancelAnimationFrame(id) {
|
||||||
|
clearTimeout(id)
|
||||||
|
},
|
||||||
|
start() {
|
||||||
|
this.localStartVal = this.startVal
|
||||||
|
this.startTime = null
|
||||||
|
this.localDuration = this.duration
|
||||||
|
this.paused = false
|
||||||
|
this.rAF = this.requestAnimationFrame(this.count)
|
||||||
|
},
|
||||||
|
restart() {
|
||||||
|
if (this.paused) {
|
||||||
|
this.resume()
|
||||||
|
this.paused = false
|
||||||
|
} else {
|
||||||
|
this.stop()
|
||||||
|
this.paused = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stop() {
|
||||||
|
this.cancelAnimationFrame(this.rAF)
|
||||||
|
this.paused = true
|
||||||
|
},
|
||||||
|
resume() {
|
||||||
|
if (this.remaining) {
|
||||||
|
this.startTime = 0
|
||||||
|
this.localDuration = this.remaining
|
||||||
|
this.localStartVal = this.printVal
|
||||||
|
this.requestAnimationFrame(this.count)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
this.startTime = null
|
||||||
|
this.cancelAnimationFrame(this.rAF)
|
||||||
|
this.displayValue = this.formatNumber(this.startVal)
|
||||||
|
},
|
||||||
|
count(timestamp) {
|
||||||
|
if (!this.startTime) this.startTime = timestamp
|
||||||
|
this.timestamp = timestamp
|
||||||
|
const progress = timestamp - this.startTime
|
||||||
|
this.remaining = this.localDuration - progress
|
||||||
|
|
||||||
|
if (this.useEasing) {
|
||||||
|
if (this.countDown) {
|
||||||
|
this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration)
|
||||||
|
} else {
|
||||||
|
this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.countDown) {
|
||||||
|
this.printVal = this.localStartVal - (this.localStartVal - this.endVal) * (progress / this.localDuration)
|
||||||
|
} else {
|
||||||
|
this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.countDown) {
|
||||||
|
this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal
|
||||||
|
} else {
|
||||||
|
this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal
|
||||||
|
}
|
||||||
|
|
||||||
|
this.displayValue = this.formatNumber(this.printVal) || 0
|
||||||
|
|
||||||
|
if (progress < this.localDuration) {
|
||||||
|
this.rAF = this.requestAnimationFrame(this.count)
|
||||||
|
} else {
|
||||||
|
this.$emit('end')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isNumber(val) {
|
||||||
|
return !isNaN(parseFloat(val))
|
||||||
|
},
|
||||||
|
formatNumber(num) {
|
||||||
|
num = Number(num)
|
||||||
|
num = num.toFixed(Number(this.decimals))
|
||||||
|
num += ''
|
||||||
|
const x = num.split('.')
|
||||||
|
let x1 = x[0]
|
||||||
|
const x2 = x.length > 1 ? this.decimal + x[1] : ''
|
||||||
|
const rgx = /(\d+)(\d{3})/
|
||||||
|
|
||||||
|
if (this.separator && !this.isNumber(this.separator)) {
|
||||||
|
while (rgx.test(x1)) {
|
||||||
|
x1 = x1.replace(rgx, '$1' + this.separator + '$2')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return x1 + x2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.cancelAnimationFrame(this.rAF)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.uv-count-num {
|
||||||
|
display: inline-flex;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
301
components/wxwork-contact/wxwork-contact.vue
Normal file
301
components/wxwork-contact/wxwork-contact.vue
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
<template>
|
||||||
|
<view class="wxwork-contact-wrap">
|
||||||
|
<slot></slot>
|
||||||
|
<button
|
||||||
|
type="default"
|
||||||
|
hover-class="none"
|
||||||
|
class="contact-button"
|
||||||
|
@click="addWxWorkContact">
|
||||||
|
<text class="btn-text">{{ btnText }}</text>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- 确认弹窗 -->
|
||||||
|
<uni-popup ref="confirmPopup" type="center">
|
||||||
|
<view class="confirm-popup">
|
||||||
|
<view class="popup-header">
|
||||||
|
<text>添加企业微信客服</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-body">
|
||||||
|
<text>点击确定后将跳转至企业微信,添加专业客服为您服务</text>
|
||||||
|
</view>
|
||||||
|
<view class="popup-footer">
|
||||||
|
<button class="cancel-btn" @click="closePopup">取消</button>
|
||||||
|
<button class="confirm-btn" @click="confirmAdd">确定</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { WxWork } from '@/common/js/wxwork-jssdk.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'wxwork-contact',
|
||||||
|
props: {
|
||||||
|
// 按钮文字
|
||||||
|
btnText: {
|
||||||
|
type: String,
|
||||||
|
default: '添加企业微信客服'
|
||||||
|
},
|
||||||
|
// 企业ID(必需)
|
||||||
|
corpId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
// 应用ID
|
||||||
|
agentId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 时间戳
|
||||||
|
timestamp: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 随机字符串
|
||||||
|
nonceStr: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 签名
|
||||||
|
signature: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 客服ID或活码配置ID
|
||||||
|
contactId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 活码链接
|
||||||
|
contactUrl: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 是否显示确认弹窗
|
||||||
|
showConfirm: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
wxWorkSDK: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initWxWork();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 初始化企业微信SDK
|
||||||
|
*/
|
||||||
|
initWxWork() {
|
||||||
|
try {
|
||||||
|
if (this.corpId) {
|
||||||
|
this.wxWorkSDK = new WxWork();
|
||||||
|
const initResult = this.wxWorkSDK.init({
|
||||||
|
corpId: this.corpId,
|
||||||
|
agentId: this.agentId,
|
||||||
|
timestamp: this.timestamp,
|
||||||
|
nonceStr: this.nonceStr,
|
||||||
|
signature: this.signature,
|
||||||
|
jsApiList: ['openUserProfile', 'openEnterpriseChat']
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!initResult) {
|
||||||
|
console.error('企业微信SDK初始化失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化企业微信SDK失败:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击添加企业微信客服
|
||||||
|
*/
|
||||||
|
addWxWorkContact() {
|
||||||
|
if (this.showConfirm) {
|
||||||
|
this.$refs.confirmPopup.open();
|
||||||
|
} else {
|
||||||
|
this.confirmAdd();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认添加
|
||||||
|
*/
|
||||||
|
confirmAdd() {
|
||||||
|
this.closePopup();
|
||||||
|
|
||||||
|
// 直接使用props传递的配置
|
||||||
|
const contactUrl = this.contactUrl;
|
||||||
|
const contactId = this.contactId;
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
if (contactUrl) {
|
||||||
|
// 方案1:直接跳转到企业微信活码
|
||||||
|
this.jumpToWxWorkContact(contactUrl);
|
||||||
|
} else if (contactId) {
|
||||||
|
// 方案2:使用SDK打开用户资料
|
||||||
|
this.openUserProfile(contactId);
|
||||||
|
} else {
|
||||||
|
this.showError('未配置企业微信客服信息');
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
if (contactUrl) {
|
||||||
|
// H5环境直接跳转
|
||||||
|
window.location.href = contactUrl;
|
||||||
|
} else {
|
||||||
|
this.showError('未配置企业微信客服信息');
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到企业微信客服
|
||||||
|
*/
|
||||||
|
jumpToWxWorkContact(contactUrl) {
|
||||||
|
uni.navigateToMiniProgram({
|
||||||
|
appId: 'wxeb490c6f9b154ef9', // 企业微信小程序AppID
|
||||||
|
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(contactUrl)}`,
|
||||||
|
success: () => {
|
||||||
|
console.log('跳转企业微信成功');
|
||||||
|
this.$util.showToast({
|
||||||
|
title: '跳转成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('跳转企业微信失败:', err);
|
||||||
|
this.showError('跳转失败,请检查企业微信配置');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开用户资料
|
||||||
|
*/
|
||||||
|
openUserProfile(contactId) {
|
||||||
|
if (!this.wxWorkSDK) {
|
||||||
|
this.showError('企业微信SDK未初始化');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.wxWorkSDK.addContact({
|
||||||
|
userId: contactId
|
||||||
|
}, (res) => {
|
||||||
|
console.log('打开用户资料成功:', res);
|
||||||
|
}, (err) => {
|
||||||
|
console.error('打开用户资料失败:', err);
|
||||||
|
this.showError('打开用户资料失败');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示错误提示
|
||||||
|
*/
|
||||||
|
showError(message) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: message,
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭弹窗
|
||||||
|
*/
|
||||||
|
closePopup() {
|
||||||
|
this.$refs.confirmPopup.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wxwork-contact-wrap {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.contact-button {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, #1e7dd8 0%, #1482e0 100%);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-popup {
|
||||||
|
width: 600rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.popup-header {
|
||||||
|
padding: 40rpx 30rpx 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body {
|
||||||
|
padding: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer {
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
&.cancel-btn {
|
||||||
|
background: #fff;
|
||||||
|
color: #999;
|
||||||
|
border-right: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.confirm-btn {
|
||||||
|
background: #1e7dd8;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user