list.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <div
  3. :class="mobile ? 'mobileMain' : ''"
  4. :style="{marginTop: mainMarginTop, marginBottom: mobile ? '0px' : '30px !important'}">
  5. <div class="learn-wrapper" v-if="!mobile">
  6. <div class="learn-top">
  7. <div class="tabs">
  8. <a href="/skill/" class="tabs-item">技能服务</a>
  9. <a href="/consult/" class="tabs-item">咨询服务</a>
  10. <div class="tabs-item active">客栈学院</div>
  11. <!-- <el-button class="add-btn" @click="handleClickAdd">发布课程</el-button> -->
  12. </div>
  13. <div class="learn-category-wrapper">
  14. <!-- <div class="category-title">技术分类</div> -->
  15. <!-- 一级分类内容 -->
  16. <div
  17. class="category-one-wrapper"
  18. :class="categoryExpanded ? 'expand' : ''">
  19. <!-- 更多 -->
  20. <!-- <div
  21. class="category-more"
  22. @click="handleClickExpandCategory">{{ categoryExpanded ? '收起' : '更多' }}</div> -->
  23. <!-- 全部 -->
  24. <a
  25. href="/learn/"
  26. class="category-one-item"
  27. :class="pagination.selectedCateIdOne == '' ? 'active' : ''">全部</a>
  28. <!-- 一级分类 -->
  29. <a
  30. v-for="categoryOne in learnCate"
  31. :key="categoryOne.value"
  32. class="category-one-item"
  33. :class="pagination.selectedCateIdOne == categoryOne.value ? 'active' : ''"
  34. :href="`/learn/${categoryOne.value}/`">{{ categoryOne.label }}</a>
  35. </div>
  36. <!-- 二级分类内容 -->
  37. <div class="category-two-wrapper">
  38. <div
  39. class="category-two-content"
  40. v-for="categoryOne in learnCate"
  41. :key="`cate-two-parnet${categoryOne.value}`"
  42. v-show="pagination.selectedCateIdOne == categoryOne.value">
  43. <a
  44. class="category-two-item"
  45. :class="pagination.selectedCateIdTwo == categoryTwo.value ? 'active' : ''"
  46. :href="`/learn/${categoryTwo.value}/`"
  47. v-for="categoryTwo in categoryOne.children"
  48. :key="`cate-two-${categoryTwo.value}`">{{ categoryTwo.label }}</a>
  49. </div>
  50. </div>
  51. </div>
  52. </div>
  53. <div class="learn-content">
  54. <div class="learn-list-wrapper" v-if="learnList.length">
  55. <div
  56. class="learn-item"
  57. v-for="item in learnList"
  58. :key="item.sale_id">
  59. <a :href="`/s/${item.sale_id}`">
  60. <img class="cover" :src="item.coverImage" alt="learnCover,cover">
  61. </a>
  62. <a class="owner-wrapper" :href="`/wo/${item.user.uid}/learn`">
  63. <img class="avatar" :src="item.user.icon_url" alt="avatar">
  64. <div class="nickname">{{ item.user.nickname }}</div>
  65. </a>
  66. <a class="title" :href="`/s/${item.sale_id}`">{{ item.title }}</a>
  67. <div class="price-wrapper">
  68. <div class="price-text">¥{{ item.price }}</div>
  69. <div v-if="item.buy_num>0" class="buy-num">{{ item.buy_num }}人已学习</div>
  70. </div>
  71. </div>
  72. </div>
  73. <div class="result-empty-wrapper" v-else>
  74. <img src="@/assets/img/common/empty@2x.png" alt="empty">
  75. <span>暂无搜索内容</span>
  76. </div>
  77. <div class="pagination-wrapper" v-if="pagination.total > pagination.pagesize">
  78. <el-pagination
  79. background
  80. layout="prev, pager, next"
  81. :current-page="pagination.page"
  82. :total="pagination.total"
  83. :page-size="pagination.pagesize"
  84. @current-change="handlePageChange">
  85. </el-pagination>
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. </template>
  91. <script>
  92. import {mapState} from "vuex"
  93. import DealSeoList from "@/components/learn/dealSeoList"
  94. import qs from "qs"
  95. export default {
  96. name: 'SeoLearnList',
  97. data () {
  98. return {
  99. baseUrl: '',
  100. // firstLoad: true,
  101. isWeixinApp: true,
  102. categoryExpanded: true, // 更多按钮不要,默认为展开状态
  103. showCategoryDrawer: false,
  104. currentDrawerCategoryId: 0,
  105. currentDrawerCategoryIndex: 0
  106. }
  107. },
  108. head() {
  109. const {
  110. title = "",
  111. keyword = "",
  112. description = "",
  113. h1 = "",
  114. canonical = "",
  115. metaLocation
  116. } = this.head || {}
  117. let obj = {
  118. title: title,
  119. meta: [{
  120. name: "keywords",
  121. content: keyword
  122. }, {
  123. name: "description",
  124. content: description
  125. }, {
  126. name: "h1",
  127. content: h1
  128. }],
  129. link: [{rel: "canonical", href: canonical}]
  130. }
  131. if (metaLocation) {
  132. obj.meta.push({name: "location", content: metaLocation})
  133. }
  134. return obj
  135. },
  136. computed: {
  137. ...mapState(["deviceType"]),
  138. showWxHeader () {
  139. return !this.deviceType.app && !this.isWeixinApp &&
  140. (this.deviceType.android || this.deviceType.ios)
  141. },
  142. mainMarginTop () {
  143. if (this.mobile && this.showWxHeader) {
  144. return '64px !important'
  145. } else if (this.mobile) {
  146. return '0px !important'
  147. } else {
  148. return '20px !important'
  149. }
  150. }
  151. },
  152. async asyncData ({...params}) {
  153. let dealDataObj = new DealSeoList(params)
  154. let ans = await dealDataObj.dealData()
  155. return {
  156. ...ans
  157. }
  158. },
  159. mounted () {
  160. this.baseUrl = this.$store.state.domainConfig.siteUrl
  161. this.isWeixinApp = navigator.userAgent.indexOf("miniProgram") > -1
  162. },
  163. methods: {
  164. /** 分页获取技能列表数据 */
  165. _getLearnList () {
  166. const self = this
  167. const data = {
  168. type: 1,
  169. page: this.pagination.page,
  170. page_size: this.pagination.pagesize,
  171. cate_id: this.pagination.selectedCateIdTwo,
  172. status: 2,
  173. owner_type: 1,
  174. root_type: this.root_type
  175. }
  176. this.pagination.loading = true
  177. this.pagination.noMore = false
  178. this.$axios.$post('/api/sale/saleList', data).then(res => {
  179. if (Number(res.status) === 1) {
  180. let learnList = res.data.list || []
  181. learnList.forEach((item) => {
  182. let imageList = item.image.split(',')
  183. item.coverImage = imageList[0] || ''
  184. imageList.splice(0, 1)
  185. item.imageList = imageList
  186. })
  187. if (self.mobile) {
  188. self.learnList = self.learnList.concat(learnList)
  189. } else {
  190. self.learnList = learnList
  191. }
  192. self.pagination.total = res.data.total
  193. self.pagination.pagesize = res.data.page_size || 9
  194. if (self.pagination.page * self.pagination.pagesize >= self.pagination.total) {
  195. console.log('noMore true', self.pagination)
  196. self.pagination.noMore = true
  197. } else {
  198. console.log('noMore false', self.pagination)
  199. self.pagination.noMore = false
  200. }
  201. }
  202. }).then(() => {
  203. self.pagination.loading = false
  204. })
  205. },
  206. /** 点击展开、收起 */
  207. handleClickExpandCategory () {
  208. this.categoryExpanded = !this.categoryExpanded
  209. },
  210. /** 点击一级分类时 */
  211. handleClickCategoryOne (id) {
  212. if (id === 0) {
  213. // 点击全部时,移除筛选分类
  214. this.pagination.selectedCateIdOne = id
  215. this.pagination.selectedCateIdTwo = ''
  216. this.currentDrawerCategoryId = ''
  217. this.pagination.page = 1
  218. this.learnList = []
  219. window.scroll(0, 0)
  220. this._getLearnList()
  221. return
  222. }
  223. if (this.pagination.selectedCateIdOne !== id) {
  224. this.pagination.selectedCateIdOne = id
  225. }
  226. },
  227. /** 点击二级分类时:移动端 */
  228. handleClickCategoryTwo (id) {
  229. if (this.pagination.selectedCateIdTwo === id) {
  230. this.pagination.selectedCateIdTwo = ''
  231. this.currentDrawerCategoryId = ''
  232. } else {
  233. this.pagination.selectedCateIdTwo = id
  234. this.currentDrawerCategoryId = id
  235. }
  236. this.pagination.page = 1
  237. this.learnList = []
  238. window.scroll(0, 0)
  239. this._getLearnList()
  240. },
  241. /** 分页页码改变时 */
  242. handlePageChange (val) {
  243. let query = {
  244. page: val
  245. }
  246. if (this.root_type && Number(this.root_type) > 0) {
  247. query.root_type = this.root_type
  248. }
  249. window.location.href = `${window.location.origin}${window.location.pathname}?${qs.stringify(query)}`
  250. },
  251. /** mobile 加载更多 */
  252. handleLoadMoreSkill () {
  253. if (this.pagination.loading) {
  254. return
  255. }
  256. this.pagination.page++
  257. this._getLearnList()
  258. },
  259. /** 点击筛选时 */
  260. handleShowCategoryDrawer () {
  261. this.showCategoryDrawer = true
  262. },
  263. /**
  264. * 点击 mobile 分类 drawer 一级分类
  265. */
  266. handleClickDrawerCategoryOne (id) {
  267. if (id === 0) {
  268. this.showCategoryDrawer = false
  269. return
  270. }
  271. if (id !== this.currentDrawerCategoryIndex) {
  272. this.currentDrawerCategoryIndex = id
  273. }
  274. },
  275. /**
  276. * 点击 mobile 分类 drawer 二级分类
  277. */
  278. handleClickDrawerCategoryTwo (id) {
  279. if (this.currentDrawerCategoryId === id) {
  280. this.pagination.selectedCateIdTwo = ''
  281. } else {
  282. this.pagination.selectedCateIdTwo = id
  283. }
  284. this.currentDrawerCategoryId = id
  285. this.showCategoryDrawer = false
  286. this.pagination.page = 1
  287. this.learnList = []
  288. window.scroll(0, 0)
  289. this._getLearnList()
  290. },
  291. /**
  292. * 点击 mobile 的一项技能时
  293. */
  294. handleClickSkillItem (saleId) {
  295. if (this.deviceType.android || this.deviceType.ios) {
  296. // 端跳转
  297. let jumpUrl = `${this.baseUrl}/s/${saleId}`
  298. location.href = `proginn://webview?url=${jumpUrl}`
  299. } else {
  300. // web 跳转
  301. location.href = `/s/${saleId}`
  302. }
  303. },
  304. /**
  305. * 点击成为讲师
  306. */
  307. handleClickAdd () {
  308. location.href = '/workbench/skill/index'
  309. }
  310. }
  311. }
  312. </script>
  313. <style lang="scss" scoped>
  314. @import "@/assets/css/learn/list.scss";
  315. </style>
  316. <style lang="scss">
  317. .category-drawer {
  318. .el-drawer {
  319. height: 100vh !important;
  320. .el-drawer__body {
  321. position: relative;
  322. width: 100%;
  323. display: flex;
  324. }
  325. }
  326. .drawer-category-one {
  327. width: 100px;
  328. height: 100vh;
  329. padding-bottom: 34px;
  330. background: #f4f5f9;
  331. overflow-x: hidden;
  332. overflow-y: auto;
  333. -webkit-overflow-scrolling: touch;
  334. &::-webkit-scrollbar {
  335. display: none;
  336. }
  337. .drawer-category-one-item {
  338. width: 100%;
  339. height: 50px;
  340. line-height: 50px;
  341. text-align: center;
  342. font-size: 15px;
  343. font-family: PingFangSC, PingFangSC-Medium;
  344. font-weight: 500;
  345. color: #222222;
  346. background: inherit;
  347. &.active {
  348. color: #308eff;
  349. background: #ffffff;
  350. }
  351. }
  352. }
  353. .drawer-category-two {
  354. width: calc(100% - 100px);
  355. height: 100vh;
  356. padding: 4px 10px 34px;
  357. background: #ffffff;
  358. overflow-x: hidden;
  359. overflow-y: auto;
  360. -webkit-overflow-scrolling: touch;
  361. &::-webkit-scrollbar {
  362. display: none;
  363. }
  364. .drawer-category-two-wrapper {
  365. width: 100%;
  366. display: flex;
  367. flex-wrap: wrap;
  368. .drawer-category-two-item {
  369. margin: 8px 8px 0 0;
  370. padding: 0 12px;
  371. height: 35px;
  372. line-height: 35px;
  373. background: rgba(244,245,249,.8);
  374. border-radius: 4px;
  375. // opacity: 0.8;
  376. font-size: 13px;
  377. font-family: PingFangSC, PingFangSC-Regular;
  378. font-weight: 400;
  379. color: #222222;
  380. &.active {
  381. height: 33px;
  382. line-height: 33px;
  383. border: 1px solid #308eff;
  384. background: #ffffff;
  385. font-size: 12px;
  386. font-family: PingFangSC, PingFangSC-Medium;
  387. font-weight: 500;
  388. color: #308eff;
  389. }
  390. }
  391. }
  392. }
  393. }
  394. .wx-header-custom-list {
  395. position: fixed !important;
  396. z-index: 11 !important;
  397. }
  398. </style>