crowdfundingDetailsDesign.vue 27 KB

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