index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. <template>
  2. <view :style="colorStyle">
  3. <!-- #ifdef MP -->
  4. <NavBar titleText="分销等级" iconColor="#333333" textColor="#333333" showBack></NavBar>
  5. <!-- #endif -->
  6. <view class='member-center' :style="{'--level-theme':levelInfo.color}">
  7. <view class="background" :style="{
  8. backgroundImage: `linear-gradient(180deg, ${colorToRgba(levelInfo.color, 0.1)} 0%, ${colorToRgba(levelInfo.color, 0)} 100%)`
  9. }"></view>
  10. <view class='header acea-row row-middle'>
  11. <view class="avatar">
  12. <image :src="userInfo.avatar" class="image"></image>
  13. </view>
  14. <view class="text">
  15. <view class="name">{{userInfo.nickname}}</view>
  16. <view class="badge acea-row row-center-wrapper" :style="[badgeStyle]">
  17. <text class="iconfont icon-huiyuandengji"></text>
  18. <text>{{ userInfo.agent_level ? `V${levelInfo.grade}` : '未解锁' }}</text>
  19. </view>
  20. </view>
  21. </view>
  22. <view class="skill-section" :style="{
  23. borderColor: colorToRgba(levelInfo.color, 0.6),
  24. backgroundImage: `linear-gradient(to right, ${colorToRgba(levelInfo.color, 0.2)}, ${colorToRgba(levelInfo.color, 0)},${colorToRgba(levelInfo.color, 0.2)})`
  25. }">
  26. <image :src="levelInfo.image" class="badge"></image>
  27. <view class="section-hd">
  28. <view class="title acea-row row-middle">
  29. {{`V`+levelInfo.grade}}
  30. <template v-if="userInfo.agent_level">升级中</template>
  31. <template v-else>等级未解锁<text class="iconfont icon-ic_"></text></template>
  32. </view>
  33. <view v-if="task.length" class="task acea-row row-middle">
  34. 以下任务全部达成即可升级
  35. <text class="task-item task-num">
  36. {{ taskNum }}
  37. </text>
  38. <text class="task-item">
  39. /{{ task.length}}
  40. </text>
  41. </view>
  42. </view>
  43. <view class="level-grow-wrap acea-row row-middle">
  44. <view class="level-info acea-row row-middle" :class="">
  45. <view class="level-info-title">一级分佣上浮</view>
  46. <view class="num">
  47. {{ levelInfo.one_brokerage || 0 }}<text class="percent">%</text>
  48. </view>
  49. </view>
  50. <view class="level-info acea-row row-middle" :class="">
  51. <view class="level-info-title">二级分佣上浮</view>
  52. <view class="num">
  53. {{ levelInfo.two_brokerage || 0 }}<text class="percent">%</text>
  54. </view>
  55. </view>
  56. </view>
  57. <view v-if="task.length" class="section-bd">
  58. <view class="item acea-row row-middle" v-for="(item,index) in task" :key='item.id'>
  59. <view class="item-content">
  60. <view class="title">{{item.name}}</view>
  61. <view class="acea-row row-middle">
  62. <view class="progress-wrap">
  63. <view class="progress">
  64. <view class="back"></view>
  65. <view :style="{width: `${Math.floor((item.new_number / item.number) > 1 ? 100 : item.new_number / item.number* 100)}%`}" class="inner"></view>
  66. </view>
  67. <view class="info-box acea-row row-between-wrapper">
  68. <view class="info">{{item.finish ? '' : item.task_type_title}}</view>
  69. <view class="link" hover-class="none">
  70. <text class="new-number">{{item.new_number}}</text>
  71. /{{item.number}}
  72. </view>
  73. </view>
  74. </view>
  75. </view>
  76. </view>
  77. <view v-if="item.finish" class="button">已完成</view>
  78. <view v-else-if="item.type==1" class="button" @click="jumbPath(0)">去邀请</view>
  79. <view v-else class="button" @click="jumbPath(1)">去逛逛</view>
  80. </view>
  81. </view>
  82. </view>
  83. <view v-if="hostProduct.length" class="px-20">
  84. <recommend :hostProduct="hostProduct"></recommend>
  85. </view>
  86. <view class='growthValue' :class='growthValue==false?"on":""'>
  87. <text class='iconfont icon-guanbi3' @click='growthValue = true'></text>
  88. <view class='conter'>{{illustrate}}</view>
  89. </view>
  90. <view class='mask' :hidden='growthValue' @click='growthValueClose'></view>
  91. </view>
  92. <!-- #ifdef MP -->
  93. <authorize v-if="isShowAuth" @authColse="authColse" @onLoadFun="onLoadFun"></authorize>
  94. <!-- #endif -->
  95. </view>
  96. </template>
  97. <script>
  98. import {
  99. agentLevelList,
  100. agentLevelTaskList
  101. } from '@/api/user.js';
  102. import {
  103. getProductHot
  104. } from '@/api/store.js';
  105. import {
  106. toLogin
  107. } from '@/libs/login.js';
  108. import {
  109. mapGetters
  110. } from "vuex";
  111. import recommend from '@/components/recommend';
  112. import colors from '@/mixins/color.js';
  113. import NavBar from '@/components/NavBar.vue'
  114. export default {
  115. components: {
  116. recommend,
  117. NavBar
  118. },
  119. mixins: [colors],
  120. data() {
  121. return {
  122. reach_count: 0,
  123. distributionLevel: [],
  124. swiperIndex: 0,
  125. growthValue: true,
  126. task: [], //任务列表
  127. illustrate: '', //任务说明
  128. level_id: 0, //任务id,
  129. hostProduct: [],
  130. grade: 0,
  131. hotScroll: false,
  132. hotPage: 1,
  133. hotLimit: 10,
  134. level_title: '',
  135. level_discount: '',
  136. levelInfo: {},
  137. userInfo: {},
  138. taskInfo: {},
  139. taskNum: 0,
  140. isShowAuth: false
  141. };
  142. },
  143. computed: {
  144. ...mapGetters(['isLogin']),
  145. badgeStyle() {
  146. let styleObject = {};
  147. if (this.levelInfo.color) {
  148. styleObject['background'] = `linear-gradient(90deg, #FFFFFF 0%, rgba(255, 255, 255, 0.3) 51%, ${this.colorToRgba(this.levelInfo.color, 0.1)} 100%)`;
  149. styleObject['color'] = this.levelInfo.color;
  150. }
  151. return styleObject;
  152. },
  153. },
  154. watch: {
  155. distributionLevel: function() {
  156. let that = this;
  157. if (that.distributionLevel.length > 0) {
  158. that.distributionLevel.forEach(function(item, index) {
  159. if (item.is_clear === false) {
  160. // that.swiper.slideTo(index);
  161. that.activeIndex = index;
  162. that.grade = item.grade;
  163. }
  164. });
  165. }
  166. },
  167. isLogin: {
  168. handler: function(newV, oldV) {
  169. if (newV) {
  170. // this.get_host_product();
  171. }
  172. },
  173. deep: true
  174. }
  175. },
  176. onLoad() {
  177. this.get_host_product();
  178. if (this.isLogin) {
  179. this.agentLevelList();
  180. } else {
  181. toLogin()
  182. }
  183. },
  184. onShow() {
  185. uni.removeStorageSync('form_type_cart');
  186. },
  187. methods: {
  188. onLoadFun() {
  189. this.agentLevelList();
  190. this.isShowAuth = false
  191. },
  192. // 授权关闭
  193. authColse: function(e) {
  194. this.isShowAuth = e
  195. },
  196. agentLevelList: function() {
  197. agentLevelList().then(res => {
  198. const {
  199. level_info,
  200. level_list,
  201. task,
  202. user
  203. } = res.data;
  204. this.levelInfo = level_info;
  205. this.distributionLevel = level_list;
  206. this.userInfo = user;
  207. this.taskInfo = task;
  208. this.levelInfo.exp = parseFloat(this.levelInfo.exp);
  209. this.levelInfo.rate = Math.floor(this.levelInfo.exp / this.levelInfo.exp_num * 100);
  210. if (this.levelInfo.rate > 100) {
  211. this.levelInfo.rate = 100;
  212. }
  213. const index = level_list.findIndex((
  214. grade, v
  215. ) =>
  216. grade.id === user.agent_level
  217. );
  218. if (index !== -1) {
  219. this.swiperIndex = index === -1 ? 0 : (index + 1);
  220. }
  221. if (index === -1) {
  222. this.levelInfo = {
  223. ...this.levelInfo,
  224. ...this.distributionLevel[0]
  225. };
  226. }
  227. this.level_id = this.distributionLevel[index === -1 ? 0 : (index + 1)].id || 0;
  228. this.getTask();
  229. });
  230. },
  231. /**
  232. * 获取我的推荐
  233. */
  234. get_host_product: function() {
  235. let that = this;
  236. if (that.hotScroll) return
  237. getProductHot(
  238. that.hotPage,
  239. that.hotLimit,
  240. ).then(res => {
  241. that.hotPage++
  242. that.hotScroll = res.data.length < that.hotLimit
  243. that.hostProduct = that.hostProduct.concat(res.data)
  244. });
  245. },
  246. /**
  247. * 会员切换
  248. *
  249. */
  250. swiperChange(e) {
  251. let index = e.detail.current;
  252. this.swiperIndex = index;
  253. this.level_id = this.distributionLevel[index].id || 0;
  254. this.level_title = this.distributionLevel[index].name || '';
  255. this.level_discount = this.distributionLevel[index].discount || '';
  256. // this.grade = this.distributionLevel[index].grade
  257. this.getTask();
  258. },
  259. /**
  260. * 关闭说明
  261. */
  262. growthValueClose: function() {
  263. this.growthValue = true;
  264. },
  265. /**
  266. * 打开说明
  267. */
  268. opHelp: function(index) {
  269. this.growthValue = false;
  270. this.illustrate = this.task[index].desc;
  271. },
  272. /**
  273. * 获取任务要求
  274. */
  275. getTask: function() {
  276. let that = this;
  277. that.taskNum = 0
  278. agentLevelTaskList(that.level_id).then(res => {
  279. that.task = res.data.list
  280. for (let i = 0; i < that.task.length; i++) {
  281. if (that.task[i].finish) {
  282. that.taskNum += 1
  283. }
  284. }
  285. });
  286. },
  287. //跳转
  288. jumbPath(type) {
  289. let path = [
  290. '/pages/extension/invite_friend/index',
  291. '/pages/goods/goods_list/index',
  292. ]
  293. uni.navigateTo({
  294. url: path[type]
  295. })
  296. },
  297. colorToRgba(str, n) {
  298. if (!str) {
  299. return
  300. }
  301. // 十六进制颜色值的正则表达式
  302. const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
  303. let sColor = str.toLowerCase();
  304. // 十六进制颜色转换为RGB格式
  305. if (sColor && reg.test(sColor)) {
  306. if (sColor.length === 4) {
  307. let sColorNew = '#';
  308. for (let i = 1; i < 4; i += 1) {
  309. sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
  310. }
  311. sColor = sColorNew;
  312. }
  313. // 处理六位颜色值
  314. const sColorChange = [];
  315. for (let k = 1; k < 7; k += 2) {
  316. sColorChange.push(parseInt(`0x${sColor.slice(k, k + 2)}`, 16));
  317. }
  318. return `rgba(${sColorChange.join(',')}, ${n})`;
  319. }
  320. return sColor;
  321. },
  322. },
  323. onPageScroll(e) {
  324. uni.$emit('scroll');
  325. },
  326. onReachBottom() {
  327. if (!this.hotScroll) {
  328. this.get_host_product();
  329. }
  330. }
  331. }
  332. </script>
  333. <style lang="scss" scoped>
  334. .swiper {
  335. .swiper-item {
  336. height: 100%;
  337. border-radius: 6rpx;
  338. background: center/100% 100% no-repeat;
  339. transform: scale(0.9);
  340. transition: all 0.2s ease-in 0s;
  341. line-height: 1.1;
  342. &.on {
  343. transform: none;
  344. }
  345. }
  346. .user-wrap {
  347. padding-top: 20rpx;
  348. padding-left: 22rpx;
  349. line-height: 1.1;
  350. .image {
  351. width: 90rpx;
  352. height: 90rpx;
  353. border-radius: 50%;
  354. }
  355. .user-msg {
  356. margin-left: 14rpx;
  357. .text {
  358. flex: 1;
  359. display: flex;
  360. align-items: center;
  361. min-width: 0;
  362. font-size: 22rpx;
  363. color: #666666;
  364. .num {
  365. margin-right: 10rpx;
  366. margin-left: 10rpx;
  367. font-size: 30rpx;
  368. font-style: italic;
  369. }
  370. }
  371. }
  372. .name {
  373. flex: 1;
  374. overflow: hidden;
  375. white-space: nowrap;
  376. text-overflow: ellipsis;
  377. font-weight: bold;
  378. font-size: 28rpx;
  379. color: #fff;
  380. margin-right: 8rpx;
  381. }
  382. .state {
  383. position: absolute;
  384. top: 0rpx;
  385. right: 0;
  386. width: 70rpx;
  387. height: 70rpx;
  388. .lock {
  389. width: 100%;
  390. height: 100%;
  391. }
  392. }
  393. }
  394. .grow-wrap {
  395. padding-left: 34rpx;
  396. margin-top: 70rpx;
  397. font-size: 20rpx;
  398. color: #474747;
  399. display: flex;
  400. .num {
  401. margin-right: 8rpx;
  402. margin-left: 8rpx;
  403. font-size: 26rpx;
  404. }
  405. }
  406. .level {
  407. font-size: 24rpx;
  408. color: #fff;
  409. border-radius: 4rpx;
  410. border: 1px solid #fff;
  411. padding: 3rpx 8rpx;
  412. }
  413. }
  414. .skill-section {
  415. position: relative;
  416. padding: 32rpx 24rpx;
  417. border: 2rpx solid transparent;
  418. border-radius: 32rpx;
  419. margin: 0 20rpx;
  420. background-repeat: no-repeat;
  421. background-size: 100% 100%;
  422. .badge {
  423. position: absolute;
  424. top: -104rpx;
  425. right: 38rpx;
  426. width: 238rpx;
  427. height: 192rpx;
  428. }
  429. .section-hd {
  430. .title {
  431. font-weight: 500;
  432. font-size: 28rpx;
  433. line-height: 40rpx;
  434. color: #333333;
  435. .iconfont {
  436. margin-left: 4rpx;
  437. font-size: 28rpx;
  438. }
  439. }
  440. .task {
  441. margin-top: 8rpx;
  442. color: #999999;
  443. font-size: 24rpx;
  444. }
  445. .task-item {
  446. font-family: Regular;
  447. font-size: 28rpx;
  448. }
  449. .task-num {
  450. margin-left: 8rpx;
  451. color: var(--level-theme);
  452. }
  453. }
  454. .section-bd {
  455. padding: 32rpx;
  456. border-radius: 24rpx;
  457. background-color: #FFFFFF;
  458. .item {
  459. +.item {
  460. margin-top: 32rpx;
  461. }
  462. }
  463. .item-content {
  464. flex: 1;
  465. }
  466. .title {
  467. font-weight: 500;
  468. font-size: 28rpx;
  469. line-height: 40rpx;
  470. color: #333333;
  471. }
  472. .progress-wrap {
  473. flex: 1;
  474. padding-right: 32rpx;
  475. }
  476. .progress {
  477. position: relative;
  478. .back {
  479. height: 8rpx;
  480. border-radius: 4rpx;
  481. background-color: var(--level-theme);
  482. opacity: 0.1;
  483. }
  484. .inner {
  485. position: absolute;
  486. top: 0;
  487. left: 0;
  488. height: 8rpx;
  489. border-radius: 4rpx;
  490. background-color: var(--level-theme);
  491. }
  492. }
  493. .info-box {
  494. margin-top: 12rpx;
  495. }
  496. .info {
  497. font-size: 22rpx;
  498. line-height: 30rpx;
  499. color: #999999;
  500. }
  501. .link {
  502. font-family: Regular;
  503. font-size: 28rpx;
  504. line-height: 28rpx;
  505. color: #999999;
  506. .new-number {
  507. color: #333333;
  508. }
  509. }
  510. .button {
  511. height: 64rpx;
  512. padding: 0 32rpx;
  513. border-radius: 32rpx;
  514. background-color: var(--level-theme);
  515. font-weight: 500;
  516. font-size: 24rpx;
  517. line-height: 64rpx;
  518. color: #FFFFFF;
  519. }
  520. }
  521. }
  522. .background {
  523. position: absolute;
  524. top: 0;
  525. left: 0;
  526. width: 100%;
  527. height: 664rpx;
  528. // background: linear-gradient(180deg, rgba(217, 126, 29, 0.1) 0%, rgba(217, 126, 29, 0) 100%);
  529. }
  530. .member-center .header {
  531. padding: 40rpx 296rpx 36rpx 32rpx;
  532. .avatar {
  533. width: 88rpx;
  534. height: 88rpx;
  535. .image {
  536. width: 100%;
  537. height: 100%;
  538. border: 4rpx solid #FFFFFF;
  539. border-radius: 50%;
  540. }
  541. }
  542. .text {
  543. flex: 1;
  544. padding-left: 20rpx;
  545. }
  546. .name {
  547. font-size: 32rpx;
  548. line-height: 44rpx;
  549. color: #333333;
  550. }
  551. .badge {
  552. display: inline-flex;
  553. min-width: 84rpx;
  554. height: 32rpx;
  555. padding: 0 10rpx;
  556. border-radius: 16rpx;
  557. margin-top: 8rpx;
  558. background: linear-gradient(90deg, #FFFFFF 0%, rgba(255, 255, 255, 0.3) 51%, rgba(217, 126, 29, 0.1) 100%);
  559. vertical-align: middle;
  560. font-weight: 500;
  561. font-size: 22rpx;
  562. line-height: 32rpx;
  563. color: var(--level-theme);
  564. .image {
  565. width: 32rpx;
  566. height: 32rpx;
  567. margin-right: 4rpx;
  568. }
  569. .iconfont {
  570. margin-right: 4rpx;
  571. font-size: 32rpx;
  572. }
  573. }
  574. }
  575. .member-center .header swiper {
  576. position: relative;
  577. }
  578. .member-center .growthValue {
  579. background-color: #fff;
  580. border-radius: 16rpx;
  581. position: fixed;
  582. top: 266rpx;
  583. left: 50%;
  584. width: 560rpx;
  585. min-height: 440rpx;
  586. margin-left: -280rpx;
  587. z-index: 99;
  588. transform: translate3d(0, -200%, 0);
  589. transition: all .3s cubic-bezier(.25, .5, .5, .9);
  590. }
  591. .member-center .growthValue.on {
  592. transform: translate3d(0, 0, 0);
  593. }
  594. .member-center .growthValue .pictrue {
  595. width: 100%;
  596. height: 257rpx;
  597. position: relative;
  598. }
  599. .member-center .growthValue .pictrue image {
  600. width: 100%;
  601. height: 100%;
  602. border-radius: 16rpx 16rpx 0 0;
  603. }
  604. .member-center .growthValue .conter {
  605. padding: 0 35rpx;
  606. font-size: 30rpx;
  607. color: #333;
  608. margin-top: 58rpx;
  609. line-height: 1.5;
  610. height: 350rpx;
  611. overflow: auto;
  612. }
  613. .member-center .growthValue .iconfont {
  614. position: absolute;
  615. font-size: 65rpx;
  616. color: #fff;
  617. bottom: -90rpx;
  618. left: 50%;
  619. transform: translateX(-50%);
  620. }
  621. .level-grow-wrap {
  622. height: 92rpx;
  623. .level-info {
  624. margin-right: 72rpx;
  625. .level-info-title {
  626. font-size: 24rpx;
  627. color: #999999;
  628. }
  629. .num {
  630. font-family: Regular;
  631. margin-left: 20rpx;
  632. font-weight: 600;
  633. font-size: 36rpx;
  634. color: var(--level-theme);
  635. .percent {
  636. font-weight: 500;
  637. font-size: 32rpx;
  638. }
  639. }
  640. }
  641. .lock-sty {
  642. opacity: 0.7;
  643. }
  644. }
  645. .swiper .level-sty {
  646. opacity: 0.7;
  647. }
  648. </style>