项目初始化

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,208 @@
<template>
<view>
<!-- :id="`zp-id-${item.zp_index}`":key="item.zp_index" 必须写必须写 -->
<!-- 这里for循环的index不是数组中真实的index了请使用item.zp_index获取真实的index -->
<view class="item" :id="`zp-id-${item.zp_index}`" :key="item.zp_index" v-for="(item,index) in orderList">
<view-item :index="index" :item="item" @onLongPress="onLongPress"></view-item>
</view>
<view class="shade" v-show="showShade" @tap="hidePop">
<view class="pop" :style="popStyle" :class="{'show':showPop}">
<view v-for="(item,index) in popButton" :key="index" @tap="pickerMenu" :data-index="index">{{item}}</view>
</view>
</view>
</view>
</template>
<script>
import ViewItem from '@/pages/tabbar/components/message/viewItem.vue';
import ImConversationApi from '@/sheep/api/im/memberConversation';
import dayjs from 'dayjs';
import relativeTime from "dayjs/plugin/relativeTime";
dayjs.extend(relativeTime);
export default {
components: {
ViewItem,
},
props: {
virtualList: {
type: Array,
default: [],
},
},
data() {
return {
winSize: {},
/* 显示遮罩 */
showShade: false,
/* 显示操作弹窗 */
showPop: false,
/* 弹窗按钮列表 */
popButton: [],
/* 弹窗定位样式 */
popStyle: "",
/* 选择的用户下标 */
pickerUserIndex: -1,
paddingTop: 0,
paddingBottom: 100,
}
},
computed: {
orderList() {
this.virtualList.forEach((order) => order.time = this.showDayTime(order.lastMessageTime));
return this.virtualList;
},
},
created() {
this.getWindowSize();
this.$emit('reload');
},
methods: {
/* 获取窗口尺寸 */
getWindowSize() {
uni.getSystemInfo({
success: (res) => {
this.winSize = {
"witdh": res.windowWidth,
"height": res.windowHeight
}
}
})
},
/* 长按监听 */
onLongPress(e) {
let [touches, style, index] = [e.touches[0], "", e.currentTarget.dataset.index];
/* 因 非H5端不兼容 style 属性绑定 Object ,所以拼接字符 */
if (touches.clientY > (this.winSize.height / 2)) {
style = `bottom:${this.winSize.height-touches.clientY}px;`;
} else {
style = `top:${touches.clientY}px;`;
}
if (touches.clientX > (this.winSize.witdh / 2)) {
style += `right:${this.winSize.witdh-touches.clientX}px`;
} else {
style += `left:${touches.clientX}px`;
}
this.popStyle = style;
this.pickerUserIndex = Number(index);
var conversation = this.orderList[this.pickerUserIndex];
if(conversation.pinned == '0'){
this.popButton = ["置顶聊天", "删除该聊天", "拉黑该用户"];
}else{
this.popButton = ["取消置顶", "删除该聊天", "拉黑该用户"];
}
this.showShade = true;
this.$nextTick(() => {
setTimeout(() => {
this.showPop = true;
}, 10);
});
},
pinned(id, pinned) {
var form = {
pinned: pinned,
id: id,
};
ImConversationApi.pinnedMemberConversation(form).then(res => {
this.$emit('reload');
this.$refs.paging.reload();
});
},
delete(id) {
ImConversationApi.deleteMemberConversation(id).then(res => {
this.$emit('reload');
});
},
slashed(id) {
ImConversationApi.slashedMemberConversation(id).then(res => {
this.$emit('reload');
});
},
/* 隐藏弹窗 */
hidePop() {
this.showPop = false;
this.pickerUserIndex = -1;
setTimeout(() => {
this.showShade = false;
}, 250);
},
/* 选择菜单 */
pickerMenu(e) {
let index = Number(e.currentTarget.dataset.index);
console.log(`${this.pickerUserIndex+1}个用户,第${index+1}个按钮`);
var conversation = this.orderList[this.pickerUserIndex];
if(index == 0){
if(conversation.pinned == '0'){
this.pinned(conversation.id, '1');
}else{
this.pinned(conversation.id, '0');
}
}else if(index == 1){
this.delete(conversation.id);
}else if(index == 2){
this.slashed(conversation.id);
}
this.hidePop();
},
showDayTime(datetime) {
if (!datetime) return "";
return dayjs(datetime).fromNow();
},
}
}
</script>
<style lang="scss" scoped>
.item {
background-color: #fff;
}
/* 遮罩 */
.shade {
position: fixed;
z-index: 100;
top: 0;
right: 0;
bottom: 0;
left: 0;
-webkit-touch-callout: none;
.pop {
position: fixed;
z-index: 101;
width: 260rpx;
box-sizing: border-box;
font-size: 28upx;
text-align: left;
color: #333;
background-color: #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
line-height: 80upx;
transition: transform 0.15s ease-in-out 0s;
user-select: none;
-webkit-touch-callout: none;
transform: scale(0, 0);
&.show {
transform: scale(1, 1);
}
&>view {
padding: 0 20upx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
user-select: none;
-webkit-touch-callout: none;
&:active {
background-color: #f3f3f3;
}
}
}
}
</style>

