增加我的评价

This commit is contained in:
TOP糯米 2023-03-29 21:45:12 +08:00
parent 08b4626a36
commit d81902ab71
11 changed files with 932 additions and 1 deletions

View File

@ -0,0 +1,205 @@
<template>
<view class="component-appraise-group">
<view class="group-cate-group">
<view
class="cate-item"
v-for="(item, index) in cate"
:key="index"
:class="{ active: currentCate == index }"
@click="changeCate(index)"
>
<text
>{{ item.name }} <text v-if="item.count > 0">({{ item.count }})</text></text
>
</view>
</view>
<view class="appraise-list-box">
<view v-show="currentCate == index" v-for="(item, index) in cate" :key="index">
<view class="appraise-item" :class="['tab' + index]" v-for="(v, k) in item.list" :key="k">
<view class="appraise-left">
<image class="avatar" :src="v.avatar" mode="aspectFill" />
</view>
<view class="appraise-right">
<view class="head">
<text class="nickname">{{ v.nickname }}</text>
<text class="date">{{ v.createTime }}</text>
<text class="desc">
<text class="area">{{ v.area }}</text>
<text class="worker">服务人员{{ v.worker }}</text>
</text>
<view class="grade">
<uni-rate :readonly="true" :value="v.grade" :allowHalf="false" :size="utils.rpx2px(40)" />
</view>
</view>
<view class="tags">
<view class="tag" v-for="(tag, tagIdx) in v.tags" :key="tagIdx">{{ tag }}</view>
</view>
<view v-show="v.content != ''" class="content">
<rich-text :nodes="v.content"></rich-text>
</view>
<view v-show="v.images.length > 0" class="image-group">
<view class="image-item" v-for="(image, imageIdx) in v.images" :key="imageIdx">
<image class="image" :src="image" mode="aspectFill" @click="previewImage(v.images, imageIdx)" />
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import UniRate from "@/uni_modules/uni-rate/components/uni-rate/uni-rate.vue";
export default {
name: "appraise-group",
data() {
return {
utils: this.$utils,
currentCate: 0,
};
},
props: {
cate: {
type: Array,
default: [],
},
},
components: {
UniRate,
},
created() {},
mounted() {},
destroyed() {},
methods: {
/**
* 修改分类
*/
changeCate(index) {
this.currentCate = index;
this.$emit("changeCate", this.cate[index], index);
},
/**
* 预览图片
*/
previewImage(list, index) {
uni.previewImage({
urls: list,
current: index,
});
},
},
};
</script>
<style lang="less" scoped>
.component-appraise-group {
width: 100%;
}
.group-cate-group {
width: 100%;
display: flex;
flex-wrap: wrap;
line-height: 32rpx;
margin-bottom: 40rpx;
.cate-item {
font-size: 24rpx;
color: #333333;
margin-right: 40rpx;
}
.cate-item.active {
font-size: 32rpx;
font-weight: bold;
color: #333333;
}
}
.appraise-list-box {
width: 100%;
.appraise-item {
box-sizing: border-box;
padding: 30rpx;
border: 2rpx solid #d7d7d7;
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 22rpx;
}
}
.appraise-left {
.avatar {
width: 70rpx;
height: 70rpx;
box-sizing: border-box;
border: 2rpx solid #999999;
}
}
.appraise-right {
width: 525rpx;
.head {
position: relative;
width: 100%;
}
.nickname,
.date,
.desc {
display: block;
}
.nickname {
font-size: 30rpx;
line-height: 30rpx;
color: #333333;
}
.date {
font-size: 22rpx;
line-height: 22rpx;
color: #999999;
margin: 18rpx 0;
}
.desc {
font-size: 22rpx;
line-height: 22rpx;
color: #999999;
}
.area {
margin-right: 30rpx;
}
.tags {
width: 100%;
margin-top: 20rpx;
}
.tag {
display: inline-block;
font-size: 22rpx;
line-height: 22rpx;
color: #666666;
padding: 12rpx 24rpx;
background: #f6f6f6;
border-radius: 23rpx;
margin-right: 24rpx;
margin-bottom: 20rpx;
}
}
.grade {
position: absolute;
top: 0;
right: 0;
}
.content {
font-size: 28rpx;
font-size: #666666;
}
.image-group {
width: 100%;
margin-top: 20rpx;
}
.image-item {
display: inline-block;
width: 110rpx;
height: 110rpx;
margin-right: 20rpx;
.image {
width: 100%;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<view class="component-appraise-section">
<view class="appraise-total"> 累计 {{ total }} 条真实用户评价 </view>
<view class="appraise-tags-group">
<view class="tag-item" v-for="(item, index) in tags" :key="index">
<text>{{ item.name }}{{ item.count }}</text>
</view>
</view>
<div class="appraise-group-box">
<appraise-group :cate="cate" @changeCate="changeCate" />
</div>
</view>
</template>
<script>
import AppraiseGroup from "@/components/appraise/group";
export default {
name: "appraise-section",
data() {
return {};
},
props: {
total: {
type: [Number, String],
default: 0,
},
tags: {
type: Array,
default: [],
},
cate: {
type: Array,
default: [],
},
},
components: {
AppraiseGroup,
},
created() {},
mounted() {},
destroyed() {},
methods: {
/**
* 修改分类
*/
changeCate(cate, index) {
this.$emit("changeCate", cate, index);
},
},
};
</script>
<style lang="less" scoped>
.component-appraise-section {
width: 100%;
box-sizing: border-box;
padding: 30rpx;
background-color: #ffffff;
.appraise-total {
font-size: 24rpx;
line-height: 24rpx;
color: #333333;
}
.appraise-tags-group {
width: 100%;
display: flex;
flex-wrap: wrap;
margin-bottom: 35rpx;
.tag-item {
background: #f6f7ff;
border-radius: 26rpx;
padding: 14rpx 10rpx;
box-sizing: border-box;
text-align: center;
font-size: 24rpx;
line-height: 24rpx;
color: #333333;
margin-right: 18rpx;
margin-top: 35rpx;
}
.tag-item:nth-child(3n) {
margin-right: 0;
}
}
}
</style>

View File

@ -72,6 +72,14 @@ const apis = {
showLoading: true,
auth: true,
}
},
appraise: {
count: {
url: "/wxapp/index/mysevaluation",
},
list: {
url: "/wxapp/index/seemyevaluation",
}
}
},
service: {

View File

@ -298,5 +298,47 @@ export default {
return reject(response.msg);
}).catch(e => { });
});
},
appraise: {
count() {
return new Promise((resolve, reject) => {
prototype.$request({
api: "user.appraise.count",
}).then(response => {
if (response.code == 1) {
return resolve(response.data);
}
return reject(response.msg);
}).catch(e => { });
});
},
list() {
return new Promise((resolve, reject) => {
prototype.$request({
api: "user.appraise.list",
data: data
}).then(response => {
if (response.code == 1) {
let list = [];
response.data.forEach((data) => {
list.push({
id: data.id,
avatar: data.u_avatar,
nickname: data.u_name,
createTime: data.time,
tags: data.msg.split(","),
area: "-",
worker: data.wid,
grade: data.score,
images: data.img,
content: data.desc,
});
});
return resolve(list);
}
return reject(response.msg);
}).catch(e => { });
});
}
}
}

