吉光研途前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
8.7 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. <template>
  2. <view class="page__view">
  3. <view class="bg"></view>
  4. <view class="main">
  5. <view class="header">
  6. <view class="title">
  7. {{ configList.config_name }}
  8. </view>
  9. <view class="desc">
  10. <view class="desc-line"></view>
  11. {{ configList.config_name_en }}
  12. </view>
  13. </view>
  14. <!-- 搜索栏 -->
  15. <view class="section search">
  16. <uv-search v-model="keyword" placeholder="输入关键词搜索" bgColor="#FBFBFB" @custom="search" @search="search">
  17. <template #prefix>
  18. <image class="search-icon" src="@/static/image/icon-search.png" mode="widthFix"></image>
  19. </template>
  20. </uv-search>
  21. </view>
  22. <!-- 轮播图 -->
  23. <view class="section swiper">
  24. <uv-swiper :list="bannerList" keyName="image" indicator indicatorMode="dot" indicatorActiveColor="#4883F9" indicatorInactiveColor="#FFFFFF" :height="swiperHeight"></uv-swiper>
  25. </view>
  26. <view class="section card" v-for="group in list" :key="group.id">
  27. <view class="card-header">
  28. <view class="card-header-title">{{ group.title }}</view>
  29. <view class="card-header-tag">JGYT</view>
  30. </view>
  31. <view class="card-content">
  32. <view class="card-item card-row" v-for="item in group.children" :key="item.id">
  33. <view class="flex info">
  34. <image class="info-icon" :src="item.image" mode="widthFix"></image>
  35. <view class="info-label">{{ item.title }}</view>
  36. </view>
  37. <button class="btn" @click="jumpToCategory(group.id, item.id, item.title, 'queryThesisList')">查看</button>
  38. </view>
  39. </view>
  40. </view>
  41. <view class="section card" v-for="group in list2" :key="group.id">
  42. <view class="card-header">
  43. <view class="card-header-title">{{ group.title }}</view>
  44. <view class="card-header-tag">JGYT</view>
  45. </view>
  46. <view class="card-content">
  47. <view class="card-box">
  48. <view class="card-item info" v-for="item in group.children" :key="item.id" @click="jumpToCategory(group.id, item.id, item.title, 'queryThesisTwoList')">
  49. <image class="info-icon" :src="item.image" mode="widthFix"></image>
  50. <view class="info-label">{{ item.title }}</view>
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. <tabber select="home" />
  57. </view>
  58. </template>
  59. <script>
  60. import tabber from '@/components/base/tabbar.vue'
  61. export default {
  62. components: {
  63. tabber,
  64. },
  65. data() {
  66. return {
  67. keyword: '',
  68. bannerList: [],
  69. list: [],
  70. list2: [],
  71. swiperHeight: '239rpx',
  72. }
  73. },
  74. onLoad() {
  75. const windowWidth = uni.getSystemInfoSync().windowWidth
  76. this.swiperHeight = `${(windowWidth - 18) * 239 / 714}px`
  77. this.fetchBanner()
  78. this.getData()
  79. },
  80. methods: {
  81. transformData(records) {
  82. let groups = []
  83. records.forEach(record => {
  84. if (record.hasChild == 1) {
  85. const { id, title, createTime } = record
  86. const index = groups.findIndex(group => group.id === id)
  87. if (index === -1) {
  88. groups.push({ id, title, createTime, children: [] })
  89. } else {
  90. groups[index].title = title
  91. groups[index].createTime = createTime
  92. }
  93. } else {
  94. const { pid, id, title, image, createTime } = record
  95. const index = groups.findIndex(group => group.id === pid)
  96. const item = { id, title, image, createTime }
  97. if (index === -1) {
  98. groups.push({ id: pid, children: [item] })
  99. } else {
  100. groups[index].children.push(item)
  101. }
  102. }
  103. })
  104. groups.forEach(group => {
  105. let { children } = group
  106. children.sort((a, b) => new Date(a.createTime).getTime() - new Date(b.createTime).getTime())
  107. group.children = children
  108. })
  109. groups.sort((a, b) => new Date(a.createTime).getTime() - new Date(b.createTime).getTime())
  110. return groups
  111. },
  112. async fetchCategoryThesisList() {
  113. try {
  114. let records = (await this.$fetch('queryCategoryThesisList', { pageNo: 1, pageSize: 1000 }))?.records
  115. this.list = this.transformData(records)
  116. } catch (err) {
  117. }
  118. },
  119. async fetchCategoryThesisTwoList() {
  120. try {
  121. let records = (await this.$fetch('queryCategoryThesisTwoList', { pageNo: 1, pageSize: 1000 }))?.records
  122. this.list2 = this.transformData(records)
  123. } catch (err) {
  124. }
  125. },
  126. getData() {
  127. this.fetchCategoryThesisList()
  128. this.fetchCategoryThesisTwoList()
  129. },
  130. search() {
  131. uni.navigateTo({
  132. url: '/pages_order/thesis/search?search=' + this.keyword
  133. })
  134. this.keyword = ''
  135. },
  136. // 获取轮播图
  137. async fetchBanner() {
  138. try {
  139. this.bannerList = (await this.$fetch('queryBannerList', { type: '0' }))?.records // type:0-首页 1-案例 2-服务 3-其他
  140. } catch (err) {
  141. }
  142. },
  143. jumpToCategory(categoryOne, categoryTwo, title, api) {
  144. uni.navigateTo({
  145. url: `/pages_order/thesis/search?categoryOne=${categoryOne}&categoryTwo=${categoryTwo}&title=${title}&api=${api}`
  146. })
  147. },
  148. },
  149. }
  150. </script>
  151. <style scoped lang="scss">
  152. .bg {
  153. width: 100%;
  154. // height: 438rpx;
  155. height: 488rpx;
  156. background-image: linear-gradient(#4883F9, #4883F9, #4883F9, #FCFDFF);
  157. }
  158. .main {
  159. position: absolute;
  160. top: 0;
  161. left: 0;
  162. width: 100%;
  163. // padding: 192rpx 0 182rpx 0;
  164. padding: 100rpx 0 182rpx 0;
  165. }
  166. .header {
  167. margin-left: 44rpx;
  168. .title {
  169. position: relative;
  170. letter-spacing: 6rpx;
  171. font-size: 46rpx;
  172. font-weight: 700;
  173. color: #FFFFFF;
  174. }
  175. .desc {
  176. position: relative;
  177. font-size: 30rpx;
  178. // font-weight: 700;
  179. color: #FFFFFF;
  180. margin: 4rpx 0 22rpx 0;
  181. display: inline-block;
  182. &-line {
  183. margin-bottom: 6rpx;
  184. width: 100%;
  185. height: 11rpx;
  186. background: linear-gradient(to right, #ffffff, #4883f9);
  187. }
  188. }
  189. }
  190. .section {
  191. margin: 0 18rpx 0 18rpx;
  192. }
  193. .search {
  194. width: calc(100% - 20rpx * 2);
  195. background-color: #FFFFFF;
  196. border-radius: 37rpx;
  197. padding: 13rpx 0 13rpx 18rpx;
  198. box-sizing: border-box;
  199. display: flex;
  200. align-items: center;
  201. /deep/ .uv-search__action {
  202. color: $uni-color;
  203. padding: 10rpx 18rpx;
  204. }
  205. &-icon {
  206. width: 26rpx;
  207. height: auto;
  208. }
  209. }
  210. .swiper {
  211. margin-top: 29rpx;
  212. margin-bottom: 26rpx;
  213. border-radius: 25rpx;
  214. overflow: hidden;
  215. /deep/ .uv-swiper-indicator__wrapper__dot {
  216. width: 15rpx;
  217. height: 15rpx;
  218. }
  219. /deep/ .uv-swiper-indicator__wrapper__dot--active {
  220. width: 15rpx;
  221. }
  222. }
  223. .card {
  224. margin-bottom: 35rpx;
  225. width: calc(100% - 20rpx * 2);
  226. box-sizing: border-box;
  227. padding-bottom: 45rpx;
  228. background-image: linear-gradient(164deg,#cfecfe 88rpx, #fcfdfe 176rpx);
  229. border: 3rpx solid #FFFFFF;
  230. border-radius: 25rpx;
  231. box-shadow: 0px 3rpx 6rpx 0rpx rgba(0,0,0,0.16);
  232. &-header {
  233. position: relative;
  234. width: 100%;
  235. box-sizing: border-box;
  236. padding: 46rpx 0 17rpx 33rpx;
  237. overflow: hidden;
  238. &-title {
  239. font-size: 42rpx;
  240. font-weight: 800;
  241. color: #000000;
  242. }
  243. &-tag {
  244. position: absolute;
  245. top: -40rpx;
  246. right: 12rpx;
  247. font-size: 156rpx;
  248. font-weight: 800;
  249. color: rgba(255,255,255,0.3);
  250. }
  251. }
  252. &-content {
  253. padding: 0 30rpx;
  254. box-sizing: border-box;
  255. }
  256. &-item {
  257. display: flex;
  258. align-items: center;
  259. justify-content: flex-start;
  260. column-gap: 50rpx;
  261. padding: 26rpx 28rpx;
  262. box-sizing: border-box;
  263. background: #f3f6fd;
  264. border-radius: 28rpx;
  265. box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0,0,0,0.16);
  266. }
  267. .info {
  268. &-icon {
  269. width: 80rpx;
  270. height: auto;
  271. }
  272. &-label {
  273. font-size: 32rpx;
  274. font-weight: 400;
  275. color: #000000;
  276. }
  277. }
  278. &-row {
  279. justify-content: space-between;
  280. padding: 15rpx 35rpx;
  281. & + & {
  282. margin-top: 33rpx;
  283. }
  284. .info {
  285. column-gap: 33rpx;
  286. }
  287. .btn {
  288. padding: 7rpx 30rpx;
  289. font-size: 28rpx;
  290. font-weight: 400;
  291. color: #4883F9;
  292. background: #FFFFFF;
  293. border-radius: 27rpx;
  294. }
  295. }
  296. &-box {
  297. display: grid;
  298. grid-template-columns: repeat(2, 1fr);
  299. column-gap: 34rpx;
  300. row-gap: 26rpx;
  301. .info {
  302. column-gap: 50rpx;
  303. }
  304. }
  305. }
  306. </style>