项目初始化

This commit is contained in:
jerry
2025-01-21 01:46:34 +08:00
parent 364021b042
commit 48153e7761
962 changed files with 172070 additions and 0 deletions

View File

@@ -0,0 +1,225 @@
<template>
<su-fixed alway :bgStyles="{ background: '#fff' }" :val="0" noNav opacity :placeholder="false">
<su-status-bar />
<view
class="ui-bar ss-flex ss-col-center ss-row-between ss-p-x-20"
:style="[{ height: sys_navBar - sys_statusBar + 'px' }]"
>
<!-- -->
<view class="icon-box ss-flex">
<view class="icon-button icon-button-left ss-flex ss-row-center" @tap="onClickLeft">
<text :class="tabOpacityVal > 0.4 ? 'black' : ''" class="sicon-back" v-if="hasHistory" />
<text :class="tabOpacityVal > 0.4 ? 'black' : ''" class="sicon-home" v-else />
</view>
<view class="line"></view>
<view class="icon-button icon-button-right ss-flex ss-row-center" @tap="onClickRight">
<text :class="tabOpacityVal > 0.4 ? 'black' : ''" class="sicon-more" />
</view>
</view>
<!-- -->
<view class="detail-tab-card ss-flex-1" :style="[{ opacity: tabOpacityVal }]">
<view class="tab-box ss-flex ss-col-center ss-row-around">
<view
class="tab-item ss-flex-1 ss-flex ss-row-center ss-col-center"
v-for="item in tabList"
:key="item.value"
@tap="onTab(item)"
>
<view class="tab-title" :class="currentTab === item.value ? 'cur-tab-title' : ''">
{{ item.label }}
</view>
<view v-show="currentTab === item.value" class="tab-line"></view>
</view>
</view>
</view>
<!-- #ifdef MP -->
<view :style="[capsuleStyle]"></view>
<!-- #endif -->
</view>
</su-fixed>
</template>
<script>
import sheep from '@/sheep';
import { showMenuTools, closeMenuTools } from '@/sheep/hooks/useModal';
export default {
components: {
},
props: {
title: {
type: String,
default: '',
},
//滚动条滚动距离
scrollTop: {
type: [Number, String],
default: 0
},
},
data() {
return {
sys_navBar: sheep.$platform.navbar,
sys_statusBar: sheep.$platform.device.statusBarHeight,
hasHistory: sheep.$router.hasHistory(),
tabList: [
{
label: '价格',
value: 1,
},
{
label: '动态',
value: 2,
},
{
label: '评价',
value: 3,
},
],
capsuleStyle: {
width: sheep.$platform.capsule.width + 'px',
height: sheep.$platform.capsule.height + 'px',
},
}
},
computed: {
tabOpacityVal() {
return this.scrollTop > sheep.$platform.navbar ? 1 : this.scrollTop * 0.01;;
},
currentTab() {
return sheep.$store('sys').clerkTabIndex;
},
},
methods: {
onClickLeft() {
if (this.hasHistory) {
sheep.$router.back();
} else {
sheep.$router.go('/pages/tabbar/index');
}
},
onClickRight() {
showMenuTools();
},
onTab(e) {
this.$emit('onTab', e.value);
},
}
}
</script>
<style lang="scss" scoped>
.icon-box {
box-shadow: 0px 0px 4rpx rgba(51, 51, 51, 0.08), 0px 4rpx 6rpx 2rpx rgba(102, 102, 102, 0.12);
border-radius: 30rpx;
width: 134rpx;
height: 56rpx;
margin-left: 8rpx;
border: 1px solid rgba(#fff, 0.4);
.line {
width: 2rpx;
height: 24rpx;
background: #e5e5e7;
}
.sicon-back {
font-size: 32rpx;
color: #fff;
}
.sicon-home {
font-size: 32rpx;
color: #fff;
}
.sicon-more {
font-size: 32rpx;
color: #fff;
}
.black {
color: #000;
}
.icon-button {
width: 67rpx;
height: 56rpx;
&-left:hover {
background: rgba(0, 0, 0, 0.16);
border-radius: 30rpx 0px 0px 30rpx;
}
&-right:hover {
background: rgba(0, 0, 0, 0.16);
border-radius: 0px 30rpx 30rpx 0px;
}
}
}
.left-box {
position: relative;
width: 60rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
.circle {
position: absolute;
left: 0;
top: 0;
width: 60rpx;
height: 60rpx;
background: rgba(#fff, 0.6);
border: 1rpx solid #ebebeb;
border-radius: 50%;
box-sizing: border-box;
z-index: -1;
}
}
.right {
position: relative;
width: 60rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
.circle {
position: absolute;
left: 0;
top: 0;
width: 60rpx;
height: 60rpx;
background: rgba(#ffffff, 0.6);
border: 1rpx solid #ebebeb;
box-sizing: border-box;
border-radius: 50%;
z-index: -1;
}
}
.detail-tab-card {
width: 50%;
.tab-item {
height: 80rpx;
position: relative;
z-index: 11;
.tab-title {
font-size: 30rpx;
}
.cur-tab-title {
font-weight: $font-weight-bold;
}
.tab-line {
width: 60rpx;
height: 6rpx;
border-radius: 6rpx;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 10rpx;
background-color: var(--ui-BG-Main);
z-index: 12;
}
}
}
</style>

View File

@@ -0,0 +1,150 @@
<template>
<view>
<view class="option-box">
<view class="tag-box">
<u-icon name="tags" color="#f6f6f6" size="34"></u-icon>
<view class="name">服务类型</view>
</view>
<view class="span-box">
<view @click="changeGame(option)" class="span" :class="catId == option.id ? 'active': '' " v-for="(option,t) in optionList">{{option.name}}</view>
</view>
</view>
<view class="option-box" v-if="categoryList.length > 0">
<view class="tag-box">
<u-icon name="tags" color="#f6f6f6" size="34"></u-icon>
<view class="name">选项</view>
</view>
<view class="span-box">
<view @click="changeCategory(option)" class="span" :class="gameId == option.id ? 'active': '' " v-for="(option,t) in categoryList">{{option.name}}</view>
</view>
</view>
<view class="option-box" v-if="goodsList.length > 0">
<view class="tag-box">
<u-icon name="tags" color="#f6f6f6" size="34"></u-icon>
<view class="name">选项</view>
</view>
<view class="span-box">
<view @click="changeGoods(option)" class="span" :class="goodsId == option.id ? 'active': '' " v-for="(option,t) in goodsList">{{option.name}}</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
props: {
optionList: {
type: Array,
default: [],
},
modelValue: {
type: Object,
default: {}
},
},
data() {
return {
catId: -1,
gameId: -1,
goodsId: -1,
categoryList: [],
goodsList: [],
goodsList: [],
}
},
methods: {
changeGame(e) {
this.gameId = -1;
this.goodsId = -1;
this.catId = e.id;
if(e.categoryList){
this.goodsList = [];
this.categoryList = e.categoryList;
}else{
this.categoryList = [];
this.goodsList = e.goodsList;
}
var node = {
catId: this.catId,
gameId: this.gameId,
goodsId: this.goodsId,
price: 0,
}
this.$emit('update:modelValue', node);
},
changeCategory(e) {
this.goodsId = -1;
this.gameId = e.id;
this.goodsList = e.goodsList;
var node = {
catId: this.catId,
gameId: this.gameId,
goodsId: this.goodsId,
price: 0,
}
this.$emit('update:modelValue', node);
},
changeGoods(e) {
this.goodsId = e.id;
var node = {
catId: this.catId,
gameId: this.gameId,
goodsId: this.goodsId,
price: e.price,
}
this.$emit('update:modelValue', node);
},
}
}
</script>
<style lang="scss" scoped>
.option-box {
margin-bottom: 10px;
.tag-box {
display: flex;
align-items: center;
margin-bottom: 12px;
.name {
font-size: 28rpx;
color: #333;
margin-left: 5px;
}
}
.span-box {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
.span {
background-color: #f6f6f6;
padding: 14rpx 20rpx;
border-radius: 40px;
margin-right: 12px;
margin-bottom: 12px;
min-width: 140rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 24rpx;
color: #949494;
}
.active {
background-color: var(--ui-BG-Main);
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,316 @@
<template>
<view v-show="showPop" class="gift-box">
<scroll-view style="height: 100%;" scroll-y>
<view class="top-box">
<view class="title">选择礼物</view>
<view class="btn-box" @click="close">
<u-icon name="close"></u-icon>
<view class="text">取消</view>
</view>
</view>
<view class="list-box">
<view v-for="(item,index) in dataList" class="gift" @click="sendGift(item)">
<view class="img-box">
<img class="img" :src="item.img"></img>
<view class="tag" v-if="item.giftType == 1">
<text>特效</text>
<text v-if="item.tag">·{{item.tag}}</text>
</view>
<view class="tag" v-if="item.giftType == 0 && item.tag">
<text>{{item.tag}}</text>
</view>
</view>
<view class="name">{{item.name}}</view>
<view class="price">{{ fen2yuan(item.money) }} 钻石</view>
</view>
</view>
</scroll-view>
</view>
<view class="svga-box" :class="giftFlag ? 'svga-show': 'svga-hide'">
<c-svga ref="cSvgaRef" :canvasId='canvasId' :src="src" :loops='0' :auto-play="false" @frame='onFrame' @finished='onFinished' @percentage='onPercentage' @loaded='onLoaded'></c-svga>
<view class="close-btn">
<view class="bottom-box">
<view class="title">{{gift.name}}</view>
<view class="price">{{ fen2yuan(gift.money) }} 钻石</view>
<view class="btn-box">
<view class="btn" @click="cannel">取消</view>
<view class="btn active" @click="ok">确定</view>
</view>
</view>
</view>
</view>
</template>
<script>
import sheep from '@/sheep';
export default {
components: {
},
props: {
modelValue: {
type: Object,
default: {}
},
showPop: {
type: Boolean,
default: false
},
dataList: {
type: Array,
default: []
},
},
emits: ["close", "update:modelValue"],
data() {
return {
giftFlag: false,
src: '',
canvasId: 'myCanvas2',
gift: {},
}
},
methods: {
close() {
this.$emit('close');
},
sendGift(e) {
this.gift = e;
if(e.giftType == 0){
// 普通礼物不播放
this.close();
this.$emit('update:modelValue', this.gift);
return;
}
this.src = e.pic;
this.giftFlag = true;
},
onFinished() {
this.giftFlag = false;
console.log('动画停止播放时回调');
},
onFrame(frame) {//动画播放至某帧后回调
// console.log(frame);
},
onPercentage(percentage) { //动画播放至某进度后回调
// console.log(percentage);
},
onLoaded() {
this.$refs.cSvgaRef.call('setContentMode', 'AspectFill');
console.log('加载完成');
this.$refs.cSvgaRef.call('startAnimation');
},
closeSvga() {
this.src = "";
this.$refs.cSvgaRef.call('stopAnimation');
this.giftFlag = false;
},
fen2yuan(price) {
var f = 0;
var p = (price / 100.0).toFixed(0);
var p1 = (price / 100.0).toFixed(1);
var p2 = (price / 100.0).toFixed(2);
if(p*100 == price){
f = 0;
}else if(p1*100 == price){
f = 1;
}else if(p2*100 == price){
f = 2;
}
return (price / 100.0).toFixed(f)
},
cannel() {
this.closeSvga();
},
ok() {
this.closeSvga();
this.close();
this.$emit('update:modelValue', this.gift);
},
}
}
</script>
<style lang="scss" scoped>
.gift-box {
background-color: #fff;
position: absolute;
top: 200rpx;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
padding: 15px;
border-top-right-radius: 20rpx;
border-top-left-radius: 20rpx;
padding-bottom: 0;
.top-box {
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
left: 0;
right: 0;
background-color: #fff;
top: 200rpx;
padding: 0 15px;
border-top-right-radius: 20rpx;
border-top-left-radius: 20rpx;
height: 110rpx;
z-index: 1;
.title {
font-size: 28rpx;
}
.btn-box {
background-color: var(--ui-BG-Main);
padding: 7px 15px;
font-size: 24rpx;
border-radius: 40px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
.text {
margin-left: 5px;
}
}
}
.list-box {
display: flex;
flex-wrap: wrap;
padding-top: 60rpx;
.gift {
width: 25%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 20rpx 0px;
.img-box {
position: relative;
.img{
max-width: 160rpx;
height: 160rpx;
}
.tag {
position: absolute;
top: 0;
right: 0;
font-size: 16rpx;
color: #fff;
background-color: var(--ui-BG-Main);
border-radius: 40px;
padding: 2rpx 8rpx;
}
}
.name {
font-size: 24rpx;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 160rpx;
margin-top: 2px;
margin-bottom: 7px;
}
.price {
font-size: 20rpx;
color: var(--ui-BG-Main);
}
}
}
}
.svga-box {
position: fixed;
top: 0;
left: 0;
z-index: 999999999;
width: 100%;
height: 100%;
background-color: black;
.close-btn {
color: #fff;
position: absolute;
z-index: 999999999;
padding: 5px 10px;
left: 0;
right: 0;
bottom: 100rpx;
.bottom-box {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.title {
font-size: 28rpx;
margin-bottom: 5px;
}
.price {
font-size: 24rpx;
}
.btn-box {
display: flex;
align-items: center;
margin-top: 10px;
.btn {
border: 1px solid #fff;
font-size: 28rpx;
padding: 20rpx 110rpx;
border-radius: 40px;
margin: 15px;
color: #fff;
}
.active {
border: 1px solid var(--ui-BG-Main);
background-color: var(--ui-BG-Main);
}
}
}
}
}
.svga-hide {
/* #ifdef MP */
transform: translate(-100%, 0);
/* #endif */
/* #ifndef MP */
display: none;
/* #endif */
}
.svga-show {
/* #ifdef MP */
transform: translate(0, 0);
/* #endif */
/* #ifndef MP */
display: block;
/* #endif */
}
</style>

View File

@@ -0,0 +1,444 @@
<template>
<tui-bottom-popup :zIndex="1002" :maskZIndex="1001" :show="popupShow" @close="hiddenPopup">
<view class="order-box">
<view class="avatar-box">
<u-image width="140" height="140" border-radius="20" :src="clerk.avatar"></u-image>
<view class="close-span" @click="hiddenPopup">
<u-icon name="close-circle" color="#98a2a1" size="50"></u-icon>
</view>
</view>
<scroll-view style="height: 700rpx;" scroll-y>
<view class="page-box">
<view class="form-box">
<view class="input-box">
<view class="tag-box">
<view class="name">服务类型</view>
</view>
<view class="tab-span">
<!-- <view @click="changeTab(0)" class="btn" :class="form.rewardType == 0 ? 'active' : ''">赠送</view> -->
<view @click="changeTab(1)" class="btn" :class="form.rewardType == 1 ? 'active' : ''">赠礼</view>
</view>
</view>
<view class="input-box" v-if="form.rewardType == 0">
<view class="tag-box">
<view class="name">打赏金额</view>
</view>
<view class="input-span">
<u-input v-model="payMoney" type="number" :placeholder-style="`fontSize: 24rpx; color: #cbced5;`" placeholder="请输入赠送金额"></u-input>
</view>
</view>
<view class="input-box" v-if="form.rewardType == 1">
<view class="tag-box">
<view class="name">赠送礼物</view>
</view>
<view class="select-span" @click="openGift">
<view v-if="gift.id > 0">已选{{gift.name}}</view>
<view v-else>点击选择礼物</view>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="input-box" v-if="gift.id > 0">
<view class="tag-box">
<view class="name">礼物数量</view>
</view>
<view class="step-span">
<img class="img" :src="gift.img"></img>
<tui-numberbox iconBgColor="var(--ui-BG-Main)" iconColor="#fff" backgroundColor="#fff" :min="1" :value="form.count" @change="change"></tui-numberbox>
</view>
</view>
<view class="input-box">
<view class="textarea-box">
<view class="name">心动留言</view>
</view>
<view class="textarea-span">
<u-input v-model="form.msg" type="textarea" :placeholder-style="`fontSize: 24rpx; color: #cbced5;`" placeholder="请输入心动留言"></u-input>
</view>
</view>
<view class="input-box" v-if="isPass">
<view class="tag-box">
<view class="name">您的微信号</view>
</view>
<view class="input-span">
<u-input v-model="form.weixin" :placeholder-style="`fontSize: 24rpx; color: #cbced5;`" placeholder="请输入正确的微信号"></u-input>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="bottom-box2" v-if="form.rewardType == 0">
<view class="btn-box">
<view class="pay-btn" @click="confirm">立即赠送</view>
</view>
</view>
<view class="bottom-box" v-if="form.rewardType == 1">
<view class="price-box">
<text>总价</text>
<text class="price">{{ fen2yuan(gift.money*form.count) }}</text>
<text>钻石</text>
</view>
<view class="btn-box">
<view class="pay-btn" @click="confirm">立即赠送</view>
</view>
</view>
</view>
</tui-bottom-popup>
<gift-list :showPop="giftFlag" :dataList="giftList" v-model="gift" @close="closeGift"></gift-list>
</template>
<script>
import tuiBottomPopup from "@/components/thorui/tui-bottom-popup/tui-bottom-popup.vue"
import tuiNumberbox from "@/components/thorui/tui-numberbox/tui-numberbox.vue"
import GiftList from '@/pages/clerk/detail/components/giftList.vue';
import RewardApi from '@/sheep/api/worker/reward';
import sheep from '@/sheep';
export default {
components: {
tuiBottomPopup,
tuiNumberbox,
GiftList,
},
props: {
},
data() {
return {
popupShow: false,
gift: {
id: -1,
money: 0,
},
giftFlag: false,
giftList: [],
payMoney: '',
form: {
rewardType: 1,
count: 1,
giftId: -1,
money: '',
weixin: '',
msg: '',
payMoney: '',
},
}
},
computed: {
clerk() {
return sheep.$store('sys').clerk;
},
userInfo() {
return sheep.$store('user').userInfo;
},
isPass() {
return sheep.$store('user').tradeConfig.weixinEnabled;
},
},
methods: {
//调用此方法显示弹层
showPopup() {
this.form.weixin = this.userInfo.weixin;
RewardApi.getGiftList().then(res => {
this.giftList = res.data;
this.popupShow = true
});
},
showGiftPopup(e) {
this.gift = e;
this.form.rewardType = 1;
this.form.weixin = this.userInfo.weixin;
RewardApi.getGiftList().then(res => {
this.giftList = res.data;
this.popupShow = true
});
},
hiddenPopup() {
this.popupShow = false
},
change(e) {
this.form.count = e.value
},
changeTab(e) {
this.form.rewardType = e;
this.gift = {
id: -1,
money: 0,
};
},
fen2yuan(price) {
var f = 0;
var p = (price / 100.0).toFixed(0);
var p1 = (price / 100.0).toFixed(1);
var p2 = (price / 100.0).toFixed(2);
if(p*100 == price){
f = 0;
}else if(p1*100 == price){
f = 1;
}else if(p2*100 == price){
f = 2;
}
return (price / 100.0).toFixed(f)
},
yuan2fen(price) {
return (price * 100.0).toFixed(0)
},
openGift() {
this.giftFlag = true;
},
closeGift() {
this.form.count = 1;
this.giftFlag = false;
},
confirm() {
if(this.isPass && !this.form.weixin){
sheep.$helper.toast('请输入正确的微信');
return;
}
if(this.form.rewardType == 0){
this.form.payMoney = this.yuan2fen(this.payMoney);
if(this.form.payMoney < 1){
sheep.$helper.toast('请输入打赏金额');
return;
}
}else{
this.form.giftId = this.gift.id;
if(this.form.giftId < 1){
sheep.$helper.toast('请选择打赏礼物');
return;
}
}
this.form.workerClerkId = this.clerk.id;
RewardApi.createRewardOrder(this.form).then(res => {
// 跳转到支付页面
this.$u.route({
url: 'pages/pay/reward/index',
params: {
id: res.data.payOrderId,
}
});
});
},
}
}
</script>
<style lang="scss" scoped>
.avatar-box {
padding: 10px 0;
display: flex;
justify-content: center;
align-items: center;
.close-span {
position: absolute;
right: 5px;
top: 5px;
width: 70rpx;
height: 70rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
.page-box {
padding: 15px;
padding-bottom: 10px;
.form-box {
margin-bottom: 10px;
.tag-box {
display: flex;
align-items: center;
width: 180rpx;
.name {
font-size: 24rpx;
color: #333;
margin-left: 5px;
}
}
.textarea-box {
height: 20px;
display: flex;
width: 180rpx;
.name {
font-size: 24rpx;
color: #333;
margin-left: 5px;
}
}
.input-box {
display: flex;
margin-bottom: 20px;
align-items: center;
.input-span {
background-color: #f6f6f6;
margin-left: 15px;
display: flex;
flex: 1;
padding: 0 12px;
border-radius: 10rpx;
}
.select-span {
font-size: 24rpx;
background-color: #f6f6f6;
margin-left: 15px;
display: flex;
flex: 1;
padding: 12px 12px;
border-radius: 10rpx;
color: #aaaaaa;
justify-content: space-between;
}
.tab-span {
display: flex;
flex: 1;
padding: 0 12px;
align-items: center;
.btn {
background-color: #f6f6f6;
font-size: 24rpx;
padding: 7px 0;
border-radius: 40px;
min-width: 120rpx;
display: flex;
justify-content: center;
align-items: center;
margin-right: 15px;
}
.active {
color: #fff;
background-color: var(--ui-BG-Main);
}
}
.textarea-span {
background-color: #f6f6f6;
margin-left: 15px;
flex: 1;
padding: 2px 12px;
border-radius: 10px;
}
.step-span {
display: flex;
justify-content: space-between;
flex: 1;
padding-left: 12px;
align-items: center;
.img {
width: 80rpx;
height: 80rpx;
border-radius: 100%;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
}
}
}
}
}
.bottom-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
box-shadow: 0 0 6px 0 #ccc;
.price-box {
color: #fb932c;
font-size: 28rpx;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
.price {
margin-right: 5px;
}
}
.btn-box {
width: 50%;
padding-left: 15px;
.pay-btn {
background-color: var(--ui-BG-Main);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 40px;
font-size: 28rpx;
height: 70rpx;
}
}
}
.bottom-box2 {
display: flex;
justify-content: center;
align-items: center;
padding: 15px;
box-shadow: 0 0 6px 0 #ccc;
.price-box {
color: #fb932c;
font-size: 28rpx;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
.price {
margin-right: 5px;
}
}
.btn-box {
width: 50%;
.pay-btn {
background-color: var(--ui-BG-Main);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 40px;
font-size: 28rpx;
height: 70rpx;
}
}
}
</style>

View File

@@ -0,0 +1,263 @@
<!-- 虚拟列表演示(不使用内置列表)(vue) -->
<!-- 写法较简单在页面中对当前需要渲染的虚拟列表数据进行for循环在vue3中兼容性良好 -->
<!-- 在各平台兼容性请查阅https://z-paging.zxlee.cn/module/virtual-list.html -->
<template>
<view class="content">
<!-- 如果页面中的cell高度是固定不变的则不需要设置cell-height-mode如果页面中高度是动态改变的则设置cell-height-mode="dynamic" -->
<!-- 原先的v-model修改为@virtualListChange="virtualListChange"并赋值处理后的虚拟列表 -->
<z-paging ref="paging" :show-loading-more-no-more-view="showLoad" :show-default-loading-more-text="showLoad" use-virtual-list :force-close-inner-list="true" :paging-style="{ paddingTop: 0 + 'px', paddingBottom: paddingBottom + 'rpx' }" cell-height-mode="dynamic" @scroll="scroll" @virtualListChange="virtualListChange" @query="queryList">
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中如果需要跟着滚动则不要设置slot="top" -->
<template #top>
<nav-bar :title="title" :scrollTop="scrollTop" @onTab="change" @initNav="initNav"></nav-bar>
</template>
<view>
<user-box :clerk="clerk" :clerkLevel="clerk.clerkLevel" :paddingTop="paddingTop"></user-box>
<sticky-box :clerk="clerk" @change="change"></sticky-box>
</view>
<!-- :id="`zp-id-${item.zp_index}`":key="item.zp_index" 必须写必须写 -->
<!-- 这里for循环的index不是数组中真实的index了请使用item.zp_index获取真实的index -->
<view class="data-box">
<star-list v-if="currentTab == 0" @openGift="openGift" :clerk="clerk" :virtualList="giftList"></star-list>
<price-list v-if="currentTab == 1" :clerk="clerk"></price-list>
<post-list v-if="currentTab == 2" :virtualList="virtualList"></post-list>
<rate-list v-if="currentTab == 3" :clerk="clerk" :virtualList="virtualList"></rate-list>
</view>
<template #bottom>
<view v-if="isGift" class="bottom-box">
<view class="order" @click="doOrder">立即下单</view>
<view class="gift" @click="doGift">赠礼</view>
</view>
<view v-else class="bottom-box">
<view class="order-btn" @click="doOrder">立即下单</view>
</view>
</template>
</z-paging>
<order-popup ref="orderPopup"></order-popup>
<gift-popup ref="giftPopup"></gift-popup>
</view>
</template>
<script>
import UserBox from '@/pages/clerk/detail/components/userBox.vue';
import StickyBox from '@/pages/clerk/detail/components/stickyBox.vue';
import StarList from '@/pages/clerk/detail/components/starList.vue';
import PriceList from '@/pages/clerk/detail/components/priceList.vue';
import PostList from '@/pages/clerk/detail/components/postList.vue';
import RateList from '@/pages/clerk/detail/components/rateList.vue';
import NavBar from '@/pages/clerk/detail/components/navBar.vue';
import OrderPopup from '@/pages/clerk/detail/components/orderPopup.vue';
import GiftPopup from '@/pages/clerk/detail/components/giftPopup.vue';
import UserApi from '@/sheep/api/member/user';
import ClerkApi from '@/sheep/api/worker/clerk';
import TrendApi from '@/sheep/api/worker/trend';
import RewardApi from '@/sheep/api/worker/reward';
import CommentApi from '@/sheep/api/product/comment';
import { showAuthModal } from '@/sheep/hooks/useModal';
import sheep from '@/sheep';
export default {
components: {
UserBox,
StickyBox,
StarList,
PriceList,
PostList,
RateList,
NavBar,
OrderPopup,
GiftPopup,
},
props: {
title: {
type: String,
default: '',
}
},
data() {
return {
// 虚拟列表数组,通过@virtualListChange监听获得最新数组
virtualList: [],
scrollTop: 0,
paddingTop: 0,
paddingBottom: 0,
height: 0,
clerk: {},
workerClerkId: 0,
giftList: [],
}
},
computed: {
currentTab() {
return sheep.$store('sys').clerkTabIndex;
},
showLoad() {
return sheep.$store('sys').clerkTabIndex > 1;
},
isLogin: {
get() {
return sheep.$store('user').isLogin;
},
},
userInfo: {
get() {
return sheep.$store('user').userInfo;
},
},
isGift() {
return sheep.$store('user').tradeConfig.giftEnabled;
},
},
methods: {
initNav(e) {
this.height = e.height;
this.paddingTop = this.height;
},
initData(options) {
this.workerClerkId = options.id;
ClerkApi.getClerk({
id: options.id,
userId: this.userInfo.id,
}).then(res => {
this.clerk = res.data;
sheep.$store('sys').setClerk(res.data);
});
RewardApi.getRewardGiftList({
workerClerkId: options.id,
}).then(res => {
this.giftList = res.data;
});
},
scroll(e) {
this.scrollTop = e.detail.scrollTop;
},
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
virtualListChange(vList) {
this.virtualList = vList;
},
queryList(pageNo, pageSize) {
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
// 这里的pageNo和pageSize会自动计算好直接传给服务器即可
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
const params = {
pageNo: pageNo,
pageSize: pageSize,
workerClerkId: this.workerClerkId,
}
if(this.currentTab == 0){
}else if(this.currentTab == 1){
}else if(this.currentTab == 2){
TrendApi.getTrendPage(params).then(res => {
// 将请求的结果数组传递给z-paging
this.$refs.paging.complete(res.data.list);
}).catch(res => {
// 如果请求失败写this.$refs.paging.complete(false);
// 注意每次都需要在catch中写这句话很麻烦z-paging提供了方案可以全局统一处理
// 在底层的网络请求抛出异常时写uni.$emit('z-paging-error-emit');即可
this.$refs.paging.complete(false);
})
}else if(this.currentTab == 3){
CommentApi.getCommentPage(this.workerClerkId,pageNo,pageSize,0).then(res => {
// 将请求的结果数组传递给z-paging
this.$refs.paging.complete(res.data.list);
}).catch(res => {
// 如果请求失败写this.$refs.paging.complete(false);
// 注意每次都需要在catch中写这句话很麻烦z-paging提供了方案可以全局统一处理
// 在底层的网络请求抛出异常时写uni.$emit('z-paging-error-emit');即可
this.$refs.paging.complete(false);
})
}
},
change(e) {
sheep.$store('sys').setClerkTabIndex(e);
this.scrollTop = 0;
this.$refs.paging.reload();
},
doOrder() {
if(this.isLogin){
this.$refs.orderPopup.showPopup();
}else{
showAuthModal();
}
},
doGift() {
if(this.isLogin){
this.$refs.giftPopup.showPopup();
}else{
showAuthModal();
}
},
openGift(e) {
if(this.isLogin){
this.$refs.giftPopup.showGiftPopup(e);
}else{
showAuthModal();
}
},
}
}
</script>
<style lang="scss" scoped>
.data-box {
padding: 0 15px;
}
.bottom-box {
display: flex;
justify-content: center;
align-items: center;
padding: 10px 30px;
box-shadow: 0 0 6px 0 #ccc;
.order {
background-color: var(--ui-BG-Main);
padding: 10px;
border-top-left-radius: 40px;
border-bottom-left-radius: 40px;
color: #fff;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
height: 88rpx;
font-size: 28rpx;
}
.order-btn {
background-color: var(--ui-BG-Main);
padding: 10px;
border-radius: 40px;
color: #fff;
flex: 1;
display: flex;
justify-content: center;
align-items: center;
height: 88rpx;
font-size: 28rpx;
}
.gift {
background-color: #eef3f2;
padding: 10px;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
height: 88rpx;
color: #aaa;
font-size: 28rpx;
}
}
</style>

View File

@@ -0,0 +1,89 @@
<template>
<view>
<tui-navigation-bar @init="initNavigation" @change="opacityChange" :scrollTop="scrollTop" backgroundColor="#fff" color="#333">
<detailNavbar @onTab="onTab" :scrollTop="scrollTop" />
</tui-navigation-bar>
</view>
</template>
<script>
import tuiNavigationBar from "@/components/thorui/tui-navigation-bar/tui-navigation-bar.vue";
import detailNavbar from '@/pages/clerk/detail/components/detail-navbar.vue';
export default {
components: {
tuiNavigationBar,
detailNavbar,
},
props: {
title: {
type: String,
default: '',
},
//滚动条滚动距离
scrollTop: {
type: [Number, String],
default: 0
},
},
data() {
return {
top: 0, //标题图标距离顶部距离
opacity: 0,
height: 0,
}
},
methods: {
initNavigation(e) {
this.height = e.height;
this.opacity = e.opacity;
this.top = e.top;
this.$emit('initNav', e);
},
opacityChange(e) {
this.opacity = e.opacity;
},
onTab(e) {
this.$emit('onTab', e);
},
}
}
</script>
<style lang="scss" scoped>
.content-bpx {
color: #fff;
display: flex;
align-items: center;
height: 44px;
justify-content: center;
.left-box {
display: flex;
position: absolute;
left: 0;
}
.nickname {
position: absolute;
width: 100px;
display: flex;
justify-content: center;
align-items: center;
height: 44px;
font-size: 15px;
font-weight: bolder;
color: #1f2122;
}
.set-btn {
padding: 0 15px;
height: 44px;
display: flex;
align-items: center;
}
}
</style>

View File

@@ -0,0 +1,282 @@
<template>
<tui-bottom-popup :zIndex="1002" :maskZIndex="1001" :show="popupShow" @close="hiddenPopup">
<view class="order-box">
<view class="avatar-box">
<u-image width="140" height="140" border-radius="20" :src="clerk.avatar"></u-image>
<view class="close-span" @click="hiddenPopup">
<u-icon name="close-circle" color="#98a2a1" size="50"></u-icon>
</view>
</view>
<scroll-view style="height: 700rpx;" scroll-y>
<view class="page-box">
<game-box v-model="game" :optionList="clerk.goodsList"></game-box>
<view class="form-box">
<!-- <view class="input-box">
<view class="tag-box">
<u-icon name="tags" color="#f6f6f6" size="34"></u-icon>
<view class="name">你的微信号</view>
</view>
<view class="input-span">
<u-input placeholder="请输入正确的微信号~"></u-input>
</view>
</view>
<view class="input-box">
<view class="textarea-box">
<u-icon name="tags" color="#f6f6f6" size="34"></u-icon>
<view class="name">其它备注</view>
</view>
<view class="textarea-span">
<u-input type="textarea" placeholder="请输入备注内容"></u-input>
</view>
</view> -->
<view class="input-box">
<view class="tag-box">
<u-icon name="tags" color="#f6f6f6" size="34"></u-icon>
<view class="name">购买数量</view>
</view>
<view class="step-span">
<tui-numberbox iconBgColor="var(--ui-BG-Main)" iconColor="#fff" backgroundColor="#fff" :min="1" :value="order.num" @change="change"></tui-numberbox>
</view>
</view>
<!-- <view class="input-box">
<radio-box style="width: 100%;" v-model="payMethod" :optionList="optionList"></radio-box>
</view> -->
</view>
</view>
</scroll-view>
<view class="bottom-box">
<view class="price-box">
<text>总价</text>
<text class="price">{{ fen2yuan(game.price*order.num) }}</text>
<text>钻石</text>
</view>
<view class="btn-box">
<view class="pay-btn" @click="confirm">立即下单</view>
</view>
</view>
</view>
</tui-bottom-popup>
</template>
<script>
import tuiBottomPopup from "@/components/thorui/tui-bottom-popup/tui-bottom-popup.vue"
import tuiNumberbox from "@/components/thorui/tui-numberbox/tui-numberbox.vue"
import RadioBox from '@/pages/clerk/detail/components/radioBox.vue';
import GameBox from '@/pages/clerk/detail/components/gameBox.vue';
import sheep from '@/sheep';
export default {
components: {
tuiBottomPopup,
tuiNumberbox,
RadioBox,
GameBox,
},
props: {
},
data() {
return {
popupShow: false,
optionList: [
{
name: '余额支付',
value: '0',
type: 'number',
number: '1000',
},
{
name: '微信支付',
value: '1',
type: 'icon',
},
],
payMethod: '0',
game: {
goodsId: -1,
price: 0,
},
order: {
num: 1,
goodsId: -1,
price: 0,
},
}
},
computed: {
clerk() {
return sheep.$store('sys').clerk;
},
},
methods: {
//调用此方法显示弹层
showPopup() {
this.popupShow = true
},
hiddenPopup() {
this.popupShow = false
},
change(e) {
this.order.num = e.value
},
// 选中某个单选框时由radio时触发
radioChange(e) {
// console.log(e);
},
// 选中任一radio时由radio-group触发
radioGroupChange(e) {
// console.log(e);
},
fen2yuan(price) {
return (price / 100.0).toFixed(0)
},
confirm() {
this.order.goodsId = this.game.goodsId,
this.order.price = this.game.price*this.order.num
if(this.order.goodsId < 0) {
sheep.$helper.toast('请选择商品');
return;
}
var data = {
"clerkId": this.clerk.id,
'items' : [{"skuId": this.order.goodsId, "count": this.order.num}]
}
this.$u.route({
url: 'pages/order/worker/confirm',
params: {
data: JSON.stringify(data),
}
});
},
}
}
</script>
<style lang="scss" scoped>
.avatar-box {
padding: 10px 0;
display: flex;
justify-content: center;
align-items: center;
.close-span {
position: absolute;
right: 5px;
top: 5px;
width: 70rpx;
height: 70rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
.page-box {
padding: 15px;
padding-bottom: 10px;
.form-box {
margin-bottom: 10px;
.tag-box {
display: flex;
align-items: center;
width: 200rpx;
.name {
font-size: 28rpx;
color: #333;
margin-left: 5px;
}
}
.textarea-box {
height: 20px;
display: flex;
width: 200rpx;
.name {
font-size: 28rpx;
color: #333;
margin-left: 5px;
}
}
.input-box {
display: flex;
margin-bottom: 20px;
.input-span {
background-color: #f6f6f6;
margin-left: 15px;
display: flex;
flex: 1;
padding: 0 12px;
border-radius: 40px;
}
.textarea-span {
background-color: #f6f6f6;
margin-left: 15px;
flex: 1;
padding: 2px 12px;
border-radius: 10px;
}
.step-span {
display: flex;
justify-content: flex-end;
flex: 1;
align-items: center;
}
}
}
}
.bottom-box {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
box-shadow: 0 0 6px 0 #ccc;
.price-box {
color: #fb932c;
font-size: 28rpx;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
.price {
margin-right: 5px;
}
}
.btn-box {
width: 50%;
padding-left: 15px;
.pay-btn {
background-color: var(--ui-BG-Main);
color: #fff;
display: flex;
justify-content: center;
align-items: center;
border-radius: 40px;
font-size: 28rpx;
height: 70rpx;
}
}
}
</style>

View File

@@ -0,0 +1,50 @@
<template>
<view class="photo-box">
<scroll-view scroll-x>
<view class="scroll-box">
<view class="img-box" @click="showImage(item)" v-for="(item,index) in dataList">
<u-image border-radius="20" width="170rpx" height="170rpx" :src="item"></u-image>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
components: {
},
props: {
dataList: {
type: Array,
default: [],
},
},
data() {
return {
}
},
methods: {
showImage(src) {
uni.previewImage({
indicator: "none",
current: src,
urls: this.dataList,
});
},
}
}
</script>
<style lang="scss" scoped>
.photo-box {
.scroll-box {
display: flex;
}
.img-box {
margin-right: 15px;
}
}
</style>

View File

@@ -0,0 +1,342 @@
<template>
<view>
<view class="item" :id="`zp-id-${item.zp_index}`" :key="item.zp_index" v-for="(item,index) in orderList">
<view class="card">
<view class="right">
<view class="card-header">
<view class="box3">
<view class="box1">
<view class="tag-list">
<!-- <view class="tag">Ta爱玩王者荣耀</view> -->
<view class="tag">发布于 {{item.createTimeStr}}</view>
</view>
</view>
</view>
</view>
<view class="card-content">
<view class="text-box">
<rich-text :nodes="item.content"></rich-text>
</view>
</view>
<view class="image-box" v-if="item.fileType == 0">
<img-box :file="item.file"></img-box>
</view>
<view class="voice-box" v-if="item.fileType == 1">
<voice-play :sec="item.seconds" @tap.stop="playAudio(item)" :isPlay="item.id == playId"></voice-play>
</view>
<view class="video-box" v-if="item.fileType == 2">
<video-box :file="item.file"></video-box>
</view>
<view class="topic-list">
<view class="topic">
<u-icon name="map-fill" size="40" color="#3cc9a4"></u-icon>
<view class="tag-text">{{item.city}}</view>
<u-icon name="arrow-right" size="24" color="#3cc9a4"></u-icon>
</view>
</view>
<view class="card-footer">
<!-- <view class="toolbar">
<u-icon color="#f880ab" name="presentfill" size="38" custom-prefix="iconfont"></u-icon>
<view class="toolbar-text">3</view>
</view> -->
<!-- <view class="toolbar">
<u-icon name="pinglun" size="38" custom-prefix="iconfont"></u-icon>
<view class="toolbar-text">22</view>
</view> -->
<view class="toolbar" @click="thumb(item)">
<u-icon v-if="item.like" name="thumb-up-fill" color="var(--ui-BG-Main)" size="40"></u-icon>
<u-icon v-else name="thumb-up" size="40"></u-icon>
<view class="toolbar-text" v-if="item.likeNum > 0">{{item.likeNum}}</view>
<view class="text" v-else>点赞</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import ImgBox from '@/pages/tabbar/components/trend/imgBox.vue';
import VideoBox from '@/pages/tabbar/components/trend/videoBox.vue';
import VoicePlay from '@/pages/tabbar/components/trend/voicePlay.vue';
import sheep from '@/sheep';
import TrendApi from '@/sheep/api/worker/trend';
const audio = uni.createInnerAudioContext();
export default {
components: {
ImgBox,
VideoBox,
VoicePlay,
},
props: {
virtualList: {
type: Array,
default: [],
},
},
data() {
return {
playId: null,
}
},
computed: {
orderList() {
this.virtualList.forEach((order) => order.createTimeStr = sheep.$helper.timeFormat(order.createTime, 'yyyy-mm-dd hh:MM'));
return this.virtualList;
},
},
methods: {
playAudio(e) {
if(this.playId == e.id){
this.playId = null;
audio.stop();
return;
}
this.playId = e.id;
//语音自然播放结束
audio.onEnded((res) => {
this.playId = null;
});
audio.src = e.file;
audio.play();
},
thumb(e) {
TrendApi.createTrendLike({
trendId: e.id,
}).then((res) => {
if(res) {
if(e.like){
e.like = false;
e.likeNum = e.likeNum-1;
sheep.$helper.toast('取消点赞');
}else{
e.like = true;
e.likeNum = e.likeNum+1;
sheep.$helper.toast('点赞成功');
}
}
});
},
fans(e) {
TrendApi.createClerkFans({
workerClerkId: e.workerClerkId,
}).then((res) => {
if(res){
if(e.fans){
sheep.$helper.toast('取消收藏');
e.fans = false;
}else{
sheep.$helper.toast('收藏成功');
e.fans = true;
}
}
});
},
detail(e) {
this.$u.route({
url: 'pages/clerk/detail/index',
params: {
id: e.workerClerkId,
}
});
},
}
}
</script>
<style lang="scss" scoped>
.item {
display: flex;
flex-direction: column;
}
.card {
padding: 30rpx 20rpx;
border-bottom: 1rpx solid #f5f5f5;
display: flex;
.right {
display: flex;
flex-direction: column;
flex: 1;
}
}
.avatar-img{
margin-right: 5px;
width: 110rpx;
height: 110rpx;
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: 8rpx;
.img {
width: 100%;
height: 100%;
border-radius: 100%;
}
}
.avatar{
margin-right: 5px;
width: 110rpx;
height: 110rpx;
position: relative;
display: flex;
justify-content: center;
align-items: center;
.img {
width: 75%;
height: 75%;
border-radius: 100%;
}
.gif {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
}
}
.card-header {
display: flex;
align-items: center;
.box1 {
.tag-list {
display: flex;
align-items: center;
font-size: 22rpx;
margin-top: 4rpx;
.tag::after {
content: '·';
padding: 0 10rpx; /* 添加一些间隔 */
}
}
.tag-list .tag:last-child::after {
content: unset;
}
}
.box2 {
display: flex;
align-items: center;
line-height: 40rpx;
.nickname {
font-size: 28rpx;
color: #333333;
}
.sex-box {
display: flex;
align-items: center;
justify-content: center;
background-color: #d06b8d1f;
border-radius: 20px;
font-size: 20rpx;
padding: 4rpx 10rpx;
color: #d06b8d;
line-height: 24rpx;
margin: 0 5px;
.age {
margin-left: 2px;
}
}
.nan {
background-color: #007aff1a;
color: #007aff;
}
}
.box3 {
display: flex;
justify-content: space-between;
flex: 1;
align-items: center;
}
.fans {
width: 60rpx;
display: flex;
justify-content: flex-end;
height: 60rpx;
align-items: center;
color: var(--ui-BG-Main);
font-size: 24rpx;
padding-right: 3px;
}
}
.card-content {
margin-top: 20rpx;
margin-bottom: 10rpx;
.text-box {
font-size: 26rpx;
line-height: 180%;
white-space: pre-wrap;
letter-spacing: 2rpx;
}
}
.topic-list {
display: flex;
align-items: center;
margin-top: 10px;
.topic {
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
margin-right: 20rpx;
color: var(--ui-BG-Main);
font-weight: bold;
.tag-text {
margin-left: 2px;
}
}
}
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 30rpx;
.toolbar {
display: flex;
align-items: center;
justify-content: flex-end;
color: #666666;
width: 80rpx;
height: 40rpx;
flex: 1;
}
.toolbar-text {
font-size: 26rpx;
margin-left: 5px;
}
.text {
font-size: 24rpx;
margin-left: 5px;
}
}
</style>

View File

@@ -0,0 +1,50 @@
<template>
<view class="price-box">
<table-list :tableList="clerk.goodsList"></table-list>
<view class="price-remark">
<u-parse :html="content"></u-parse>
</view>
</view>
</template>
<script>
import TableList from '@/pages/clerk/detail/components/tableList.vue';
export default {
components: {
TableList,
},
props: {
clerk: {
type: Object,
default: {},
},
},
data() {
return {
content: `
<p>露从今夜白,月是故乡明</p>
`
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.price-box {
padding: 30rpx 20rpx;
padding-top: 0px;
.price-remark {
padding: 5px 15px;
}
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<view class="check-box">
<view class="check-option" @click="change(option)" v-for="(option,index) in optionList">
<view class="icon-box">
<view class="check-icon-span" v-if="option.value == valueDom">
<u-icon name="checkmark-circle-fill" color="var(--ui-BG-Main)" size="50"></u-icon>
</view>
<text class="check-icon" v-else></text>
<text class="check-label">{{option.name}}</text>
</view>
<view class="price-box" v-if="option.type == 'number'">
<text class="num">{{option.number}}</text>
<text>钻石</text>
</view>
<view v-if="option.type == 'icon'">
<u-icon name="weixin-fill" color="#39b54a" size="50"></u-icon>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
props: {
optionList: {
type: Array,
default: [],
},
modelValue: {
type: String,
default: ''
},
},
data() {
return {
}
},
computed: {
valueDom() {
return this.modelValue;
},
},
methods: {
change(e) {
this.$emit('update:modelValue', e.value);
},
}
}
</script>
<style lang="scss" scoped>
.check-box {
display: flex;
flex-direction: column;
flex: 1;
.check-option {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
.icon-box {
display: flex;
align-items: center;
.check-icon {
width: 40rpx;
height: 40rpx;
border-radius: 100%;
border: 1px solid var(--ui-BG-Main);
display: flex;
justify-content: center;
align-items: center;
}
.check-icon-span {
width: 40rpx;
height: 44rpx;
display: flex;
justify-content: center;
align-items: center;
}
.check-label {
font-size: 28rpx;
color: var(--ui-BG-Main);
margin-left: 5px;
}
}
.price-box {
font-size: 26rpx;
color: var(--ui-BG-Main);
.num {
font-size: 40rpx;
margin-right: 2px;
}
}
}
.check-option:last-child {
margin-bottom: 0;
}
}
</style>

View File

@@ -0,0 +1,125 @@
<template>
<view :id="`zp-id-${item.zp_index}`" :key="item.zp_index" v-for="(item,index) in orderList" class="card-box">
<view class="avatar-box">
<u-avatar v-if="item.anonymous" size="80"></u-avatar>
<u-avatar v-else size="80" :src="item.userAvatar"></u-avatar>
<view class="nickname-box">
<view class="nickname">
<text class="text">{{item.userNickname}}</text>
<uni-rate :readonly="true" v-model="item.scores" size="14" />
</view>
<view class="time">{{item.createTimeStr}}</view>
</view>
</view>
<view class="spu-box">
<text class="tag">{{clerk.nickname}}</text>
<text class="tag">服务类型{{item.skuName}}</text>
</view>
<view class="content">
<rich-text :nodes="item.content"></rich-text>
</view>
<view class="img-box" v-if="item.picUrls && item.picUrls.length > 0">
<img-box :file="item.picUrls.join(',')"></img-box>
</view>
</view>
</template>
<script>
import ImgBox from '@/pages/tabbar/components/trend/imgBox.vue';
import sheep from '@/sheep';
export default {
components: {
ImgBox
},
props: {
clerk: {
type: Object,
default: {},
},
virtualList: {
type: Array,
default: [],
},
},
data() {
return {
}
},
computed: {
orderList() {
this.virtualList.forEach((order) => order.createTimeStr = sheep.$helper.timeFormat(order.createTime, 'yyyy-mm-dd'));
this.virtualList.forEach(function(e){
if(e.skuProperties){
var skuNameList = [];
e.skuProperties.forEach(function(sku){
skuNameList.push(sku.valueName);
});
e.skuName = skuNameList.join('-');
}
});
return this.virtualList;
},
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.card-box {
padding: 30rpx 20rpx;
border-bottom: 1rpx solid #eeeeee;
}
.avatar-box {
display: flex;
align-items: center;
.nickname-box {
font-size: 24rpx;
margin-left: 10px;
.nickname {
letter-spacing: 0.0625rem;
display: flex;
align-items: center;
.text {
letter-spacing: 2rpx;
margin-right: 10px;
}
}
.time {
color: rgb(164, 164, 164);
font-size: 22rpx;
margin-top: 3px;
}
}
}
.spu-box {
font-size: 24rpx;
color: rgb(164, 164, 164);
margin: 10px 0;
letter-spacing: 2rpx;
.tag {
margin-right: 20rpx;
}
}
.content {
font-size: 26rpx;
line-height: 180%;
white-space: pre-wrap;
letter-spacing: 2rpx;
}
</style>

View File

@@ -0,0 +1,310 @@
<template>
<view>
<view v-if="isGift" class="star-box">
<view class="title-box">
<view class="title">礼物墙</view>
<view class="num">(已点亮{{starNum}}/{{total}})</view>
</view>
<view class="list-box">
<view @click="sendGift(item)" v-for="(item,index) in virtualList" :key="item.id" class="gift">
<view class="img-box">
<img class="img" :class="item.playStatus == 0 ? 'hui' : ''" :src="item.img"></img>
<view class="tag" v-if="item.giftType == 1">
<text>特效</text>
<text v-if="item.tag">·{{item.tag}}</text>
</view>
<view class="tag" v-if="item.giftType == 0 && item.tag">
<text>{{item.tag}}</text>
</view>
</view>
<view class="name">{{item.name}}</view>
<view class="price">x {{item.playNum}}</view>
<view class="btn" @tap.stop="openGift(item)" v-if="item.playStatus == 0">点亮</view>
<view class="btn" @tap.stop="openGift(item)" v-if="item.playStatus == 1">赠送</view>
<view class="btn" v-if="item.playStatus == 2">已下架</view>
</view>
</view>
</view>
<view class="svga-box" :class="giftFlag ? 'svga-show': 'svga-hide'">
<c-svga ref="cSvgaRef" :canvasId='canvasId' :src="src" :loops='0' :auto-play="false" @frame='onFrame' @finished='onFinished' @percentage='onPercentage' @loaded='onLoaded'></c-svga>
<view class="close-btn" @click="closeSvga">
<view class="bottom-box">
<view class="title">{{gift.name}}</view>
<view class="price">{{ fen2yuan(gift.money) }} 钻石</view>
<view class="btn-box">
<view class="btn" @click="cannel">取消</view>
<view v-if="gift.playStatus == 0" class="btn active" @click="ok">点亮</view>
<view v-if="gift.playStatus == 1" class="btn active" @click="ok">赠送</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import sheep from '@/sheep';
export default {
components: {
},
props: {
virtualList: {
type: Array,
default: [],
},
},
data() {
return {
giftFlag: false,
src: '',
canvasId: 'myCanvas',
gift: {},
}
},
computed: {
starNum() {
var count = 0;
this.virtualList.forEach(e => {
if(e.playStatus > 0){
count ++;
}
});
return count;
},
total() {
return this.virtualList.length;
},
isGift() {
return sheep.$store('user').tradeConfig.giftEnabled;
},
},
methods: {
sendGift(e) {
this.gift = e;
if(e.giftType == 0){
// 普通礼物不播放
this.$emit('openGift', this.gift);
return;
}
this.src = e.pic;
this.giftFlag = true;
},
onFinished() {
this.giftFlag = false;
console.log('动画停止播放时回调');
},
onFrame(frame) {//动画播放至某帧后回调
// console.log(frame);
},
onPercentage(percentage) { //动画播放至某进度后回调
// console.log(percentage);
},
onLoaded() {
this.$refs.cSvgaRef.call('setContentMode', 'AspectFill');
console.log('加载完成');
this.$refs.cSvgaRef.call('startAnimation');
},
closeSvga() {
this.src = "";
this.$refs.cSvgaRef.call('stopAnimation');
this.giftFlag = false;
},
fen2yuan(price) {
var f = 0;
var p = (price / 100.0).toFixed(0);
var p1 = (price / 100.0).toFixed(1);
var p2 = (price / 100.0).toFixed(2);
if(p*100 == price){
f = 0;
}else if(p1*100 == price){
f = 1;
}else if(p2*100 == price){
f = 2;
}
return (price / 100.0).toFixed(f)
},
cannel() {
this.closeSvga();
},
ok() {
this.closeSvga();
this.$emit('openGift', this.gift);
},
openGift(e) {
this.$emit('openGift', e);
},
}
}
</script>
<style lang="scss" scoped>
.star-box {
padding: 30rpx 20rpx;
.title-box {
display: flex;
align-items: center;
.title {
font-size: 28rpx;
margin-right: 10px;
}
.num {
font-size: 24rpx;
color: var(--ui-BG-Main);
}
}
.list-box {
display: flex;
flex-wrap: wrap;
padding-top: 30rpx;
.gift {
width: 25%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 20rpx 0px;
.img-box {
position: relative;
.img{
max-width: 150rpx;
height: 150rpx;
}
.hui {
filter: grayscale(100%);
}
.tag {
position: absolute;
top: 0;
right: 0;
font-size: 16rpx;
color: #fff;
background-color: var(--ui-BG-Main);
border-radius: 40px;
padding: 2rpx 8rpx;
}
}
.name {
font-size: 24rpx;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 150rpx;
margin-top: 2px;
margin-bottom: 7px;
}
.price {
font-size: 20rpx;
color: var(--ui-BG-Main);
margin-bottom: 7px;
}
.btn {
border: 1px solid var(--ui-BG-Main);
border-radius: 40px;
color: var(--ui-BG-Main);
padding: 8rpx 20rpx;
font-size: 24rpx;
}
}
}
}
.svga-box {
position: fixed;
top: 0;
left: 0;
z-index: 999999999;
width: 100%;
height: 100%;
background-color: black;
.close-btn {
color: #fff;
position: absolute;
z-index: 999999999;
padding: 5px 10px;
left: 0;
right: 0;
bottom: 100rpx;
.bottom-box {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.title {
font-size: 28rpx;
margin-bottom: 5px;
}
.price {
font-size: 24rpx;
}
.btn-box {
display: flex;
align-items: center;
margin-top: 10px;
.btn {
border: 1px solid #fff;
font-size: 28rpx;
padding: 20rpx 110rpx;
border-radius: 40px;
margin: 15px;
color: #fff;
}
.active {
border: 1px solid var(--ui-BG-Main);
background-color: var(--ui-BG-Main);
}
}
}
}
}
.svga-hide {
/* #ifdef MP */
transform: translate(-100%, 0);
/* #endif */
/* #ifndef MP */
display: none;
/* #endif */
}
.svga-show {
/* #ifdef MP */
transform: translate(0, 0);
/* #endif */
/* #ifndef MP */
display: block;
/* #endif */
}
</style>

View File

@@ -0,0 +1,64 @@
<template>
<view>
<view class="sticky-box">
<view>
<tui-tabs :tabs="tabList" badgeBgColor="var(--ui-BG-Main)" selectedColor="var(--ui-BG-Main)" sliderBgColor="var(--ui-BG-Main)" :currentTab="currentTab" @change="change"></tui-tabs>
</view>
</view>
</view>
</template>
<script>
import tuiTabs from "@/components/thorui/tui-tabs/tui-tabs.vue"
import sheep from '@/sheep';
export default {
components: {
tuiTabs,
},
props: {
clerk: {
type: Object,
default: {},
},
},
data() {
return {
}
},
computed: {
tabList() {
var tabs = [{
name: '礼物墙'
},{
name: '价格'
}, {
name: '动态',
num: this.clerk.trendNum,
}, {
name: '评价',
num: this.clerk.commentNum,
}];
return tabs;
},
currentTab() {
return sheep.$store('sys').clerkTabIndex;
},
},
created() {
},
methods: {
change(e) {
this.$emit('change', e.index);
},
}
}
</script>
<style lang="scss" scoped>
.sticky-box {
background-color: #fff;
padding: 5px 0;
}
</style>

View File

@@ -0,0 +1,100 @@
<template>
<view class="tn-table-class tn-table" :class="[tableClass]" :style="[tableStyle]">
<slot></slot>
</view>
</template>
<script>
export default {
name: 'table-bd',
props: {
// 边框宽度
borderWidth: {
type: [String, Number],
default: ''
},
// 边框颜色
borderColor: {
type: String,
default: ''
},
// 显示上边框
borderTop: {
type: Boolean,
default: true
},
// 显示右边框
borderRight: {
type: Boolean,
default: false
},
// 显示下边框
borderBottom: {
type: Boolean,
default: false
},
// 显示左边框
borderLeft: {
type: Boolean,
default: true
}
},
computed: {
parentData() {
return [this.borderWidth, this.borderColor]
},
tableClass() {
let clazz = ''
return clazz
},
tableStyle() {
let style = {}
if (this.borderWidth !== '') {
style.borderWidth = this.borderWidth + 'rpx'
}
if (this.borderColor) {
style.borderColor = this.borderColor
}
if (this.borderLeft) {
style.borderLeftStyle = 'solid'
}
if (this.borderRight) {
style.borderRightStyle = 'solid'
}
if (this.borderTop) {
style.borderTopStyle = 'solid'
}
if (this.borderBottom) {
style.borderBottomStyle = 'solid'
}
return style
}
},
data() {
return {}
},
created() {
this.children = []
},
watch: {
parentData() {
// 更新子组件的数据
if (this.children.length) {
this.children.map((child) => {
typeof(child.updateParentData) === 'function' && child.updateParentData()
})
}
}
}
}
</script>
<style lang="scss" scoped>
.tn-table {
box-sizing: border-box;
width: 100%;
border-width: 1rpx;
border-style: none;
border-color: var(--ui-BG-Main);;
}
</style>

View File

@@ -0,0 +1,305 @@
<template>
<view class="tn-td-class tn-td" :class="[tdClass]" :style="[tdStyle]" @tap.stop="handleClick">
<slot></slot>
</view>
</template>
<script>
export default {
name: 'table-td',
options: {
// 在微信小程序中将组件节点渲染为虚拟节点更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
virtualHost: true
},
props: {
// 占整个表格的宽度跨度
// [1-24]
span: {
type: Number,
default: 24
},
// 宽度
// 优先级比span高
width: {
type: [String, Number],
default: ''
},
// 高度
height: {
type: [String, Number],
default: ''
},
// 字体加粗
bold: {
type: Boolean,
default: false
},
// 格内边距
padding: {
type: String,
default: ''
},
// 边框颜色
borderColor: {
type: String,
default: ''
},
// 边框宽度
borderWidth: {
type: [String, Number],
default: ''
},
// 左边框
borderLeft: {
type: Boolean,
default: false
},
// 下边框
borderBottom: {
type: Boolean,
default: false
},
// 右边框
borderRight: {
type: Boolean,
default: true
},
// 文字超出隐藏
ellipsis: {
type: Boolean,
default: false
},
// 文本对齐方式
// left center right
textAlign: {
type: String,
default: 'left'
},
// 排列方式
// left center right
alignItems: {
type: String,
default: 'left'
},
// 收缩表格
shrink: {
type: Boolean,
default: true
},
// 铺满剩余空间
grow: {
type: Boolean,
default: false
},
// 隐藏
hidden: {
type: Boolean,
default: false
},
// 固定列数据
fixed: {
type: Boolean,
default: false
},
// zIndex
zIndex: {
type: Number,
default: 0
},
// 列数
index: {
type: [String, Number],
default: 0
},
// keys
keys: {
type: [String, Number],
default: ''
}
},
computed: {
tdClass() {
let clazz = ''
clazz += `${this.ellipsis ? 'tn-td--ellipsis' : 'tn-td--normal'}`
/* if (this.backgroundColorClass) {
clazz += ` ${this.backgroundColorClass}`
}
if (this.fontColorClass) {
clazz += ` ${this.fontColorClass}`
} */
if (this.alignItems) {
clazz += ` tn-td--${this.alignItems}`
}
if (this.textAlign) {
clazz += ` tn-td__text--${this.textAlign}`
}
if (!this.shrink) {
clazz += ' tn-td--shrink'
}
if (this.grow) {
clazz += ' tn-td--grow'
}
if (this.hidden) {
clazz += ' tn-td--hidden'
}
return clazz
},
tdStyle() {
let style = {}
/* if (this.backgroundColorStyle) {
style.backgroundColor = this.backgroundColorStyle
} */
/* if (this.fontColorStyle) {
style.color = this.fontColorStyle
} */
/* if (this.fontSizeStyle) {
style.fontSize = this.fontSizeStyle
} */
style.width = this.getWidth()
if (this.height) {
style.height = this.height + 'rpx';
}
style.fontWeight = this.bold ? 'bold' : 'normal'
if (this.padding) {
style.padding = this.padding
}
if (this.borderWidth !== '' || this.parentData.borderWidthValue !== '') {
style.borderWidth = this.borderWidth !== '' ? this.borderWidth+'rpx' : this.parentData.borderWidthValue + 'rpx'
}
if (this.borderColor || this.parentData.borderColorValue) {
style.borderColor = this.borderColor || this.parentData.borderColorValue
}
if (this.borderLeft) {
style.borderLeftStyle = 'solid'
}
if (this.borderRight) {
style.borderRightStyle = 'solid'
}
if (this.borderBottom) {
style.borderBottomStyle = 'solid'
}
if (this.fixed) {
style.zIndex = this.zIndex ? this.zIndex : 1000
}
return style
}
},
data() {
return {
parentData: {
borderColorValue: null,
borderWidthValue: null
}
}
},
created() {
this.parent = false
this.updateParentData()
this.parent && this.parent.children.push(this)
},
methods: {
// 获取表格宽度
getWidth() {
if (this.width) {
return this.width + 'rpx'
}
return [
'4.16666667%',
'8.33333333%',
'12.5%',
'16.66666667%',
'20.83333333%',
'25%',
'29.16666667%',
'33.33333333%',
'37.5%',
'41.66666667%',
'45.83333333%',
'50%',
'54.16666667%',
'58.33333333%',
'62.5%',
'66.66666667%',
'70.83333333%',
'75%',
'79.16666667%',
'83.33333333%',
'87.5%',
'91.66666667%',
'95.83333333%',
'100%'
][this.span - 1]
},
// 点击事件
handleClick() {
this.$emit('click', {
index: this.index,
key: this.keys
})
},
// 更新父组件信息
updateParentData() {
this.getParentData('tn-tr')
}
}
}
</script>
<style lang="scss" scoped>
.tn-td {
box-sizing: border-box;
position: relative;
word-break: break-all;
background-color: transparent;
height: auto;
padding: 12rpx;
border-width: 1rpx;
border-style: none;
border-color: var(--ui-BG-Main);
&--normal {
display: inline-flex;
align-items: center;
}
&--ellipsis {
display: inline-block;
overflow: hidden;
white-space: nowrap !important;
text-overflow: ellipsis;
}
&--shrink {
flex-shrink: 0;
}
&--grow {
flex-grow: 1;
}
&--left {
justify-content: flex-start;
}
&--center {
justify-content: center;
}
&--right {
justify-content: flex-end;
}
&__text {
&--left {
text-align: left;
}
&--center {
text-align: center;
}
&--right {
text-align: right;
}
}
&--hidden {
visibility: hidden;
}
}
</style>

View File

@@ -0,0 +1,208 @@
<template>
<view class="tn-tr-class tn-tr" :class="[trClass]" :style="[trStyle]">
<slot></slot>
</view>
</template>
<script>
export default {
name: 'table-tr',
options: {
// 在微信小程序中将组件节点渲染为虚拟节点更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
virtualHost: true
},
props: {
// 宽度
width: {
type: [String, Number],
default: ''
},
// 边框颜色
borderColor: {
type: String,
default: ''
},
// 边框宽度
borderWidth: {
type: [String, Number],
default: ''
},
// 左边框
borderLeft: {
type: Boolean,
default: false
},
// 上边框
borderTop: {
type: Boolean,
default: false
},
// 换行显示
wrap: {
type: Boolean,
default: false
},
// 固定表格
fixed: {
type: Boolean,
default: false
},
// left偏移值
left: {
type: [String, Number],
default: 0
},
// right偏移值
right: {
type: [String, Number],
default: 0
},
// top偏移值(自定义顶部导航栏时用到)
top: {
type: [String, Number],
default: 0
},
// 外边距
margin: {
type: String,
default: ''
},
// zIndex
zIndex: {
type: Number,
default: 0
},
// 行数索引
index: {
type: [String, Number],
default: 0
},
// 参数
params: {
type: String,
default: ''
}
},
computed: {
borderWidthValue() {
return this.borderWidth || this.parentData.borderWidth || ''
},
borderColorValue() {
return this.borderColor || this.parentData.borderColor || ''
},
trClass() {
let clazz = ''
/* if (this.backgroundColorClass) {
clazz += ` ${this.backgroundColorClass}`
}
if (this.fontColorClass) {
clazz += ` ${this.fontColorClass}`
} */
if (this.wrap) {
clazz += ' tn-tr--wrap'
}
if (this.fixed) {
clazz += ' tn-tr--fixed'
}
return clazz
},
trStyle() {
let style = {}
if (this.width) {
style.width = this.width + 'rpx'
}
/* if (this.backgroundColorStyle) {
style.backgroundColor = this.backgroundColorStyle
}
if (this.fontColorStyle) {
style.color = this.fontColorStyle
}
if (this.fontSizeStyle) {
style.fontSize = this.fontSizeStyle
} */
if (this.borderWidth !== '' || this.parentData.borderWidth !== '') {
style.borderWidth = this.borderWidth !== '' ? this.borderWidth + 'rpx' : this.parentData.borderWidth + 'rpx'
}
if (this.borderColor || this.parentData.borderColor) {
style.borderColor = this.borderColor || this.parentData.borderColor
}
if (this.borderLeft) {
style.borderLeftStyle = 'solid'
}
if (this.borderTop) {
style.borderTopStyle = 'solid'
}
if (this.fixed) {
style.left = this.left ? this.left + 'rpx' : 'auto'
style.right = this.right ? this.right + 'rpx' : 'auto'
style.top = this.top ? this.top + 'rpx' : 'auto'
}
if (this.margin) {
style.margin = this.margin
}
style.zIndex = this.zIndex ? this.zIndex : 1000
return style
}
},
data() {
return {
parentData: {
borderColor: null,
borderWidth: null
}
}
},
watch: {
parentData: {
handler() {
// 更新子组件的数据
if (this.children.length) {
this.children.map((child) => {
typeof(child.updateParentData) === 'function' && child.updateParentData()
})
}
},
deep: true
}
},
created() {
this.children = []
this.parent = false
this.updateParentData()
this.parent && this.parent.children.push(this)
},
methods: {
handleClick() {
this.$emit('click', {
index: this.index,
params: this.params
})
},
// 更新父组件信息
updateParentData() {
this.getParentData('tn-table')
}
}
}
</script>
<style lang="scss" scoped>
.tn-tr {
width: 100%;
display: flex;
box-sizing: border-box;
background-color: #FFFFFF;
border-width: 1rpx;
border-style: none none solid none;
border-color: var(--ui-BG-Main);;
&--wrap {
flex-wrap: wrap;
}
&--fixed {
position: fixed;
}
}
</style>

View File

@@ -0,0 +1,98 @@
<template>
<view>
<table-bd style="width: 100%;">
<table-tr>
<table-td :span="18" height="80rpx" :fontSize="30" :bold="true" fontColor="#01BEFF" alignItems="center">服务项目</table-td>
<table-td :span="6" height="80rpx" :fontSize="30" :bold="true" fontColor="#01BEFF" alignItems="center">价格</table-td>
</table-tr>
<block v-for="(tb,t) in tableList">
<table-tr>
<table-td :span="6" alignItems="center">{{tb.name}}</table-td>
<block v-if="tb.goodsList">
<table-td :span="12" :ellipsis="true" padding="0">
<block v-for="(tb2,t2) in tb.goodsList">
<table-tr :borderWidth="t2 == tb.goodsList.length-1 ? 0 : 1">
<table-td :span="24" :borderRight="false" alignItems="center">{{tb2.name}}</table-td>
</table-tr>
</block>
</table-td>
<table-td :span="6" :ellipsis="true" padding="0">
<block v-for="(tb2,t2) in tb.goodsList">
<table-tr :borderWidth="t2 == tb.goodsList.length-1 ? 0 : 1">
<table-td :span="24" borderWidth="1rpx" :borderRight="false" alignItems="center">{{ fen2yuan(tb2.price) }}</table-td>
</table-tr>
</block>
</table-td>
</block>
<block v-if="tb.categoryList">
<table-td :span="12" :ellipsis="true" padding="0">
<block v-for="(tb2,t2) in tb.categoryList">
<table-tr :borderWidth="t2 == tb.categoryList.length-1 ? 0 : 1">
<table-td :span="12" borderWidth="1rpx" alignItems="center">{{tb2.name}}</table-td>
<table-td :span="12" :ellipsis="true" :borderRight="false" padding="0">
<block v-for="(tb3,t3) in tb2.goodsList">
<table-tr :borderWidth="t3 == tb2.goodsList.length-1 ? 0 : 1">
<table-td :span="24" :borderRight="false" alignItems="center">{{tb3.name}}</table-td>
</table-tr>
</block>
</table-td>
</table-tr>
</block>
</table-td>
<table-td :span="6" :ellipsis="true" padding="0">
<block v-for="(tb2,t2) in tb.categoryList">
<block v-for="(tb3,t3) in tb2.goodsList">
<table-tr :borderWidth="t2 == tb.categoryList.length-1 && t3 == tb2.goodsList.length-1 ? 0 : 1">
<table-td :span="24" borderWidth="1rpx" :borderRight="false" alignItems="center">{{ fen2yuan(tb3.price) }}</table-td>
</table-tr>
</block>
</block>
</table-td>
</block>
</table-tr>
</block>
</table-bd>
</view>
</template>
<script>
import TableBd from '@/pages/clerk/detail/components/table-bd.vue';
import TableTd from '@/pages/clerk/detail/components/table-td.vue';
import TableTr from '@/pages/clerk/detail/components/table-tr.vue';
export default {
components: {
TableBd,
TableTd,
TableTr,
},
props: {
tableList: {
type: Array,
default: [],
},
},
data() {
return {
}
},
methods: {
fen2yuan(price) {
return (price / 100.0).toFixed(0)
},
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,270 @@
<template>
<view class="user-box" :style="`background-size: contain;background-image: url(${clerk.avatar});`">
<view class="info-box" :style="{ paddingTop: paddingTop + 20 + 'px'}">
<view class="avatar-box">
<view class="avatar-span">
<u-image width="100%" height="100%" shape="circle" :src="clerk.avatar"></u-image>
<view class="fans-btn" @click="fans(clerk)">
<u-icon v-if="clerk.isFans" color="var(--ui-BG-Main)" name="checkmark-circle-fill" size="46"></u-icon>
<u-icon v-else color="var(--ui-BG-Main)" name="plus-circle-fill" size="46"></u-icon>
</view>
</view>
<view class="right-box">
<view class="nickname-box">
<view class="nickname">{{clerk.nickname}}</view>
<view class="icon">
<u-icon name="wode_duanwei" size="36" custom-prefix="iconfont"></u-icon>
<text>{{clerkLevel.name}}</text>
</view>
</view>
<view class="online" v-if="clerk.onlineStatus">可接单</view>
<view class="online" v-else>休息中</view>
</view>
</view>
<view class="sex-box">
<view class="span" v-if="clerk.sex == 1">
<u-icon name="ziyuan2" color="#f898c5" size="34" custom-prefix="iconfont"></u-icon>
</view>
<view class="span" v-if="clerk.sex == 0">
<u-icon name="ziyuan3" color="#0081ff" size="34" custom-prefix="iconfont"></u-icon>
</view>
<view class="span">{{clerk.age}}</view>
<!-- <view class="span">{{clerk.city}}</view> -->
</view>
<view class="sign-box">{{clerk.intro}}</view>
<view class="voice-box" v-if="clerk.sound">
<view class="voice-span">
<voice-play :sec="clerk.soundTime" :src="clerk.sound"></voice-play>
</view>
<!-- <view class="span">全声线</view>
<view class="span">御姐音</view>
<view class="span">夹子音</view> -->
</view>
<view class="tag-list">
<view class="tag-box">
<span class="tag" v-for="(categoryName,index) in clerk.categoryNameList">{{categoryName}}</span>
</view>
</view>
<!-- <view class="tags-box">
<view class="span">搞笑</view>
<view class="span">风骚走位</view>
<view class="span">乖巧懂事🍑 极致体验</view>
</view> -->
<photo-box v-if="clerk.albums" :dataList="clerk.albums.split(',')"></photo-box>
</view>
</view>
</template>
<script>
import VoicePlay from '@/pages/clerk/detail/components/voicePlay.vue';
import PhotoBox from '@/pages/clerk/detail/components/photoBox.vue';
import sheep from '@/sheep';
import TrendApi from '@/sheep/api/worker/trend';
export default {
components: {
VoicePlay,
PhotoBox,
},
props: {
paddingTop: {
type: Number,
default: 0,
},
clerk: {
type: Object,
default: {},
},
clerkLevel: {
type: Object,
default: {},
},
},
data() {
return {
photo: 'http://cos.duopei.feiniaowangluo.com/34/clerk/1707236152609pJKyvtedS9.jpg,http://cos.duopei.feiniaowangluo.com/34/clerk/1720278125689P34fP9MU1c.jpg?imageView2/1/w/200/h/200',
}
},
methods: {
fans(e) {
TrendApi.createClerkFans({
workerClerkId: e.id,
}).then((res) => {
if(res){
if(e.isFans){
sheep.$helper.toast('取消关注');
e.isFans = false;
}else{
sheep.$helper.toast('关注成功');
e.isFans = true;
}
}
});
},
}
}
</script>
<style lang="scss" scoped>
.info-box {
backdrop-filter: blur(10px);
background-color: rgba(0, 0, 0, 0.5);
padding: 15px;
.avatar-box {
display: flex;
align-items: center;
.avatar-span {
border-radius: 100%;
width: 140rpx;
height: 140rpx;
border: 2px solid #fff;
position: relative;
.fans-btn {
position: absolute;
right: 0;
bottom: 0;
}
}
.right-box {
color: #fff;
display: flex;
justify-content: space-between;
flex: 1;
align-items: center;
margin-left: 10px;
.nickname {
font-size: 34rpx;
font-weight: bold;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 320rpx;
}
.icon {
background-color: #ff5ebd;
display: flex;
justify-content: center;
align-items: center;
border-radius: 40px;
font-weight: bold;
color: #fff;
font-size: 22rpx;
line-height: 22rpx;
padding: 5px 5px;
margin-top: 10px;
}
.online {
border-bottom: 1px solid #fff;
font-size: 28rpx;
}
}
}
.sex-box {
color: #fff;
display: flex;
align-items: center;
line-height: 30px;
.span {
margin-right: 5px;
font-size: 26rpx;
}
}
.sign-box {
color: #cfcfcf;
font-size: 28rpx;
margin-top: 10px;
margin-bottom: 10px;
}
.voice-box {
display: flex;
flex-wrap: wrap;
align-items: center;
.voice-span {
margin-bottom: 10px;
margin-right: 10px;
}
.span {
padding: 10rpx 20rpx;
background-color: rgba(132, 167, 164, .81);
border-radius: 20px;
font-size: 24rpx;
margin-bottom: 10px;
margin-right: 10px;
color: #fff;
}
}
.tags-box {
display: flex;
flex-wrap: wrap;
align-items: center;
margin: 5px 0;
.span {
font-size: 20rpx;
color: #fff;
background-color: #000000;
border-radius: 999px;
padding: 3px 10px;
margin: 0 10px 10px 0;
}
}
.tag-list {
display: flex;
margin: 5px 0;
}
.tag-box {
display: inline-block;
align-items: center;
margin-bottom: 5px;
background-color: #eef2f26e;
border-radius: 3px;
color: #fff;
font-size: 12px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 100%;
padding: 5px 0;
.tag {
white-space: nowrap;
padding: 5px 5px;
position: relative;
}
.tag:after {
content: ' ';
border-left: 1px solid #fff;
display: inline-block;
height: 10px;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
}
.tag:last-child:after{
display: none;
}
}
}
</style>

View File

@@ -0,0 +1,183 @@
<template>
<view class="voice-btn" @click="playBtn" :class="play?'audioplaying':''">
<img class="play-btn" src="@/static/images/audio.png"></img>
<view class="audio-box">
<view class="audio1 wave1"></view>
<view class="audio2 wave2"></view>
<view class="audio3 wave3"></view>
<view class="audio2 wave2"></view>
<view class="audio1 wave1"></view>
<view class="audio2 wave2"></view>
<view class="audio3 wave3"></view>
<view class="audio2 wave2"></view>
<view class="audio1 wave1"></view>
<view class="audio2 wave2"></view>
<view class="audio3 wave3"></view>
<view class="audio2 wave2"></view>
</view>
<view>{{sec}}"</view>
</view>
</template>
<script>
const audio = uni.createInnerAudioContext();
export default {
emits: ['playAudio'],
props: {
src: {
type: String,
default: ''
},
sec: {
type: Number,
default: 0
},
},
data() {
return {
play: false,
};
},
methods: {
playBtn() {
if(this.play){
this.play = false;
audio.stop();
return;
}
this.play = true;
//语音自然播放结束
audio.onEnded((res) => {
this.play = false;
});
audio.src = this.src;
audio.play();
},
}
};
</script>
<style lang="scss" scoped>
view{
box-sizing: border-box;
}
.voice-btn {
background-color: #3cc9a4;
width: 140rpx;
border-radius: 20px;
padding: 10rpx 10rpx;
display: flex;
align-items: center;
justify-content: space-between;
color: #fff;
font-size: 20rpx;
}
.play-btn {
width: 24rpx;
height: 24rpx;
}
.audio-box {
height: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.audio1{
margin-right: 2rpx;
width: 1px;
height: 33.3%;
border-radius: 50px;
background-color: #fff;
}
.audio2{
margin-right: 2rpx;
width: 1px;
height: 66.6%;
border-radius: 50px;
background-color: #fff;
}
.audio3{
margin-right: 2rpx;
width: 1px;
height: 100%;
border-radius: 50px;
background-color: #fff;
}
.audioplaying .wave1 {
animation: wave1 1s linear 0s infinite;
}
.audioplaying .wave2 {
animation: wave2 1s linear 0s infinite;
}
.audioplaying .wave3 {
animation: wave3 1s linear 0s infinite;
}
@keyframes wave1{
0% {
width: 1px;
height: 33%;
}
25% {
width: 1px;
height: 66%;
}
50% {
width: 1px;
height: 100%;
}
75% {
width: 1px;
height: 66%;
}
100% {
width: 1px;
height: 33%;
}
}
@keyframes wave2{
0% {
width: 1px;
height: 66%;
}
25% {
width: 1px;
height: 33%;
}
50% {
width: 1px;
height: 66%;
}
75% {
width: 1px;
height: 100%;
}
100% {
width: 1px;
height: 66%;
}
}
@keyframes wave3{
0% {
width: 1px;
height: 100%;
}
50% {
width: 1px;
height: 33%;
}
100% {
width: 1px;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,61 @@
<template>
<view class="container page-app theme-light main-green font-1">
<layout ref="skill" title="选人下单">
</layout>
<s-auth-modal />
<s-menu-tools />
</view>
</template>
<script>
import layout from '@/pages/clerk/detail/components/layout.vue';
import sheep from '@/sheep';
export default {
components: {
layout,
},
data() {
return {
}
},
// 分享小程序
onShareAppMessage(res) {
return {
title: this.shareInfo.title,
imageUrl: this.shareInfo.image,
};
},
onShareTimeline() {
return {
title: this.shareInfo.title,
imageUrl: this.shareInfo.image,
}
},
onLoad(options) {
this.$nextTick(() => {
this.$refs.skill.initData(options);
});
},
computed: {
shareInfo() {
return sheep.$platform.share.getShareInfo();
},
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.container {
background-color: #fff;
height: calc(100vh);
padding-bottom: env(safe-area-inset-bottom);
}
</style>