View File

@ -73,6 +73,12 @@
"navigationBarTitleText": "设置"
}
},
{
"path": "pages/member/appraise",
"style": {
"navigationBarTitleText": "我的评价"
}
},
{
"path": "pages/get/index",
"style": {

View File

@ -0,0 +1,99 @@
<template>
<app-layout title="我的评价">
<view class="appraise-container">
<app-appraise-section
:total="appraise.total"
:tags="appraise.tags"
:cate="appraise.cate"
@changeCate="changeAppraiseCate"
/>
</view>
</app-layout>
</template>
<script>
import AppLayout from "@/components/layout/layout";
import AppAppraiseSection from "@/components/appraise/section";
export default {
name: "member-appraise",
data() {
return {
currentAppraiseCateIndex: 0,
appraise: {
total: 0,
tags: [],
cate: [],
},
};
},
components: {
AppLayout,
AppAppraiseSection,
},
async onLoad() {
//
await this.$models.user.appraise.count().then((data) => {
data.tags.forEach((item) => {
this.appraise.tags.push({
count: item.count,
name: item.name,
});
});
data.cate.forEach((item) => {
this.appraise.cate.push({
name: item.name,
count: item.count,
status: item.status,
page: 1,
more: true,
list: [],
});
});
this.appraise.total = this.appraise.cate[0].count;
this.changeAppraiseCate(this.appraise.cate[0], 0);
});
},
onShow() {},
onReady() {},
onHide() {},
onReachBottom() {
let currentCate = this.appraise.cate[this.currentAppraiseCateIndex];
if (currentCate.more) {
this.loadAppraiseData(currentCate);
}
},
onPullDownRefresh() {},
methods: {
/**
* 切换评价分类
*/
changeAppraiseCate(currentCate, index) {
this.currentAppraiseCateIndex = index;
currentCate.list = [];
currentCate.more = true;
currentCate.page = 1;
this.loadAppraiseData(currentCate);
},
/**
* 加载评价数据
*/
loadAppraiseData(currentCate) {
this.$models.user.appraise
.list({
status: currentCate.status,
page: currentCate.page,
})
.then((list) => {
if (list.length > 0) {
currentCate.page++;
currentCate.list = currentCate.list.concat(list);
} else {
currentCate.more = false;
}
});
},
},
};
</script>
<style lang="less" scoped></style>

View File

@ -87,7 +87,7 @@
<text class="title limit-line clamp-1">设置服务信息</text>
<text class="iconfont icon-jinru"></text>
</view>
<view class="widget-item">
<view class="widget-item" @click="toPage('/pages/member/appraise')">
<text class="title limit-line clamp-1">我的评价</text>
<text class="iconfont icon-jinru"></text>
</view>

View File

@ -0,0 +1,25 @@
## 1.3.12022-02-25
- 修复 条件判断 `NaN` 错误的 bug
## 1.3.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-rate](https://uniapp.dcloud.io/component/uniui/uni-rate)
## 1.2.22021-09-10
- 优化 默认值修改为 0 颗星
## 1.2.12021-07-30
- 优化 vue3下事件警告的问题
## 1.2.02021-07-13
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.22021-05-12
- 新增 组件示例地址
## 1.1.12021-04-21
- 修复 布局变化后 uni-rate 星星计算不准确的 bug
- 优化 添加依赖 uni-icons, 导入 uni-rate 自动下载依赖
## 1.1.02021-04-16
- 修复 uni-rate 属性 margin 值为 string 组件失效的 bug
## 1.0.92021-02-05
- 优化 组件引用关系通过uni_modules引用组件
## 1.0.82021-02-05
- 调整为uni_modules目录规范
- 支持 pc 端

View File

@ -0,0 +1,360 @@
<template>
<view>
<view ref="uni-rate" class="uni-rate">
<view class="uni-rate__icon" :class="{'uni-cursor-not-allowed': disabled}"
:style="{ 'margin-right': marginNumber + 'px' }" v-for="(star, index) in stars" :key="index"
@touchstart.stop="touchstart" @touchmove.stop="touchmove" @mousedown.stop="mousedown"
@mousemove.stop="mousemove" @mouseleave="mouseleave">
<uni-icons :color="color" :size="size" :type="isFill ? 'star-filled' : 'star'" />
<!-- #ifdef APP-NVUE -->
<view :style="{ width: star.activeWitch.replace('%','')*size/100+'px'}" class="uni-rate__icon-on">
<uni-icons style="text-align: left;" :color="disabled?'#ccc':activeColor" :size="size"
type="star-filled" />
</view>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<view :style="{ width: star.activeWitch}" class="uni-rate__icon-on">
<uni-icons :color="disabled?disabledColor:activeColor" :size="size" type="star-filled" />
</view>
<!-- #endif -->
</view>
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin('dom');
// #endif
/**
* Rate 评分
* @description 评分组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=33
* @property {Boolean} isFill = [true|false] 星星的类型是否为实心类型, 默认为实心
* @property {String} color 未选中状态的星星颜色默认为 "#ececec"
* @property {String} activeColor 选中状态的星星颜色默认为 "#ffca3e"
* @property {String} disabledColor 禁用状态的星星颜色默认为 "#c0c0c0"
* @property {Number} size 星星的大小
* @property {Number} value/v-model 当前评分
* @property {Number} max 最大评分评分数量目前一分一颗星
* @property {Number} margin 星星的间距单位 px
* @property {Boolean} disabled = [true|false] 是否为禁用状态默认为 false
* @property {Boolean} readonly = [true|false] 是否为只读状态默认为 false
* @property {Boolean} allowHalf = [true|false] 是否实现半星默认为 false
* @property {Boolean} touchable = [true|false] 是否支持滑动手势默认为 true
* @event {Function} change uniRate value 改变时触发事件e={value:Number}
*/
export default {
name: "UniRate",
props: {
isFill: {
//
type: [Boolean, String],
default: true
},
color: {
//
type: String,
default: "#ececec"
},
activeColor: {
//
type: String,
default: "#ffca3e"
},
disabledColor: {
//
type: String,
default: "#c0c0c0"
},
size: {
//
type: [Number, String],
default: 24
},
value: {
//
type: [Number, String],
default: 0
},
modelValue: {
//
type: [Number, String],
default: 0
},
max: {
//
type: [Number, String],
default: 5
},
margin: {
//
type: [Number, String],
default: 0
},
disabled: {
//
type: [Boolean, String],
default: false
},
readonly: {
//
type: [Boolean, String],
default: false
},
allowHalf: {
//
type: [Boolean, String],
default: false
},
touchable: {
//
type: [Boolean, String],
default: true
}
},
data() {
return {
valueSync: "",
userMouseFristMove: true,
userRated: false,
userLastRate: 1
};
},
watch: {
value(newVal) {
this.valueSync = Number(newVal);
},
modelValue(newVal) {
this.valueSync = Number(newVal);
},
},
computed: {
stars() {
const value = this.valueSync ? this.valueSync : 0;
const starList = [];
const floorValue = Math.floor(value);
const ceilValue = Math.ceil(value);
for (let i = 0; i < this.max; i++) {
if (floorValue > i) {
starList.push({
activeWitch: "100%"
});
} else if (ceilValue - 1 === i) {
starList.push({
activeWitch: (value - floorValue) * 100 + "%"
});
} else {
starList.push({
activeWitch: "0"
});
}
}
return starList;
},
marginNumber() {
return Number(this.margin)
}
},
created() {
this.valueSync = Number(this.value || this.modelValue);
this._rateBoxLeft = 0
this._oldValue = null
},
mounted() {
setTimeout(() => {
this._getSize()
}, 100)
// #ifdef H5
this.PC = this.IsPC()
// #endif
},
methods: {
touchstart(e) {
// #ifdef H5
if (this.IsPC()) return
// #endif
if (this.readonly || this.disabled) return
const {
clientX,
screenX
} = e.changedTouches[0]
// TODO Nvue screenX clientX
this._getRateCount(clientX || screenX)
},
touchmove(e) {
// #ifdef H5
if (this.IsPC()) return
// #endif
if (this.readonly || this.disabled || !this.touchable) return
const {
clientX,
screenX
} = e.changedTouches[0]
this._getRateCount(clientX || screenX)
},
/**
* 兼容 PC @tian
*/
mousedown(e) {
// #ifdef H5
if (!this.IsPC()) return
if (this.readonly || this.disabled) return
const {
clientX,
} = e
this.userLastRate = this.valueSync
this._getRateCount(clientX)
this.userRated = true
// #endif
},
mousemove(e) {
// #ifdef H5
if (!this.IsPC()) return
if (this.userRated) return
if (this.userMouseFristMove) {
this.userLastRate = this.valueSync
this.userMouseFristMove = false
}
if (this.readonly || this.disabled || !this.touchable) return
const {
clientX,
} = e
this._getRateCount(clientX)
// #endif
},
mouseleave(e) {
// #ifdef H5
if (!this.IsPC()) return
if (this.readonly || this.disabled || !this.touchable) return
if (this.userRated) {
this.userRated = false
return
}
this.valueSync = this.userLastRate
// #endif
},
// #ifdef H5
IsPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
var flag = true;
for (let v = 0; v < Agents.length - 1; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
},
// #endif
/**
* 获取星星个数
*/
_getRateCount(clientX) {
this._getSize()
const size = Number(this.size)
if (isNaN(size)) {
return new Error('size 属性只能设置为数字')
}
const rateMoveRange = clientX - this._rateBoxLeft
let index = parseInt(rateMoveRange / (size + this.marginNumber))
index = index < 0 ? 0 : index;
index = index > this.max ? this.max : index;
const range = parseInt(rateMoveRange - (size + this.marginNumber) * index);
let value = 0;
if (this._oldValue === index && !this.PC) return;
this._oldValue = index;
if (this.allowHalf) {
if (range > (size / 2)) {
value = index + 1
} else {
value = index + 0.5
}
} else {
value = index + 1
}
value = Math.max(0.5, Math.min(value, this.max))
this.valueSync = value
this._onChange()
},
/**
* 触发动态修改
*/
_onChange() {
this.$emit("input", this.valueSync);
this.$emit("update:modelValue", this.valueSync);
this.$emit("change", {
value: this.valueSync
});
},
/**
* 获取星星距离屏幕左侧距离
*/
_getSize() {
// #ifndef APP-NVUE
uni.createSelectorQuery()
.in(this)
.select('.uni-rate')
.boundingClientRect()
.exec(ret => {
if (ret) {
this._rateBoxLeft = ret[0].left
}
})
// #endif
// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['uni-rate'], (ret) => {
const size = ret.size
if (size) {
this._rateBoxLeft = size.left
}
})
// #endif
}
}
};
</script>
<style lang="scss">
.uni-rate {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
line-height: 1;
font-size: 0;
flex-direction: row;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-rate__icon {
position: relative;
line-height: 1;
font-size: 0;
}
.uni-rate__icon-on {
overflow: hidden;
position: absolute;
top: 0;
left: 0;
line-height: 1;
text-align: left;
}
.uni-cursor-not-allowed {
/* #ifdef H5 */
cursor: not-allowed !important;
/* #endif */
}
</style>

View File

@ -0,0 +1,88 @@
{
"id": "uni-rate",
"displayName": "uni-rate 评分",
"version": "1.3.1",
"description": "Rate 评分组件,可自定义评分星星图标的大小、间隔、评分数。",
"keywords": [
"uni-ui",
"uniui",
"评分"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,12 @@
## Rate 评分
> **组件名uni-rate**
> 代码块: `uRate`
> 关联组件:`uni-icons`
评分组件,多用于购买商品后,对商品进行评价等场景
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-rate)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839