list.vue 12 KB

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