View File

@@ -0,0 +1,149 @@
<template>
<view>
<view class="option-box">
<view class="tag-box">
<u-icon name="tags" color="#88e6b4" 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="#88e6b4" 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="#88e6b4" 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;
font-weight: 700;
color: #1a1a1a;
padding-left: 3px;
}
}
.span-box {
display: flex;
flex-wrap: wrap;
.span {
padding: 10rpx 30rpx;
font-size: 28rpx;
background-color: #f5f5f5;
min-width: 120rpx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 40px;
margin-right: 7px;
margin-bottom: 8px;
}
.active {
background-color: var(--ui-BG-Main);
color: #fff;
}
}
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<view>
<tui-navigation-bar :isOpacity="false" @init="initNavigation" @change="opacityChange" :scrollTop="scrollTop">
<view class="tab-box">
<view class="zhong">
<view class="tab-box">
<block v-for="(item,i) in tabList" :key="i">
<view v-if="item.enabled" class="title-label" @click="tabsChange" :data-i="i" >
<text
:style="{fontWeight:current==i?'bold':'',fontSize:current==i?'36rpx':'28rpx'}">
{{item.name}}
</text>
</view>
</block>
</view>
</view>
</view>
</tui-navigation-bar>
</view>
</template>
<script>
import tuiNavigationBar from "@/components/thorui/tui-navigation-bar/tui-navigation-bar.vue";
import sheep from '@/sheep';
export default {
components: {
tuiNavigationBar,
},
props: {
tabList: {
type: Array,
default: [],
},
},
data() {
return {
top: 0, //标题图标距离顶部距离
opacity: 1,
height: 0,
scrollTop: 0.5,
}
},
computed: {
current: {
get() {
return sheep.$store('sys').messageTabIndex;
},
},
},
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;
},
tabsChange(e) {
var current = e.currentTarget.dataset.i;
sheep.$store('sys').setMessageTabIndex(current);
this.$emit('change', current);
},
}
}
</script>
<style lang="scss" scoped>
.zhong {
//width: 230rpx;
}
.tab-box {
display: flex;
justify-content: center;
align-items: center;
}
.avatar-box {
display: flex;
align-items: center;
position: absolute;
left: 40rpx;
.icon {
position: absolute;
right: 0;
bottom: 0;
}
}
.tab-box .title-label {
height: 44px;
padding: 0 20rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
//font-size: 34rpx;
}
.tab-box .title-label text {
transition: all 0.3s;
}
</style>

View File

