appraise.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. <template>
  2. <mobile-frame>
  3. <view class="main">
  4. <view class="one">
  5. <view class="one_1">
  6. <view class="text1">{{info.goods.name}}{{info.specs[0].name}}</view>
  7. <view class="text2">好评率 <text>{{info.rate||100}}%</text></view>
  8. </view>
  9. <view class="one_2">
  10. <view class="one_2_1" v-for="(item,index) in btnlist" :key="index" @tap="toSelect(item)">
  11. <text>{{item.name}}</text><text>({{item.total||0}})</text>
  12. </view>
  13. </view>
  14. </view>
  15. <view class="two">
  16. <scroll-view scroll-y="true" class="scroll-view">
  17. <view class="list-scroll-view">
  18. <view class="list" v-for="(item, index) in list" :key="index">
  19. <image v-if="item.customer.icon&&item.customer.icon.length>0" class="image"
  20. :src="item.customer.icon&&item.customer.icon.length>0?item.customer.icon[0].url:''"
  21. mode="">
  22. </image>
  23. <text v-else class="iconfont icon-top"></text>
  24. <view class="list_1">
  25. <view class="other">
  26. <text>{{item.customer.phone}}</text>
  27. <text>{{item.reply[0].time||'暂无'}}</text>
  28. </view>
  29. <view class="flie">
  30. <view v-for="(tag, indexs) in item.reply[0].file" :key="indexs">
  31. <image @click="toLarge(item,indexs)" class="images" :src="tag.url" mode="">
  32. </image>
  33. </view>
  34. </view>
  35. <view class="stars">
  36. <uni-rate size="18" :readonly="true" :value="item.goods_score" />
  37. </view>
  38. <view class="other1"><text>{{item.reply[0].content||'暂无'}}</text></view>
  39. <view class="other2">规格:{{item.goodsSpec.name}}</view>
  40. <view class="other2" v-for="(itm, indexx) in item.reply" :key="indexx">
  41. <view :class="[item.customer._id!=user._id?'reply_2':'reply']">
  42. <text>用户评论:{{itm.content||'暂无'}}</text>
  43. <text v-if="itm.reply">商家回复:{{itm.reply||'暂无'}}</text>
  44. </view>
  45. <view v-if="item.customer._id==user._id" @tap="toReply(item)">回复</view>
  46. </view>
  47. <uni-easyinput v-if="reply.reply" class="input" maxlength=-1 type="textarea"
  48. @change="confirm" placeholder="回复商家" />
  49. </view>
  50. </view>
  51. </view>
  52. </scroll-view>
  53. </view>
  54. </view>
  55. </mobile-frame>
  56. </template>
  57. <script>
  58. import moment from 'moment';
  59. export default {
  60. data() {
  61. return {
  62. id: '',
  63. user: {},
  64. btnlist: [{
  65. name: '全部好评',
  66. total: 0,
  67. code: '0'
  68. },
  69. {
  70. name: '好评',
  71. total: 0,
  72. code: '1'
  73. },
  74. {
  75. name: '中评',
  76. total: 0,
  77. code: '2'
  78. },
  79. {
  80. name: '差评',
  81. total: 0,
  82. code: '3'
  83. }
  84. ],
  85. info: {},
  86. list: [],
  87. total: 0,
  88. skip: 0,
  89. limit: 6,
  90. page: 0,
  91. one: [],
  92. two: [],
  93. thr: [],
  94. // 回复数据
  95. reply: {},
  96. // 列表
  97. code: ''
  98. };
  99. },
  100. onLoad: function(e) {
  101. const that = this;
  102. that.$set(that, `id`, e.id || '');
  103. that.watchLogin()
  104. },
  105. methods: {
  106. async confirm(e) {
  107. const that = this;
  108. let reply = that.reply
  109. let obj = {
  110. content: e,
  111. time: moment().format('YYYY-MM-DD HH:mm:ss')
  112. }
  113. reply.reply.push(obj)
  114. const arr = await that.$api(`/goodsRate/${that.reply._id}`, 'POST', reply)
  115. if (arr.errcode == '0') {
  116. uni.showToast({
  117. title: `回复成功`,
  118. icon: 'success',
  119. });
  120. that.$set(that, `reply`, {});
  121. } else {
  122. uni.showToast({
  123. title: arr.errmsg,
  124. icon: 'none',
  125. })
  126. }
  127. },
  128. // 回复
  129. toReply(e) {
  130. const that = this;
  131. that.$set(that, `reply`, e);
  132. },
  133. // 放大
  134. toLarge(e, index) {
  135. let url = e.reply[0].file.map(item => item.url)
  136. uni.previewImage({
  137. current: index,
  138. urls: url
  139. })
  140. },
  141. // 选择
  142. toSelect(e) {
  143. const that = this;
  144. that.$set(that, `code`, e.code);
  145. if (e.code == '0') {
  146. // that.clearPage();
  147. that.search()
  148. } else if (e.code == '1') {
  149. that.$set(that, `list`, that.one);
  150. } else if (e.code == '2') {
  151. that.$set(that, `list`, that.two);
  152. } else {
  153. that.$set(that, `list`, that.thr);
  154. }
  155. },
  156. // 监听用户是否登录
  157. watchLogin() {
  158. const that = this;
  159. uni.getStorage({
  160. key: 'token',
  161. success: function(res) {
  162. let user = that.$jwt(res.data);
  163. that.$set(that, `user`, user);
  164. that.search()
  165. },
  166. fail: function(err) {
  167. uni.reLaunch({
  168. url: `/pages/login/index`
  169. })
  170. }
  171. })
  172. },
  173. // 查询列表
  174. async search() {
  175. const that = this;
  176. let user = that.user;
  177. let res;
  178. res = await that.$api(`/viewGoods/goodsDetail`, `POST`, {
  179. id: that.id
  180. });
  181. if (res.errcode == '0') {
  182. that.$set(that, `info`, res.data)
  183. }
  184. let info = {
  185. // skip: that.skip,
  186. // limit: that.limit,
  187. goods: that.id
  188. }
  189. res = await that.$api(`/goodsRate`, `GET`, {
  190. ...info,
  191. })
  192. if (res.errcode == '0') {
  193. // let list = [...that.list, ...res.data]
  194. let list = res.data;
  195. for (let val of list) {
  196. val.customer.phone = val.customer.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
  197. }
  198. that.$set(that, `list`, list)
  199. that.$set(that, `total`, res.total)
  200. that.$set(that.btnlist[0], `total`, res.total)
  201. let one = list.filter(item => item.goods_score == 5);
  202. that.$set(that, `one`, one)
  203. that.$set(that.btnlist[1], `total`, one.length);
  204. let two = list.filter(item => item.goods_score < 5 && item.goods_score > 2)
  205. that.$set(that, `two`, two)
  206. that.$set(that.btnlist[2], `total`, two.length);
  207. let thr = list.filter(item => item.goods_score <= 2)
  208. that.$set(that, `thr`, thr)
  209. that.$set(that.btnlist[3], `total`, thr.length);
  210. } else {
  211. uni.showToast({
  212. title: res.errmsg,
  213. });
  214. }
  215. },
  216. // 分页
  217. toPage(e) {
  218. const that = this;
  219. let list = that.list;
  220. let limit = that.limit;
  221. if (that.total > list.length) {
  222. uni.showLoading({
  223. title: '加载中',
  224. mask: true
  225. })
  226. let page = that.page + 1;
  227. that.$set(that, `page`, page)
  228. let skip = page * limit;
  229. that.$set(that, `skip`, skip)
  230. that.search();
  231. uni.hideLoading();
  232. } else uni.showToast({
  233. title: '没有更多数据了',
  234. icon: 'none'
  235. });
  236. },
  237. // 清空列表
  238. clearPage() {
  239. const that = this;
  240. that.$set(that, `list`, [])
  241. that.$set(that, `skip`, 0)
  242. that.$set(that, `limit`, 6)
  243. that.$set(that, `page`, 0)
  244. }
  245. }
  246. }
  247. </script>
  248. <style lang="scss">
  249. .main {
  250. display: flex;
  251. flex-direction: column;
  252. width: 100vw;
  253. height: 100vh;
  254. background-color: var(--f1Color);
  255. .one {
  256. margin: 0 0 2vw 0;
  257. .one_1 {
  258. display: flex;
  259. justify-content: space-around;
  260. background-color: var(--mainColor);
  261. margin: 0 0 0.5vw 0;
  262. padding: 2vw;
  263. .text1 {
  264. width: 65vw;
  265. font-size: var(--font16Szie);
  266. }
  267. .text2 {
  268. font-size: var(--font16Szie);
  269. color: var(--f85Color);
  270. text {
  271. margin: 0 0 0 1vw;
  272. color: var(--ff0Color);
  273. }
  274. }
  275. }
  276. .one_2 {
  277. display: flex;
  278. justify-content: space-around;
  279. padding: 2vw;
  280. background-color: var(--mainColor);
  281. }
  282. }
  283. .two {
  284. position: relative;
  285. flex-grow: 1;
  286. .list {
  287. display: flex;
  288. justify-content: space-around;
  289. align-items: flex-start;
  290. background-color: var(--mainColor);
  291. margin: 0 0 2vw 0;
  292. padding: 2vw;
  293. .image {
  294. width: 10vw;
  295. height: 10vw;
  296. border-radius: 10vw;
  297. }
  298. .iconfont {
  299. font-size: 30px;
  300. }
  301. .list_1 {
  302. flex-grow: 1;
  303. width: 85vw;
  304. margin: 0 0 0 2vw;
  305. font-size: var(--font14Size);
  306. .other {
  307. display: flex;
  308. justify-content: space-between;
  309. text:last-child {
  310. font-size: var(--font12Size);
  311. color: var(--f85Color);
  312. }
  313. }
  314. .other1 {
  315. margin: 1vw 0 0 0;
  316. word-break: break-all;
  317. word-wrap: break-word;
  318. }
  319. .flie {
  320. display: flex;
  321. flex-wrap: wrap;
  322. margin: 1vw 0;
  323. .images {
  324. width: 20vw;
  325. height: 20vw;
  326. margin: 0 1vw 0 0;
  327. }
  328. }
  329. .other2 {
  330. display: flex;
  331. justify-content: space-between;
  332. font-size: var(--font12Size);
  333. color: var(--f85Color);
  334. margin: 2vw 0 0 0;
  335. .reply {
  336. display: flex;
  337. flex-direction: column;
  338. width: 70vw;
  339. word-wrap: break-word;
  340. word-break: break-all;
  341. }
  342. .reply_2 {
  343. display: flex;
  344. flex-direction: column;
  345. word-wrap: break-word;
  346. word-break: break-all;
  347. }
  348. }
  349. }
  350. }
  351. }
  352. }
  353. .scroll-view {
  354. position: absolute;
  355. top: 0;
  356. left: 0;
  357. right: 0;
  358. bottom: 0;
  359. .list-scroll-view {
  360. display: flex;
  361. flex-direction: column;
  362. }
  363. }
  364. </style>