list.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. <template>
  2. <app-layout>
  3. <view class="top">
  4. <view class="dir-left-nowrap box">
  5. <input type="text" class="box-grow-1 input" placeholder="请输入内容搜索" confirm-type="搜索"
  6. @confirm="searchList"
  7. v-model="keyword">
  8. <view class="close-tip" @click="clear">
  9. <image class="search-close" v-if="keyword" src="/static/image/icon/delete-yuan.png"></image>
  10. </view>
  11. <view class="box-grow-0 cross-center" @click="searchList">搜索</view>
  12. </view>
  13. </view>
  14. <view class="hot" v-show="isSearch">
  15. <!-- 历史记录 -->
  16. <view class="history">
  17. <view class="dir-left-nowrap cross-center title">
  18. <view class="box-grow-1">历史搜索</view>
  19. <image src="/static/image/icon/delete.png" class="box-grow-0"
  20. @click="deleteHistory"></image>
  21. </view>
  22. <view class="dir-left-wrap list">
  23. <view class="dir-left-wrap">
  24. <view v-for="(line, index) in historyList" :key="index"
  25. class="dir-left-wrap box-grow-0">
  26. <view class="box-grow-0 cross-center item"
  27. @click="historyClick(line.keyword)">
  28. <view class="t-omit" style="max-width: 650rpx">{{ line.keyword }}</view>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. <template v-if="!isSearch">
  36. <scroll-view class="auto-tab" scroll-x
  37. :scroll-into-view="'type' + (tabCurrentIndex >= 2 ? tabCurrentIndex - 2 : 0)">
  38. <view class="auto-item" v-for="(item, index) in typeList" :key="index">
  39. <view class="auto-tab-item cross-center" :id="'type' + index"
  40. :key="index"
  41. :style="{'color': tabCurrentIndex == index ? getTheme.color: ''}"
  42. :class="tabCurrentIndex == index ? 'current-type' : ''"
  43. @click="tabClick(index)">{{ item.name }}
  44. </view>
  45. </view>
  46. </scroll-view>
  47. <view class="empty"></view>
  48. <view style="margin-top: 100rpx">
  49. <app-special-topic-list :cat-show="false" :topic-list="list"></app-special-topic-list>
  50. </view>
  51. </template>
  52. </app-layout>
  53. </template>
  54. <script>
  55. import {mapGetters, mapState} from "vuex";
  56. import appSpecialTopicList from "../../components/page-component/app-special-topic/app-special-topic-list.vue";
  57. let page = 1;
  58. let search = {};
  59. let is_no_more = false;
  60. let is_loading = false;
  61. export default {
  62. name: "list",
  63. components: {
  64. appSpecialTopicList,
  65. },
  66. data() {
  67. return {
  68. list: [],
  69. typeList: [],
  70. tabCurrentIndex: 0,
  71. KEY: '_TOPIC_SEARCH_DATA',
  72. historyList: [],
  73. keyword: '',
  74. isSearch: false,
  75. };
  76. },
  77. computed: {
  78. ...mapState({
  79. bar_title: state => state.mallConfig.bar_title,
  80. }),
  81. ...mapGetters('mallConfig', {
  82. getTheme: 'getTheme',
  83. }),
  84. },
  85. watch: {
  86. keyword: {
  87. handler(n, o) {
  88. if (n !== o) {
  89. this.isSearch = true;
  90. }
  91. },
  92. immediate: true,
  93. }
  94. },
  95. onLoad(options) { this.$commonLoad.onload(options);
  96. page = 1;
  97. is_no_more = false;
  98. is_loading = false;
  99. if (typeof options.type != 'undefined') {
  100. search.type = options.type;
  101. }
  102. this.loadData();
  103. this.loadType();
  104. },
  105. onReachBottom() {
  106. if (is_no_more || this.isSearch) {
  107. return;
  108. }
  109. this.loadData();
  110. },
  111. // #ifdef MP
  112. onShareAppMessage() {
  113. let route = this.$platDiff.route();
  114. let title = '专题列表';
  115. for (let i in this.bar_title) {
  116. if (this.bar_title[i].value == route) {
  117. title = this.bar_title[i].new_name;
  118. break;
  119. }
  120. }
  121. return this.$shareAppMessage({
  122. title: title,
  123. path: '/pages/topic/list',
  124. });
  125. },
  126. // #endif
  127. methods: {
  128. historyClick(keyword) {
  129. this.keyword = keyword.trim();
  130. this.searchList();
  131. },
  132. setHistory() {
  133. let historyList = this.getHistory();
  134. let keyword = this.keyword.trim();
  135. if (!keyword) {
  136. return;
  137. }
  138. historyList.forEach((item, index) => {
  139. if (item.keyword === keyword) historyList.splice(index, 1);
  140. });
  141. historyList.unshift({
  142. keyword: keyword,
  143. });
  144. if (historyList.length > 20) historyList.pop();
  145. this.historyList = historyList;
  146. this.$storage.setStorageSync(this.KEY, historyList);
  147. },
  148. getHistory() {
  149. let historyList = this.$storage.getStorageSync(this.KEY);
  150. if (!historyList) historyList = [];
  151. return historyList;
  152. },
  153. deleteHistory() {
  154. let self = this;
  155. uni.showModal({
  156. content: '确认删除全部历史记录?',
  157. success: function (res) {
  158. if (res.confirm) {
  159. self.$storage.removeStorageSync(self.KEY);
  160. self.historyList = [];
  161. }
  162. }
  163. });
  164. },
  165. clear() {
  166. uni.hideKeyboard()
  167. this.keyword = '';
  168. },
  169. searchList() {
  170. page = 1;
  171. this.keyword = this.keyword.trim();
  172. this.loadData();
  173. },
  174. loadData() {
  175. if (is_loading) {
  176. return;
  177. }
  178. this.$showLoading();
  179. is_loading = true;
  180. search.page = page;
  181. this.setHistory();
  182. this.$request({
  183. url: this.$api.topic.list,
  184. data: Object.assign({}, {keyword: this.keyword}, search)
  185. }).then(response => {
  186. is_loading = false;
  187. this.isSearch = false;
  188. this.historyList = this.getHistory();
  189. this.$hideLoading();
  190. if (response.code === 0) {
  191. if (page === 1) {
  192. this.list = [];
  193. }
  194. if (response.data.list.length > 0) {
  195. this.list = this.list.concat(response.data.list);
  196. page++;
  197. } else {
  198. is_no_more = true;
  199. }
  200. } else {
  201. }
  202. }).catch(e => {
  203. this.$hideLoading();
  204. is_loading = false;
  205. });
  206. },
  207. loadType() {
  208. this.$request({
  209. url: this.$api.topic.type,
  210. }).then(response => {
  211. if (response.code === 0) {
  212. if (response.data.list.length > 0) {
  213. let list = [
  214. {
  215. id: 0,
  216. name: '全部'
  217. },
  218. {
  219. id: -1,
  220. name: '精选'
  221. }
  222. ];
  223. this.typeList = list.concat(response.data.list);
  224. for (let i in this.typeList) {
  225. if (this.typeList[i].id == search.type) {
  226. this.tabCurrentIndex = i;
  227. break;
  228. }
  229. }
  230. }
  231. } else {
  232. }
  233. }).catch(e => {
  234. is_loading = false;
  235. });
  236. },
  237. tabClick(index) {
  238. page = 1;
  239. is_no_more = false;
  240. let type = this.typeList[index].id;
  241. this.tabCurrentIndex = index;
  242. search = {
  243. page: page,
  244. type: type
  245. };
  246. this.loadData();
  247. }
  248. }
  249. }
  250. </script>
  251. <style scoped lang="scss">
  252. .auto-tab {
  253. position: fixed;
  254. top: 100#{rpx};
  255. left: 0;
  256. background-color: #ffffff;
  257. z-index: 1500;
  258. height: #{88rpx};
  259. width: 100%;
  260. white-space: nowrap;
  261. padding: 0 #{32rpx};
  262. border-bottom: #{1rpx} solid #e2e2e2;
  263. box-shadow: 0 1px 5px rgba(0, 0, 0, 0.06);
  264. }
  265. .auto-item {
  266. display: inline-block;
  267. height: 84upx;
  268. }
  269. .auto-tab-item {
  270. margin-right: #{60rpx};
  271. background-color: #ffffff;
  272. height: 100%;
  273. }
  274. .auto-tab-item.current-type {
  275. border-bottom: #{4rpx} solid;
  276. }
  277. .empty {
  278. height: #{88+16rpx};
  279. width: 100%;
  280. background-color: #f7f7f7;
  281. }
  282. .top {
  283. position: fixed;
  284. width: 100%;
  285. top: 0;
  286. z-index: 15;
  287. padding: #{20rpx} #{24rpx};
  288. background-color: #efeff4;
  289. font-size: $uni-font-size-import-two;
  290. color: $uni-general-color-one;
  291. .input {
  292. background-color: #ffffff;
  293. border-radius: #{50rpx 0 0 50rpx};
  294. padding: 0 #{32rpx};
  295. font-size: $uni-font-size-general-one;
  296. height: #{64rpx};
  297. }
  298. .box {
  299. position: relative;
  300. .close-tip {
  301. width: #{64rpx};
  302. height: #{64rpx};
  303. background-color: #ffffff;
  304. border-radius: #{0 50rpx 50rpx 0};
  305. margin-right: #{20rpx};
  306. }
  307. .search-close {
  308. width: #{32rpx};
  309. height: #{32rpx};
  310. border-radius: 50%;
  311. margin: #{16rpx};
  312. }
  313. }
  314. }
  315. .history {
  316. padding: #{36rpx} #{24rpx};
  317. border-radius: #{16rpx} #{16rpx} 0 0;
  318. background-color: #ffffff;
  319. margin-top: #{110rpx};
  320. min-height: calc(100vh - #{110rpx});
  321. font-size: $uni-font-size-general-one;
  322. .title {
  323. padding-bottom: #{24rpx};
  324. color: $uni-general-color-one;
  325. image {
  326. width: #{28rpx};
  327. height: #{34rpx};
  328. display: block;
  329. }
  330. }
  331. .list {
  332. .item {
  333. height: #{64rpx};
  334. background-color: #f7f7f7;
  335. padding: 0 #{20rpx};
  336. margin-right: #{20rpx};
  337. margin-bottom: #{16rpx};
  338. border-radius: #{32rpx};
  339. }
  340. }
  341. }
  342. </style>