crowdfundingDetails.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. <template>
  2. <view class="crowdfunding-details">
  3. <view class="custom-navbar" :style="navBgStyle">
  4. <view class="navbar-left scale-tap" @click="goBack">
  5. <image src="@/static/crowdFunding/back.png" mode="widthFix"></image>
  6. </view>
  7. <view class="navbar-center one-omit" style="max-width: 70vw; " :style="{ opacity: navBgOpacity }">
  8. {{ detail.title }}
  9. </view>
  10. <view class="navbar-right scale-tap" @click="showShare = true">
  11. <image src="@/static/crowdFunding/share.png" mode="widthFix"></image>
  12. </view>
  13. </view>
  14. <!-- 顶部视频图片混合轮播 -->
  15. <view class="swiper-container">
  16. <swiper class="top-swiper" :indicator-dots="false" circular :current="currentMediaIndex"
  17. @change="handleSwiperChange" :duration="300">
  18. <swiper-item v-for="(item, idx) in mediaList" :key="idx" class="swiper-item">
  19. <view v-if="item.type === 'video'" class="media-wrapper">
  20. <!-- <DomVideoPlayer style="z-index: -100; position: static;" :src="item.src" :poster="item.poster"
  21. :id="'video-' + idx" :controls="false" :autoplay="false" :loop="false" :muted="false"
  22. :objectFit="'contain'" @play="onVideoPlay(idx)" @pause="onVideoPause"
  23. @ended="onVideoEnded" /> -->
  24. <DomVideoPlayer :ref="'domVideoPlayer' + idx"
  25. :src="item.src" autoplay
  26. loop controls muted @play="onVideoPlay(idx)" @pause="onVideoPause(idx)"/>
  27. </view>
  28. <image v-else class="swiper-img" :src="item.src" mode="aspectFill" />
  29. </swiper-item>
  30. </swiper>
  31. <!-- 自定义指示点 -->
  32. <view class="custom-dots">
  33. <view v-for="(item, index) in mediaList" :key="index"
  34. :class="['dot', currentMediaIndex === index ? 'active' : '']" @click="switchMedia(index)"></view>
  35. </view>
  36. </view>
  37. <view class="content">
  38. <!-- 项目信息 -->
  39. <view class="section project-card">
  40. <view class="project-title">{{ detail.title }}</view>
  41. <view class="progress-bar-wrap">
  42. <uv-line-progress height="8rpx" :showText="false"
  43. :percentage="(detail.current_amount / detail.goal_amount * 100).toFixed(2)"
  44. inactiveColor="#F0F0F0" activeColor="#ACF934"></uv-line-progress>
  45. <view class="progress-percent">{{ (detail.current_amount / detail.goal_amount * 100).toFixed(2) +
  46. '%'
  47. }}</view>
  48. </view>
  49. <view class="project-stats">
  50. <view class="stat-block">
  51. <view class="stat-main amountOfMoney">¥{{ detail.current_amount }}</view>
  52. <view class="stat-sub">{{ detail.supporter_count }}人支持</view>
  53. </view>
  54. <view class="stat-block">
  55. <view class="stat-main">{{ detail.daysRemaining }}天</view>
  56. <view class="stat-sub">剩余时间</view>
  57. </view>
  58. <view class="stat-block">
  59. <view class="stat-main">¥{{ detail.goal_amount }}</view>
  60. <view class="stat-sub">众筹目标</view>
  61. </view>
  62. </view>
  63. </view>
  64. <!-- 项目更新 -->
  65. <view class="section project-update" v-if="projectUpdate && projectUpdate.numb">
  66. <view class="project-update-left scale-tap"
  67. @click="goPage('/pages/crowdFunding/projectUpdateDetails?id=' + projectUpdate.id)">
  68. <view class="project-update-left-title">
  69. <view>·第{{ projectUpdate.numb }}次更新</view>
  70. <view style="color: #999;">{{ projectUpdate.create_time }}</view>
  71. </view>
  72. <view class="project-update-left-content">
  73. <view class="two-omit">{{ projectUpdate.title }}</view>
  74. <view class="image">
  75. <image :src="projectUpdate.image" />
  76. </view>
  77. </view>
  78. </view>
  79. <view class="project-update-right scale-tap"
  80. @click="goPage('/pages/crowdFunding/discussionArea?tags=update&id=' + projectId)">
  81. <view>历史更新</view>
  82. <image src="@/static/crowdFunding/updateDetails.png"></image>
  83. </view>
  84. </view>
  85. <view class="section comment scale-tap"
  86. @click="goPage('/pages/crowdFunding/discussionArea?tags=comment&id=' + projectId)">
  87. <view class="comment-title">
  88. <view>项目讨论({{ totalNumberOfComments }})</view>
  89. <view class="comment-more">查看更多
  90. <image src=" @/static/crowdFunding/right.png">
  91. </image>
  92. </view>
  93. </view>
  94. <view class="comment-content">
  95. <block v-for="(item, idx) in commentList" :key="idx">
  96. <view class="comment-item">
  97. <image class="comment-avatar" :src="item.avatar"></image>
  98. <view class="comment-item-main">
  99. <view class="comment-item-content">{{ item.content }}</view>
  100. </view>
  101. <view class="comment-item-like">
  102. <image class="like-icon"
  103. :src="item.liked ? '/static/icon/icon-18.png' : '/static/icon/icon-19.png'"></image>
  104. <text class="like-num">{{ item.likeNum }}</text>
  105. </view>
  106. </view>
  107. </block>
  108. </view>
  109. </view>
  110. <!-- 塔罗牌介绍 -->
  111. <view class="section poster">
  112. <view class="initiator-bar">
  113. <image class="initiator-avatar" :src="detail.creator_avatar" />
  114. <view class="initiator-info">
  115. <text class="initiator-name">{{ detail.creator_nickname }}</text>
  116. <div class="initiator-tag" @click="certificationTips()">
  117. <image src="@/static/crowdFunding/authentication.png" mode="widthFix"></image>
  118. <div>发起人</div>
  119. </div>
  120. </view>
  121. <view class="initiator-service-btn blick-btn-animation"
  122. @click="goPage('/pages/crowdFunding/customerService?id=' + detail.creator_id + '&zc_id=' + detail.id)">
  123. <image class="service-icon" src="@/static/crowdFunding/service.png" />
  124. <text>客服</text>
  125. </view>
  126. </view>
  127. <block v-for="(item, idx) in detail.content_images" :key="idx">
  128. <image class="intro-img" :src="item" mode="widthFix" />
  129. </block>
  130. </view>
  131. <!-- 风险说明 -->
  132. <view class="section risk-section">
  133. <view class="risk-row" @click="goWeb('https://e.zhichao.art/web/refund.php', '退款说明')">
  134. <view class="risk-title">退款政策</view>
  135. <view class="risk-more ">查看更多
  136. <image src="@/static/crowdFunding/right.png" class="risk-more-icon" />
  137. </view>
  138. </view>
  139. <view class="risk-desc">众筹结束前最后1个小时无法申请退款</view>
  140. <view class="risk-row risk-row-border"
  141. @click="goWeb('https://e.zhichao.art/web/crowdtips.php', '风险提示')">
  142. <view class="risk-title">风险提示</view>
  143. <view class="risk-more ">查看更多
  144. <image src="@/static/crowdFunding/right.png" class="risk-more-icon" />
  145. </view>
  146. </view>
  147. <view class="risk-content">
  148. <view>1. 您参与众筹是支持将创意变为现实的过程,而不是直接的商品交易,因此存在一定风险。请您根据自己的判断选择,支持众筹项目。</view>
  149. <view>2. 众筹存在于发起人与支持者之间,摩点作为第三方平台,提供网络空间、技术支持等服务。众筹的回报产品和承诺由发起人负责。</view>
  150. </view>
  151. </view>
  152. </view>
  153. <view class="bottom-bar-reserveASeat"></view>
  154. <view class="bottom-bar">
  155. <view class="bottom-bar-left">
  156. <view class="bar-btn" @click="toggleFavorite">
  157. <image v-if="isFavorite" src="@/static/crowdFunding/collect-active.png"
  158. class="scale-tap bar-icon" />
  159. <image v-else src="@/static/crowdFunding/collect.png" class="scale-tap bar-icon" />
  160. <view class="bar-text">{{ isFavorite ? '已收藏' : '收藏' }}</view>
  161. </view>
  162. <!-- <view class="bar-btn">
  163. <image v-if="true" src="@/static/crowdFunding/like.png" class=" scale-tap bar-icon" />
  164. <image v-else src="@/static/crowdFunding/like-active.png" class=" scale-tap bar-icon" />
  165. <view class="bar-text">看好</view>
  166. </view> -->
  167. </view>
  168. <button class="buy-btn blick-btn-animation" @click="specificationsOpen()">立即购买支持</button>
  169. </view>
  170. <image src="@/static/crowdFunding/backToTop.png" class="back-top scale-tap" v-show="navBgOpacity > 0.9"
  171. @click="scrollToTop"></image>
  172. <!-- 分享弹窗 -->
  173. <SharePopup :visible="showShare" :userId="0" :share-title="shareTitle" :share-desc="shareDesc"
  174. :share-img="shareImg" view="crowdfundingDetails" :link="shareLink" @close="showShare = false"
  175. :isReportContent="true" />
  176. <productSpecifications ref="specSheet" :rewards="rewards" :title="detail.title" @confirm="onSpecConfirm" />
  177. </view>
  178. </template>
  179. <script>
  180. import VideoPlayer from "@/components/VideoPlayer/VideoPlayer.vue";
  181. import SharePopup from "@/components/SharePopup/SharePopup.vue";
  182. import productSpecifications from "./components/productSpecifications/productSpecifications.vue";
  183. import DomVideoPlayer from "@/components/DomVideoPlayer/DomVideoPlayer.vue";
  184. export default {
  185. components: {
  186. VideoPlayer,
  187. SharePopup,
  188. productSpecifications,
  189. DomVideoPlayer
  190. },
  191. data() {
  192. return {
  193. mediaList: [],
  194. videoPlaying: false,
  195. currentMediaIndex: 0,
  196. commentList: [
  197. ],
  198. navBgOpacity: 0,
  199. swiperHeight: 0,
  200. showShare: false,
  201. shareTitle: '',
  202. shareDesc: '',
  203. shareImg: '',
  204. shareLink: "https://e.zhichao.art/site/#/mobile-download",
  205. userId: 0, // 可根据实际登录用户赋值
  206. isFavorite: false, // 是否已收藏
  207. projectId: null, // 当前项目id
  208. detail: {}, // 众筹详情
  209. projectUpdate: '',
  210. rewards: [],
  211. totalNumberOfComments: 0
  212. }
  213. },
  214. computed: {
  215. navBgStyle() {
  216. return {
  217. background: `rgba(255,255,255,${this.navBgOpacity})`,
  218. transition: 'background 0.3s'
  219. }
  220. }
  221. },
  222. methods: {
  223. // 返回上一页
  224. goBack() {
  225. uni.navigateBack({
  226. delta: 1,
  227. });
  228. },
  229. scrollToTop() {
  230. uni.pageScrollTo({
  231. scrollTop: 0,
  232. duration: 300
  233. });
  234. },
  235. switchMedia(index) {
  236. if (this.currentMediaIndex === index) return;
  237. // 如果当前在播放视频,先暂停
  238. if (this.mediaList[this.currentMediaIndex]?.type === 'video') {
  239. const videoContext = uni.createVideoContext('video-' + this.currentMediaIndex, this);
  240. if (videoContext) {
  241. videoContext.pause();
  242. }
  243. }
  244. this.currentMediaIndex = index;
  245. },
  246. handleSwiperChange(e) {
  247. const lastIndex = this.currentMediaIndex;
  248. this.currentMediaIndex = e.detail.current;
  249. // 如果上一个是视频,暂停它
  250. if (this.mediaList[lastIndex]?.type === 'video') {
  251. const videoContext = uni.createVideoContext('video-' + lastIndex, this);
  252. if (videoContext) {
  253. videoContext.pause();
  254. this.videoPlaying = false;
  255. }
  256. }
  257. },
  258. onVideoPlay(idx) {
  259. // 更新当前播放的视频索引
  260. this.$refs['domVideoPlayer' + idx].play();
  261. },
  262. onVideoPause(idx) {
  263. this.$refs['domVideoPlayer' + idx].pause();
  264. },
  265. onVideoEnded() {
  266. this.videoPlaying = false;
  267. },
  268. goPage(url) {
  269. uni.navigateTo({
  270. url: url
  271. });
  272. },
  273. onSpecConfirm(selectedSpec) {
  274. uni.navigateTo({
  275. url: '/pages/crowdFunding/orderConfirm',
  276. success: function (res) {
  277. // 通过 eventChannel 向被打开页面传送数据
  278. res.eventChannel.emit('acceptDataFromOpener', { selectedSpec: selectedSpec, detail: this.detail });
  279. }.bind(this)
  280. });
  281. },
  282. specificationsOpen() {
  283. this.$refs.specSheet.show();
  284. },
  285. toggleFavorite() {
  286. if (!this.projectId) {
  287. return;
  288. }
  289. const action = this.isFavorite ? 'remove' : 'add';
  290. uni.request({
  291. url: this.$apiHost + '/crowdfund/favorite',
  292. method: 'POST',
  293. header: {
  294. "content-type": "application/x-www-form-urlencoded",
  295. },
  296. data: {
  297. uuid: getApp().globalData.uuid,
  298. skey: getApp().globalData.skey,
  299. crowdfund_id: this.projectId,
  300. action
  301. },
  302. success: (res) => {
  303. console.log(res.data, "收藏");
  304. if (res.data && res.data.success && res.data.success == 'yes') {
  305. this.isFavorite = !this.isFavorite;
  306. uni.showToast({ title: this.isFavorite ? '已收藏' : '已取消收藏', icon: 'none' });
  307. } else {
  308. uni.showToast({ title: res.data.msg || '操作失败', icon: 'none' });
  309. }
  310. },
  311. fail: () => {
  312. uni.showToast({ title: '网络错误', icon: 'none' });
  313. }
  314. });
  315. },
  316. getDetail() {
  317. if (!this.projectId) return;
  318. uni.request({
  319. url: this.$apiHost + '/crowdfund/detail',
  320. method: 'GET',
  321. data: {
  322. id: this.projectId,
  323. uuid: getApp().globalData.uuid,
  324. skey: getApp().globalData.skey
  325. },
  326. success: (res) => {
  327. if (res.data && res.data.success === 'yes' && res.data.data) {
  328. this.processingDataDetails(res.data.data);
  329. // 可根据接口返回字段设置isFavorite等
  330. }
  331. }
  332. });
  333. uni.request({
  334. url: this.$apiHost + '/crowdfund/favorite/status',
  335. method: 'GET',
  336. data: {
  337. crowdfund_id: this.projectId,
  338. uuid: getApp().globalData.uuid,
  339. skey: getApp().globalData.skey
  340. },
  341. success: (res) => {
  342. if (res.data && res.data.success === 'yes' && res.data.data) {
  343. console.log(res.data.data, "收藏");
  344. this.isFavorite = res.data.data.is_favorited;
  345. // 可根据接口返回字段设置isFavorite等
  346. }
  347. }
  348. });
  349. uni.request({
  350. url: this.$apiHost + '/crowdfund/articles',
  351. method: 'GET',
  352. data: {
  353. crowdfund_id: this.projectId,
  354. page: 1,
  355. pageSize: 1,
  356. uuid: getApp().globalData.uuid,
  357. skey: getApp().globalData.skey
  358. },
  359. success: (res) => {
  360. if (res.data && res.data.success === 'yes' && res.data.data) {
  361. if (Array.isArray(res.data.data.list)) {
  362. this.projectUpdate = res.data.data.list[0]
  363. this.projectUpdate.create_time = this.projectUpdate.create_time.replace(/-/g, '.').slice(0, 16)
  364. console.log(this.projectUpdate, 8888);
  365. }
  366. }
  367. }
  368. });
  369. uni.request({
  370. url: this.$apiHost + '/Article/getcomments',
  371. data: {
  372. uuid: getApp().globalData.uuid,
  373. type: 'crowdfund',
  374. id: this.projectId,
  375. page: 1,
  376. limit: 2,
  377. },
  378. header: {
  379. "content-type": "application/json",
  380. 'sign': getApp().globalData.headerSign
  381. },
  382. success: (res) => {
  383. console.log("评论列表:", res.data);
  384. if (res.data.success == "yes") {
  385. this.totalNumberOfComments = res.data.total
  386. // 确保数据存在且是数组,然后只取前两条
  387. this.commentList = (res.data.list || []).slice(0, 2).map(item => ({
  388. avatar: item.user_avatar || '',
  389. content: item.user_content || '',
  390. likeNum: item.like_count || 0,
  391. liked: item.is_like || false
  392. }));
  393. } else {
  394. // 如果请求失败,使用默认空数组
  395. this.commentList = [];
  396. uni.showToast({
  397. title: '获取评论列表失败',
  398. icon: 'none'
  399. });
  400. }
  401. },
  402. fail: (e) => {
  403. console.log("----e:", e);
  404. // 请求失败时使用默认空数组
  405. this.commentList = [];
  406. }
  407. });
  408. },
  409. goWeb(url, title) {
  410. uni.navigateTo({
  411. url: `/pages/webview/index?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`
  412. })
  413. },
  414. processingDataDetails(data) {
  415. this.detail = data;
  416. // 确保 image_list 始终是一个数组
  417. data.image_list = data.image_list || [];
  418. const videoItem = data.video_url ? [{
  419. type: 'video',
  420. poster: data.main_image,
  421. src: data.video_url,
  422. }] : [];
  423. const imageItems = data.image_list.map(v => ({
  424. type: 'image',
  425. src: v
  426. }));
  427. // 计算剩余天数
  428. if (data.start_time && data.end_time) {
  429. const startDate = new Date(data.start_time.replace(/-/g, '/'));
  430. const endDate = new Date(data.end_time.replace(/-/g, '/'));
  431. const now = new Date();
  432. // 如果当前时间在开始时间之前,显示总天数
  433. if (now < startDate) {
  434. this.detail.daysRemaining = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24));
  435. }
  436. // 如果当前时间在结束时间之后,显示0天
  437. else if (now > endDate) {
  438. this.detail.daysRemaining = 0;
  439. }
  440. // 如果当前时间在开始和结束时间之间,显示剩余天数
  441. else {
  442. this.detail.daysRemaining = Math.ceil((endDate - now) / (1000 * 60 * 60 * 24));
  443. }
  444. } else {
  445. this.detail.daysRemaining = 0;
  446. }
  447. // 计算进度
  448. this.detail.progress = (data.current_amount / data.goal_amount * 100).toFixed(2)
  449. console.log(this.detail.progress, "进度");
  450. if (Number.isNaN) this.detail.progress = 0
  451. this.mediaList = [...videoItem, ...imageItems];
  452. this.rewards = data.rewards
  453. this.shareTitle = data.title;
  454. this.shareDesc = data.description;
  455. this.shareImg = data.image_list[0];
  456. console.log("回报数据", this.rewards);
  457. console.log("顶部轮播数据", this.mediaList, "mediaList");
  458. console.log("详情", this.detail, "detail");
  459. },
  460. certificationTips() {
  461. uni.showToast({
  462. title: '官方已实名认证',
  463. icon: 'none'
  464. });
  465. }
  466. },
  467. mounted() {
  468. this.$nextTick(() => {
  469. // 动态获取轮播图高度
  470. uni.createSelectorQuery().in(this).select('.top-swiper').boundingClientRect(rect => {
  471. if (rect) {
  472. this.swiperHeight = rect.height;
  473. }
  474. }).exec();
  475. });
  476. },
  477. onPageScroll(e) {
  478. const threshold = this.swiperHeight || uni.upx2px(400); // 优先用实际高度
  479. let opacity = 0;
  480. if (e.scrollTop > 0) {
  481. opacity = Math.min(e.scrollTop / threshold, 1);
  482. }
  483. this.navBgOpacity = opacity;
  484. },
  485. onLoad(options) {
  486. // 获取id
  487. this.projectId = options.id || null;
  488. this.getDetail();
  489. },
  490. onShow() {
  491. this.getDetail();
  492. },
  493. }
  494. </script>
  495. <style lang="scss" scoped>
  496. .crowdfunding-details {
  497. /* 自定义导航栏样式 */
  498. .custom-navbar {
  499. display: flex;
  500. flex-direction: row;
  501. align-items: center;
  502. justify-content: space-between;
  503. width: 100%;
  504. height: calc(90rpx + var(--status-bar-height));
  505. padding: 0 20rpx;
  506. position: fixed;
  507. top: 0;
  508. z-index: 100;
  509. padding: 12rpx 24rpx;
  510. padding-top: calc(var(--status-bar-height) + 12rpx);
  511. background: transparent;
  512. transition: background 0.3s;
  513. image {
  514. width: 64rpx;
  515. height: 64rpx;
  516. }
  517. }
  518. .swiper-container {
  519. position: relative;
  520. width: 100vw;
  521. height: 100vw;
  522. background: #000;
  523. .top-swiper {
  524. width: 100%;
  525. height: 100%;
  526. .swiper-item {
  527. width: 100%;
  528. height: 100%;
  529. display: flex;
  530. align-items: center;
  531. justify-content: center;
  532. }
  533. .media-wrapper {
  534. width: 100%;
  535. height: 100%;
  536. display: flex;
  537. align-items: center;
  538. justify-content: center;
  539. background: #000;
  540. }
  541. .swiper-video {
  542. width: 100%;
  543. height: 100%;
  544. }
  545. .swiper-img {
  546. width: 100%;
  547. height: 100%;
  548. object-fit: cover;
  549. }
  550. }
  551. .custom-dots {
  552. position: absolute;
  553. bottom: 20rpx;
  554. left: 50%;
  555. transform: translateX(-50%);
  556. display: flex;
  557. gap: 16rpx;
  558. .dot {
  559. width: 12rpx;
  560. height: 12rpx;
  561. border-radius: 50%;
  562. background: rgba(255, 255, 255, 0.5);
  563. transition: all 0.3s;
  564. &.active {
  565. width: 24rpx;
  566. border-radius: 6rpx;
  567. background: #fff;
  568. }
  569. }
  570. }
  571. }
  572. .content {
  573. background: #f2f6f2;
  574. padding: 20rpx;
  575. .section {
  576. background: #fff;
  577. border-radius: 12rpx;
  578. padding: 16rpx;
  579. padding-bottom: 20rpx;
  580. margin: 12rpx 0;
  581. .section-title {
  582. font-size: 28rpx;
  583. font-family: 'PingFang SC-Medium';
  584. margin-bottom: 6rpx;
  585. }
  586. .section-content {
  587. color: #333;
  588. font-size: 24rpx;
  589. line-height: 1.8;
  590. }
  591. .intro-img {
  592. width: 100%;
  593. margin: 0;
  594. padding: 0;
  595. margin-bottom: -10rpx;
  596. }
  597. }
  598. .project-card {
  599. padding-bottom: 15rpx;
  600. .project-title {
  601. font-size: 36rpx;
  602. color: 1f1f1f;
  603. font-family: "PingFang SC-Bold";
  604. font-weight: 400;
  605. }
  606. .progress-bar-wrap {
  607. display: flex;
  608. align-items: center;
  609. font-size: 20rpx;
  610. color: #1F1F1F;
  611. padding-top: 30rpx;
  612. padding-bottom: 14rpx;
  613. .progress-percent {
  614. padding-left: 12rpx;
  615. }
  616. }
  617. .project-stats {
  618. display: flex;
  619. justify-content: space-between;
  620. padding-top: 0;
  621. .stat-block {
  622. display: flex;
  623. flex-direction: column;
  624. align-items: center;
  625. text-align: center;
  626. justify-content: center;
  627. color: #1F1F1F;
  628. &:first-child {
  629. align-items: flex-start;
  630. }
  631. &:last-child {
  632. display: flex;
  633. flex-direction: column;
  634. align-items: center;
  635. text-align: center;
  636. justify-content: center;
  637. color: #1F1F1F;
  638. &:first-child {
  639. align-items: flex-start;
  640. }
  641. &:last-child {
  642. align-items: flex-end;
  643. }
  644. .stat-main {
  645. font-size: 28rpx;
  646. &.amountOfMoney {
  647. font-size: 32rpx;
  648. font-family: "PingFang SC-Bold";
  649. }
  650. }
  651. .stat-sub {
  652. font-size: 20rpx;
  653. }
  654. }
  655. }
  656. }
  657. }
  658. .project-update {
  659. background: transparent;
  660. height: 166rpx;
  661. display: flex;
  662. width: 100%;
  663. justify-content: space-between;
  664. padding: 0;
  665. >view {
  666. border-radius: 12rpx;
  667. background: #fff;
  668. flex-shrink: 0;
  669. }
  670. .project-update-left {
  671. width: 590rpx;
  672. height: 100%;
  673. padding: 16rpx;
  674. .project-update-left-title {
  675. display: flex;
  676. justify-content: space-between;
  677. align-items: center;
  678. font-size: 22rpx;
  679. }
  680. .project-update-left-content {
  681. display: flex;
  682. align-items: center;
  683. margin-top: 8rpx;
  684. >view {
  685. font-size: 24rpx;
  686. font-weight: 400;
  687. font-family: "PingFang SC-Bold";
  688. }
  689. .image {
  690. width: 180rpx;
  691. height: 78rpx;
  692. overflow: hidden;
  693. margin-left: 26rpx;
  694. border-radius: 8rpx;
  695. image {
  696. overflow: hidden;
  697. width: 100%;
  698. }
  699. }
  700. }
  701. }
  702. .project-update-right {
  703. width: 108rpx;
  704. height: 100%;
  705. font-size: 22rpx;
  706. display: flex;
  707. align-items: center;
  708. justify-content: center;
  709. flex-direction: column;
  710. image {
  711. margin-top: 12rpx;
  712. width: 28rpx;
  713. height: 28rpx;
  714. }
  715. }
  716. }
  717. .poster {
  718. padding: 0;
  719. padding-top: 16rpx;
  720. }
  721. }
  722. .comment {
  723. border-radius: 12rpx;
  724. background: #fff;
  725. margin-top: 24rpx;
  726. padding: 0 0 16rpx 0;
  727. .comment-title {
  728. display: flex;
  729. justify-content: space-between;
  730. align-items: center;
  731. font-size: 26rpx;
  732. color: #333;
  733. padding: 18rpx 20rpx 0 20rpx;
  734. .comment-more {
  735. color: #999;
  736. font-size: 22rpx;
  737. display: flex;
  738. align-items: center;
  739. image {
  740. width: 20rpx;
  741. height: 20rpx;
  742. margin-left: 4rpx;
  743. }
  744. }
  745. }
  746. .comment-content {
  747. padding: 0 20rpx;
  748. .comment-item {
  749. display: flex;
  750. //align-items: flex-start;
  751. align-items: center;
  752. padding: 18rpx 0 0 0;
  753. border-bottom: 1rpx solid #f5f5f5;
  754. &:last-child {
  755. border-bottom: none;
  756. }
  757. .comment-avatar {
  758. width: 48rpx;
  759. height: 48rpx;
  760. border-radius: 50%;
  761. margin-right: 16rpx;
  762. flex-shrink: 0;
  763. }
  764. .comment-item-main {
  765. flex: 1;
  766. display: flex;
  767. flex-direction: column;
  768. .comment-item-content {
  769. color: #1f1f1f;
  770. font-size: 24rpx;
  771. line-height: 1.7;
  772. margin-bottom: 8rpx;
  773. display: -webkit-box;
  774. -webkit-line-clamp: 2;
  775. -webkit-box-orient: vertical;
  776. overflow: hidden;
  777. text-overflow: ellipsis;
  778. word-break: break-all;
  779. }
  780. }
  781. .comment-item-like {
  782. display: flex;
  783. align-items: center;
  784. margin-left: 36rpx;
  785. .like-icon {
  786. width: 28rpx;
  787. height: 28rpx;
  788. margin-right: 4rpx;
  789. }
  790. .like-num {
  791. font-size: 22rpx;
  792. color: #888;
  793. }
  794. }
  795. }
  796. }
  797. }
  798. .bottom-bar-reserveASeat {
  799. width: 100%;
  800. height: calc(12rpx + 88rpx + var(--window-bottom) + 30rpx);
  801. }
  802. .bottom-bar {
  803. position: fixed;
  804. left: 0;
  805. right: 0;
  806. bottom: 0;
  807. z-index: 999;
  808. display: flex;
  809. align-items: center;
  810. justify-content: space-between;
  811. background: #fff;
  812. padding: 14rpx 40rpx;
  813. padding-bottom: calc(14rpx + var(--window-bottom));
  814. box-sizing: border-box;
  815. .bottom-bar-left {
  816. display: flex;
  817. align-items: center;
  818. gap: 32rpx;
  819. .bar-btn {
  820. display: flex;
  821. flex-direction: column;
  822. align-items: center;
  823. justify-content: center;
  824. width: 80rpx;
  825. height: 80rpx;
  826. border-radius: 12rpx;
  827. .bar-icon {
  828. width: 48rpx;
  829. height: 48rpx;
  830. margin-bottom: 4rpx;
  831. }
  832. .bar-text {
  833. font-size: 20rpx;
  834. color: #1f1f1f;
  835. font-family: "PingFang SC";
  836. }
  837. }
  838. }
  839. .buy-btn {
  840. width: 588rpx;
  841. height: 88rpx;
  842. background: #1f1f1f;
  843. color: #ACF934;
  844. font-size: 32rpx;
  845. border-radius: 80rpx;
  846. border: none;
  847. font-weight: bold;
  848. text-align: center;
  849. line-height: 80rpx;
  850. margin-left: 24rpx;
  851. }
  852. }
  853. }
  854. .back-top {
  855. position: fixed;
  856. bottom: calc(126rpx + var(--window-bottom));
  857. right: 16rpx;
  858. width: 82rpx;
  859. height: 82rpx;
  860. }
  861. .initiator-bar {
  862. display: flex;
  863. align-items: center;
  864. justify-content: space-between;
  865. background: #fff;
  866. border-radius: 10rpx;
  867. padding: 18rpx 24rpx 18rpx 18rpx;
  868. margin: 0;
  869. .initiator-avatar {
  870. width: 64rpx;
  871. height: 64rpx;
  872. border-radius: 50%;
  873. margin-right: 18rpx;
  874. flex-shrink: 0;
  875. }
  876. .initiator-info {
  877. display: flex;
  878. align-items: center;
  879. flex: 1;
  880. min-width: 0;
  881. }
  882. .initiator-name {
  883. font-size: 30rpx;
  884. color: #222;
  885. font-weight: bold;
  886. margin-right: 12rpx;
  887. max-width: 260rpx;
  888. overflow: hidden;
  889. text-overflow: ellipsis;
  890. white-space: nowrap;
  891. }
  892. .initiator-tag {
  893. background: #1a1a1a;
  894. color: #b6ff4b;
  895. font-size: 20rpx;
  896. border-radius: 8rpx;
  897. padding: 2rpx 12rpx;
  898. margin-left: 2rpx;
  899. display: inline-flex;
  900. align-items: center;
  901. image {
  902. width: 28rpx;
  903. height: 28rpx;
  904. }
  905. }
  906. .initiator-service-btn {
  907. display: flex;
  908. align-items: center;
  909. background: #1a1a1a;
  910. color: #b6ff4b;
  911. font-size: 28rpx;
  912. border-radius: 128rpx;
  913. padding: 0 24rpx 0 12rpx;
  914. height: 56rpx;
  915. margin-left: 18rpx;
  916. font-weight: bold;
  917. }
  918. .service-icon {
  919. width: 32rpx;
  920. height: 32rpx;
  921. margin-right: 8rpx;
  922. }
  923. }
  924. .scale-tap {
  925. transition: transform 0.15s;
  926. }
  927. .scale-tap:active {
  928. transform: scale(0.92);
  929. }
  930. .risk-section {
  931. background: #fff;
  932. border-radius: 12rpx;
  933. margin: 24rpx 0 0 0;
  934. padding: 0 0 18rpx 0;
  935. position: relative;
  936. overflow: hidden;
  937. .risk-row {
  938. display: flex;
  939. align-items: center;
  940. justify-content: space-between;
  941. padding: 18rpx 24rpx 0 0rpx;
  942. font-size: 28rpx;
  943. color: #1f1f1f;
  944. background: #fff;
  945. &.risk-row-border {
  946. border-top: 1rpx solid #f2f2f2;
  947. margin-top: 18rpx;
  948. padding-top: 18rpx;
  949. }
  950. }
  951. .risk-title {
  952. font-size: 28rpx;
  953. color: #1f1f1f;
  954. font-family: 'PingFang SC-Bold';
  955. font-weight: 400;
  956. }
  957. .risk-more {
  958. color: #1f1f1f;
  959. font-size: 24rpx;
  960. display: flex;
  961. align-items: center;
  962. font-weight: 400;
  963. font-family: 'PingFang SC-Bold';
  964. .risk-more-icon {
  965. width: 24rpx;
  966. height: 24rpx;
  967. margin-left: 4rpx;
  968. margin-top: 4rpx;
  969. }
  970. }
  971. .risk-desc {
  972. font-size: 24rpx;
  973. color: #999;
  974. padding: 8rpx 24rpx 0 0;
  975. font-family: 'PingFang SC-Regular';
  976. }
  977. .risk-content {
  978. font-size: 24rpx;
  979. color: #999;
  980. padding: 12rpx 24rpx 0 0;
  981. font-family: 'PingFang SC-Regular';
  982. line-height: 1.7;
  983. >view {
  984. margin-bottom: 6rpx;
  985. }
  986. }
  987. }
  988. </style>