@@ -0,0 +1,346 @@
<template>
<view class="page-box">
<view class="game-card">
<view class="title">
<u-icon name="tags" color="#f5736a" size="34"></u-icon>
<view class="name">店员性别</view>
</view>
<view class="sex-option">
<view class="sex-tab" @click="sexChange(1)">
<view class="img-span">
<img v-if="form.sex == 1" class="img" src="https://rbtnet.oss-cn-hangzhou.aliyuncs.com/16d050d0b229f12a8997a8118ca815c936bdb9b580db48ab8b2737181ca8518a.png"></img>
<img v-else class="img" src="https://rbtnet.oss-cn-hangzhou.aliyuncs.com/15c4eb12397fb3374be6e8bf38854b708abb09f61fb076eaa0c23d5f92cc9583.png"></img>
<view class="sex-ok" v-if="form.sex == 1">
<u-icon name="checkmark-circle-fill" color="#fe8497" size="34"></u-icon>
</view>
</view>
<view class="name">小姐姐</view>
</view>
<view class="sex-tab" @click="sexChange(0)">
<view class="img-span">
<img v-if="form.sex == 0" class="img" src="https://rbtnet.oss-cn-hangzhou.aliyuncs.com/74e49dd19affb2c8016df4805d3947bab3a93af83236e4f875b5ea18bf57d8b3.png"></img>
<img v-else class="img" src="https://rbtnet.oss-cn-hangzhou.aliyuncs.com/d0757757a5b4c0559f1bc1d373ab983902bd056bda7ca4be6c2fa04553b4665d.png"></img>
<view class="sex-ok" v-if="form.sex == 0">
<u-icon name="checkmark-circle-fill" color="#6497f8" size="34"></u-icon>
</view>
</view>
<view class="name">小哥哥</view>
</view>
</view>
<view class="title">
<u-icon name="tags" color="#e475e5" size="34"></u-icon>
<view class="name">店员等级</view>
</view>
<view class="level-option">
<view @click="levelChange(option)" class="tab" :class="option.id == form.workerClerkLevelId ? 'active' : ''" v-for="(option,t) in levelList">{{option.name}}</view>
</view>
<game-box v-model="game" :optionList="goodsList"></game-box>
<view class="input-box">
<view class="title">
<u-icon name="tags" color="#e475e5" 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="form.num" @change="change"></tui-numberbox>
</view>
</view>
<view class="input-box">
<view class="title">
<u-icon name="tags" color="#e475e5" size="34"></u-icon>
<view class="name">排除下单过的店员</view>
</view>
<view class="step-span">
<u-switch active-color="var(--ui-BG-Main)" size="40" v-model="form.blind"></u-switch>
</view>
</view>
</view>
<view class="bottom-box">
<view class="price-box">
<text>总价</text>
<text class="price">{{ fen2yuan(game.price*form.num) }}</text>
<text>钻石</text>
</view>
<view class="btn-box">
<view class="pay-btn" @click="confirm">立即下单</view>
</view>
</view>
</view>
</template>
<script>
import gameBox from '@/pages/tabbar/components/message/gameBox.vue';
import tuiNumberbox from "@/components/thorui/tui-numberbox/tui-numberbox.vue"
import ClerkApi from '@/sheep/api/worker/clerk';
import sheep from '@/sheep';
export default {
components: {
gameBox,
tuiNumberbox,
},
data() {
return {
form: {
num: 1,
goodsId: -1,
price: 0,
sex: 2,
workerClerkLevelId: 0,
blind: false,
},
game: {
goodsId: -1,
price: 0,
},
goodsList: [],
levelList: [
{
id: 0,
name: '金牌',
},
{
id: 1,
name: '银牌',
},
{
id: 2,
name: '铜牌',
},
],
}
},
created() {
this.initData();
},
methods: {
initData() {
ClerkApi.getClerkBlind().then(res => {
this.goodsList = res.data.goodsList;
this.levelList = res.data.clerkLevelList;
});
},
sexChange(e) {
this.form.sex = e;
},
levelChange(e) {
this.form.workerClerkLevelId = e.id;
},
change(e) {
this.form.num = e.value
},
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)
},
confirm() {
this.form.goodsId = this.game.goodsId,
this.form.price = this.game.price*this.form.num
if(this.form.sex > 1) {
sheep.$helper.toast('请选择店员性别');
return;
}
if(this.form.workerClerkLevelId < 1) {
sheep.$helper.toast('请选择店员等级');
return;
}
if(this.form.goodsId < 0) {
sheep.$helper.toast('请选择服务类型');
return;
}
if(this.form.price < 1) {
sheep.$helper.toast('价格不能为0');
return;
}
var data = {
workerClerkLevelId: this.form.workerClerkLevelId,
sex: this.form.sex,
blind: this.form.blind,
items : [
{
skuId: this.form.goodsId,
count: this.form.num,
},
]
}
sheep.$router.go('/pages/order/blind/confirm',{data: JSON.stringify(data)});
},
}
}
</script>
<style lang="scss" scoped>
.page-box {
padding-bottom: 100px;
}
.game-card {
background-color: #fff;
padding: 15px;
.title {
display: flex;
align-items: center;
.name {
font-size: 28rpx;
font-weight: 700;
color: #1a1a1a;
padding-left: 3px;
}
}
.sex-option {
display: flex;
align-items: center;
margin: 15px 0px;
.sex-tab {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
margin-right: 30px;
.img-span {
width: 130rpx;
height: 130rpx;
position: relative;
display: flex;
justify-content: center;
.img {
height: 100%;
width: 100%;
}
.sex-ok {
background-color: #fff;
width: 34rpx;
height: 34rpx;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
bottom: 0;
border-radius: 100%;
}
}
}
.name {
font-size: 28rpx;
font-weight: 400;
padding-top: 10px;
color: #333;
}
}
.level-option {
display: flex;
padding: 15px 0;
flex-wrap: wrap;
.tab {
padding: 10rpx 30rpx;
font-size: 28rpx;
background-color: #f5f5f5;
min-width: 120rpx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 40px;
margin-right: 7px;
margin-bottom: 8px;
}
.active {
color: #fff;
background: var(--ui-BG-Main);
}
}
.input-box {
display: flex;
margin-bottom: 20px;
.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: 0 15px;
height: 100rpx;
position: fixed;
left: 0;
right: 0;
bottom: 100rpx;
background-color: #fff;
z-index: 9;
.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: 64rpx;
}
}
}
</style>

View File

