poster.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <template>
  2. <view class="page">
  3. <!-- 头部吸顶tab标签 -->
  4. <u-sticky bgColor="#fff">
  5. <view class="tabView">
  6. <u-tabs :list="classifyList" @click="click" :current="current" :scrollable="false" lineWidth="32"
  7. :activeStyle="{ color: '#333', fontWeight: 'bold' }" :inactiveStyle="{ color: '#999' }"
  8. :itemStyle="{ height: '48rpx' }"></u-tabs>
  9. </view>
  10. </u-sticky>
  11. <!-- 海报图片列表 -->
  12. <view class="waterfallImage">
  13. <image class="poster-img" :src="item.url" mode="" v-for="(item, index) in imgList" :key="item.path"
  14. @click="showLargeImage(item.path)"></image>
  15. </view>
  16. <!-- 大图预览弹窗 -->
  17. <u-overlay :show="showLargeImageShow" @click="showLargeImageShow = false" :opacity="0.6" class="u-overlay">
  18. <view class="close-btn dis a-c j-c" @click="showLargeImageShow = false">×</view>
  19. <view class="posterview u-overlay dis f-c" @tap.stop>
  20. <image class="promoImage" :src="sctiveimg" mode=""></image>
  21. <view class="userinfo dis a-c j-s">
  22. <view class="dis f-c">
  23. <view class="item dis mb-1">
  24. <view>业务员</view>
  25. <text>{{ userInfo.sysUser.name }}</text>
  26. </view>
  27. <view class="item dis">
  28. <view>电话</view>
  29. <text>{{ userInfo.sysUser.mobile }}</text>
  30. </view>
  31. </view>
  32. <view class="panelcanvas " id="panelcanvas">
  33. <image :src="qrcodeImg" mode="widthFix" lazy-load></image>
  34. </view>
  35. </view>
  36. </view>
  37. <!-- 分享操作栏 -->
  38. <view class="share-prop" @tap.stop>
  39. <view class="header-title dis a-c j-c">分享到</view>
  40. <view class="foo-btn dis a-c j-s">
  41. <view class="interact-item dis f-c a-c">
  42. <image src="/static/icon/tool/saveImg.png" mode=""></image>
  43. <text>保存到相册</text>
  44. </view>
  45. <view class="interact-item dis f-c a-c">
  46. <image src="/static/icon/tool/wx.png" mode=""></image>
  47. <text>微信</text>
  48. </view>
  49. <view class="interact-item dis f-c a-c">
  50. <image src="/static/icon/tool/friendsCircleLogo.png" mode=""></image>
  51. <text>朋友圈</text>
  52. </view>
  53. </view>
  54. </view>
  55. </u-overlay>
  56. </view>
  57. </template>
  58. <script>
  59. import {
  60. mapState,
  61. mapMutations
  62. } from "vuex"
  63. import QR from "@/common/wxqrcode.js"
  64. import {
  65. turnBase64Image
  66. } from '@/plugins/utils.js';
  67. export default {
  68. data() {
  69. return {
  70. current: 0,
  71. showLargeImageShow: false,
  72. qrcodeImg: "", //二维码图片
  73. currentTab: 'baoxian', // 当前选中分类
  74. sctiveimg: "", // 放大显示的图片
  75. classifyList: [ // 分类标签
  76. {
  77. name: '保险',
  78. key: 'baoxian'
  79. },
  80. {
  81. name: '产品',
  82. key: 'product'
  83. },
  84. {
  85. name: '节气',
  86. key: 'season'
  87. },
  88. {
  89. name: '节日',
  90. key: 'festival'
  91. },
  92. {
  93. name: '增员',
  94. key: 'recruit'
  95. }
  96. ],
  97. posterData: { // 分类图片数据
  98. baoxian: [
  99. '/static/image/poster/baoxian/poster1.jpg',
  100. '/static/image/poster/baoxian/poster2.jpg',
  101. '/static/image/poster/baoxian/poster3.jpg',
  102. '/static/image/poster/baoxian/poster4.jpg',
  103. '/static/image/poster/baoxian/poster5.jpg',
  104. '/static/image/poster/baoxian/poster6.jpg',
  105. '/static/image/poster/baoxian/poster7.jpg',
  106. '/static/image/poster/baoxian/poster8.jpg',
  107. ],
  108. product: [
  109. '/static/image/poster/product/poster1.jpg',
  110. ],
  111. season: [],
  112. festival: [
  113. '/static/image/poster/festival/poster1.jpg',
  114. '/static/image/poster/festival/poster2.jpg',
  115. '/static/image/poster/festival/poster3.jpg',
  116. '/static/image/poster/festival/poster4.jpg',
  117. '/static/image/poster/festival/poster5.jpg',
  118. '/static/image/poster/festival/poster6.jpg',
  119. ],
  120. recruit: [],
  121. // ...其他分类
  122. },
  123. imageCache: {}, // 缓存已转换的Base64图片
  124. imgList: [], // 当前分类图片({path,url},url为base64,规避App端路径图首帧漏显)
  125. };
  126. },
  127. onLoad() {
  128. this.qrcodeImg = QR.createQrCodeImg(this.$base.h5BaseUrl + '"/#/pages/registr/h5Registr?systemCode=' + this
  129. .system_code, {
  130. size: parseInt(200) //二维码大小
  131. })
  132. this.loadImgList(this.posterData[this.currentTab] || []); // 首屏分类图片转 base64
  133. },
  134. onReady() {
  135. },
  136. computed: {
  137. ...mapState(['userInfo', 'system_code'])
  138. },
  139. methods: {
  140. // 切换分类
  141. click(tab) {
  142. if (this.currentTab === tab.key) return; // 同分类忽略
  143. this.currentTab = tab.key;
  144. const idx = this.classifyList.findIndex(item => item.key === tab.key);
  145. if (idx > -1) this.current = idx; // 同步 u-tabs 选中态
  146. this.loadImgList(this.posterData[tab.key] || []);
  147. },
  148. // 把分类图片路径批量转成 base64(App 端 /static 路径图首帧会随机漏显,base64 dataURL 显示稳定)
  149. async loadImgList(paths) {
  150. this.imgList = []; // 先清空,避免切换分类时旧图残留
  151. const tasks = (paths || []).map(async (p) => {
  152. try {
  153. if (!this.imageCache[p]) {
  154. this.imageCache[p] = await turnBase64Image(p);
  155. }
  156. return {
  157. path: p,
  158. url: this.imageCache[p]
  159. };
  160. } catch (e) {
  161. console.error('海报图转换失败:', p, e);
  162. return null;
  163. }
  164. });
  165. this.imgList = (await Promise.all(tasks)).filter(Boolean);
  166. },
  167. // 显示大图(带缓存优化)
  168. async showLargeImage(item) {
  169. try {
  170. if (!this.imageCache[item]) {
  171. this.imageCache[item] = await turnBase64Image(item);
  172. }
  173. this.sctiveimg = this.imageCache[item];
  174. this.showLargeImageShow = true;
  175. } catch (error) {
  176. console.error("图片转换失败:", error);
  177. uni.showToast({
  178. title: "图片加载失败",
  179. icon: "none"
  180. });
  181. }
  182. }
  183. }
  184. };
  185. </script>
  186. <style lang="scss" scoped>
  187. .page {
  188. background-color: #f8f8f8;
  189. height: 100vh;
  190. }
  191. .tabView {
  192. padding: 20rpx 0;
  193. box-sizing: border-box;
  194. }
  195. /* 网格布局 */
  196. .waterfallImage {
  197. background-color: #f8f8f8;
  198. padding: 30rpx;
  199. display: grid;
  200. grid-template-columns: repeat(2, 1fr);
  201. gap: 30rpx;
  202. .poster-img {
  203. border-radius: 10rpx;
  204. width: 100%;
  205. height: 484rpx;
  206. }
  207. }
  208. /* 大图预览弹窗 */
  209. .posterview {
  210. margin: 20% 80rpx 0;
  211. background-color: #fff;
  212. border-radius: 10rpx;
  213. position: relative;
  214. .promoImage {
  215. width: 100%;
  216. height: 860rpx;
  217. border-radius: 10rpx 10rpx 0 0;
  218. }
  219. .userinfo {
  220. padding: 25rpx 40rpx;
  221. .item {
  222. font-size: 28rpx;
  223. view:first-child {
  224. color: #666;
  225. width: 84rpx;
  226. }
  227. text:last-child {
  228. color: #333;
  229. margin-left: 36rpx;
  230. }
  231. }
  232. .panelcanvas {
  233. position: relative;
  234. image {
  235. width: 100rpx;
  236. height: 100rpx;
  237. }
  238. }
  239. }
  240. }
  241. /* 分享操作栏 */
  242. .share-prop {
  243. position: absolute;
  244. bottom: 0;
  245. left: 0;
  246. width: 100%;
  247. background-color: #fff;
  248. border-radius: 20rpx 20rpx 0 0;
  249. .header-title {
  250. padding: 24rpx;
  251. font-size: 36rpx;
  252. color: #333;
  253. font-weight: bold;
  254. border-bottom: 1rpx solid #eee;
  255. }
  256. .foo-btn {
  257. padding: 30rpx 128rpx;
  258. .interact-item {
  259. image {
  260. width: 88rpx;
  261. height: 88rpx;
  262. margin-bottom: 10rpx;
  263. }
  264. text {
  265. font-size: 24rpx;
  266. color: #333;
  267. }
  268. }
  269. }
  270. }
  271. .close-btn {
  272. position: absolute;
  273. width: 50rpx;
  274. height: 50rpx;
  275. right: 20rpx;
  276. top: 20rpx;
  277. font-size: 36rpx;
  278. line-height: 0.8;
  279. font-weight: bold;
  280. z-index: 10;
  281. background-color: #fff;
  282. border-radius: 50%;
  283. }
  284. /* 自定义tab滑块样式 */
  285. ::v-deep .u-tabs__wrapper__nav__line {
  286. background: linear-gradient(90deg, #FDE935 10%, rgba(253, 233, 53, 0.1) 100%) !important;
  287. border-radius: 6rpx;
  288. }
  289. </style>