@@ -0,0 +1,265 @@
<template>
<view>
<!-- 系统消息 -->
<view class="msg-list" v-if="item.groupType == 3">
<view class="msg-user">
<view class="avatar">
<!-- <image class="img" src="@/static/images/bell.png"></image> -->
</view>
<view class="content">
<view class="text-black">
<view class="text-nickname">
<view class="nickname green">通知助手</view>
</view>
<text class="time">前天</text>
</view>
<view class="text-gray">
<view class="text-msg">
<view>希望打个赏哦</view>
</view>
<view v-if="item.slashed == 1">
<u-icon name="bell-slash" custom-prefix="iconfont"></u-icon>
</view>
<view v-else>
<view v-if="item.unreadMessageCount > 0">
<tui-badge :scaleRatio="0.8" type="green" dot></tui-badge>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 用户消息 -->
<view class="msg-list" @longpress="onLongPress" :data-index="index" v-if="item.groupType == 1">
<view class="msg-user">
<view class="avatar" @click="detail(item)">
<image class="img" :src="item.avatar"></image>
<view class="badge" v-if="item.online"></view>
</view>
<view class="content" @click="toChat(item)">
<view class="text-black">
<view class="text-nickname">
<view class="nickname">{{item.nickname}}</view>
<view class="sex-badge" v-if="item.sex == 2">
<u-icon name="ziyuan2" custom-prefix="iconfont"></u-icon>
</view>
<view class="sex-man" v-if="item.sex == 1">
<u-icon name="ziyuan3" custom-prefix="iconfont"></u-icon>
</view>
<!-- <image class="vip-img" src="@/static/images/vip.png"></image> -->
</view>
<text class="time">{{item.time}}</text>
</view>
<view class="text-gray">
<view class="text-msg">
<view v-if="item.lastMessageReadStatus == '1'">已读</view>
<view class="text" v-if="item.lastMessageContentType == 1">{{item.lastMessageContent}}</view>
<view v-if="item.lastMessageContentType == 3">[语音消息]</view>
<view v-if="item.lastMessageContentType == 4">[图片消息]</view>
</view>
<view v-if="item.slashed == 1">
<u-icon name="bell-slash" custom-prefix="iconfont"></u-icon>
</view>
<view v-else>
<view v-if="item.unreadMessageCount > 0">
<tui-badge :scaleRatio="0.8" type="green">{{item.unreadMessageCount}}</tui-badge>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import sheep from '@/sheep';
import tuiBadge from "@/components/thorui/tui-badge/tui-badge.vue";
export default {
components: {
tuiBadge,
},
props: {
index: {
type: Number,
default: -1,
},
item: {
type: Object,
default: function() {
return {
dd: '',
}
}
}
},
data() {
return {
}
},
methods: {
onLongPress(e) {
this.$emit('onLongPress', e);
},
detail(e) {
sheep.$router.go('/pages/user/detail/index',{id: e.userId});
},
toChat(e) {
e.unreadMessageCount = 0;
this.$u.route({
url: 'pages/im/index',
params: {
groupId: e.groupId,
receiveUserId: e.userId,
}
});
},
}
}
</script>
<style lang="scss" scoped>
.msg-list {
display: flex;
padding: 15px;
.msg-user{
display: flex;
align-items: center;
flex: 1;
.avatar {
width: 88rpx;
height: 88rpx;
position: relative;
background-color: #ddd;
border-radius: 100%;
.img {
width: 100%;
height: 100%;
border-radius: 100%;
}
.badge {
width: 20rpx;
height: 20rpx;
top: 0;
right: 0;
border: 1px solid #fff;
position: absolute;
background-color: #dd514c;
border-radius: 85px;
}
}
.content {
display: flex;
flex: 1;
flex-direction: column;
margin-left: 10px;
.new {
width: 14rpx;
height: 14rpx;
background-color: #dd514c;
border-radius: 85px;
}
.text-black {
font-size: 28rpx;
display: flex;
align-items: center;
justify-content: space-between;
color: #333333;
margin-bottom: 8rpx;
.tag {
margin-right: 5px;
}
.time {
color: #aaaaaa;
font-size: 24rpx;
}
.text-nickname {
display: flex;
align-items: center;
.nickname {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
max-width: 200rpx;
}
}
}
.text-gray {
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
color: #aaaaaa;
.text-msg {
display: flex;
align-items: center;
.text {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
max-width: 340rpx;
}
}
}
}
}
}
.green {
color: #735fed;
}
.sex-badge {
display: flex;
align-items: center;
justify-content: center;
background-color: #e03997;
color: #ffffff;
border-radius: 3px;
font-size: 8px;
height: 30rpx;
width: 30rpx;
margin: 0 10rpx;
}
.sex-man {
display: flex;
align-items: center;
justify-content: center;
background-color: #0081ff;
color: #ffffff;
border-radius: 3px;
font-size: 8px;
height: 30rpx;
width: 30rpx;
margin: 0 10rpx;
}
.vip-img {
width: 34rpx;
height: 34rpx;
}
.svip-img {
width: 60rpx;
height: 30rpx;
}
</style>