mobile.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. <template>
  2. <div class="collections">
  3. <div class="slebar">
  4. <div>分类:</div>
  5. <ul>
  6. <li
  7. @click="menuActive = item.id"
  8. :class="{ active: menuActive == item.id }"
  9. v-for="(item, i) in menu"
  10. :key="i"
  11. >
  12. {{ item.name }}
  13. </li>
  14. </ul>
  15. </div>
  16. <div class="masonrycon">
  17. <div
  18. v-if="list && list.length > 0"
  19. class="masonry"
  20. v-infinite-scroll="getData"
  21. infinite-scroll-disabled="busy"
  22. :infinite-scroll-immediate-check="true"
  23. infinite-scroll-distance="30"
  24. v-masonry="containerId"
  25. fit-width="true"
  26. gutter="10"
  27. initLayout="true"
  28. transition-duration="0.3s"
  29. item-selector=".item"
  30. >
  31. <div
  32. @click="onClickCollection(item)"
  33. v-masonry-tile
  34. class="item"
  35. :class="{ odd: index % 2 != 0 }"
  36. v-for="(item, index) in list"
  37. :key="index"
  38. >
  39. <div class="itemimg">
  40. <div :style="`background-image:url(${item.thumb})`"></div>
  41. </div>
  42. <p class="goodBotInfo">{{ item.name }}</p>
  43. </div>
  44. </div>
  45. <div class="searchNone" style="padding-top: 40%" v-else>
  46. <img src="@/assets/images/resource/searchNone.svg" alt="" />
  47. <p>暂时没有数据</p>
  48. </div>
  49. </div>
  50. </div>
  51. <teleport to="body">
  52. <div class="fnbar">
  53. <div class="barsub">
  54. <mb_select
  55. :noradius="true"
  56. class="mb_select"
  57. @handleOption="handleTab"
  58. :value="activeId"
  59. :options="yearlist"
  60. />
  61. </div>
  62. <div class="barsub">
  63. <mb_select
  64. :noradiusAll="true"
  65. class="mb_select"
  66. @handleOption="handleTab"
  67. :value="activeId"
  68. :options="yearlist"
  69. />
  70. </div>
  71. <div class="searchimg" v-show="!showInput">
  72. <img
  73. @click="showInput = true"
  74. :src="require('@/assets/images/icon/label_search.png')"
  75. alt=""
  76. />
  77. </div>
  78. <transition name="fade">
  79. <div class="searchcon" v-if="showInput">
  80. <img :src="require('@/assets/images/icon/label_search.png')" alt="" />
  81. <input v-model="inputKey" type="text" placeholder="请输入藏品名称" />
  82. <span @click="showInput = false">取消</span>
  83. </div>
  84. </transition>
  85. </div>
  86. </teleport>
  87. <teleport to="body">
  88. <div class="fnbar">
  89. <div class="barsub">
  90. <mb_select
  91. :noradius="true"
  92. class="mb_select"
  93. @handleOption="(data) => (currentMuseum = data.id)"
  94. :value="currentMuseum"
  95. :options="museumList"
  96. />
  97. </div>
  98. <div class="barsub">
  99. <mb_select
  100. :noradiusAll="true"
  101. class="mb_select"
  102. @handleOption="(data) => (currentAge = data.id)"
  103. :value="currentAge"
  104. :options="ages"
  105. />
  106. </div>
  107. <div class="barsub">
  108. <mb_select
  109. :noradiusAll="true"
  110. class="mb_select"
  111. @handleOption="(data) => (currentType = data.id)"
  112. :value="currentType"
  113. :options="types"
  114. />
  115. </div>
  116. <div class="searchimg" v-show="!showInput">
  117. <img
  118. @click="showInput = true"
  119. :src="require('@/assets/images/icon/label_search.png')"
  120. alt=""
  121. />
  122. </div>
  123. <transition name="fade">
  124. <div class="searchcon" v-if="showInput">
  125. <img :src="require('@/assets/images/icon/label_search.png')" alt="" />
  126. <input v-model="inputKey" type="text" placeholder="请输入展览名称" />
  127. <span @click="(showInput = false), (inputKey = '')">取消</span>
  128. </div>
  129. </transition>
  130. </div>
  131. </teleport>
  132. <transition name="fade">
  133. <teleport to="body">
  134. <showCollection v-if="activeCollection" :item="activeCollection" />
  135. </teleport>
  136. </transition>
  137. </template>
  138. <script>
  139. import {
  140. defineProps,
  141. getCurrentInstance,
  142. onMounted,
  143. watch,
  144. nextTick,
  145. ref,
  146. } from "vue";
  147. import mb_select from "@/components/mb_select";
  148. import {
  149. getCollectionList,
  150. getMuseumList,
  151. getAge,
  152. getType,
  153. getMuseumListOrInfoAPI,
  154. } from "@/config/api";
  155. import showCollection from "@/components/showCollection/index.vue";
  156. import emitter from "@/mitt/index";
  157. export default {
  158. setup(props) {
  159. const containerId = ref("vuemasonry");
  160. const inputKey = ref("");
  161. const currentAge = ref("");
  162. const currentType = ref("");
  163. const currentMuseum = ref("");
  164. const busy = ref(false);
  165. const ages = ref([]);
  166. const types = ref([]);
  167. const museumList = ref([]);
  168. const menu = ref([
  169. {
  170. id: "",
  171. name: "全部",
  172. },
  173. {
  174. id: "model",
  175. name: "三维模型",
  176. },
  177. {
  178. id: "img",
  179. name: "图片",
  180. },
  181. {
  182. id: "video",
  183. name: "视频",
  184. },
  185. {
  186. id: "audio",
  187. name: "音频",
  188. },
  189. ]);
  190. const menuActive = ref("");
  191. const getMuseumListOrInfoFu = async () => {
  192. let res = await getMuseumListOrInfoAPI("goods");
  193. museumList.value = res.data.map((item) => {
  194. return {
  195. ...item,
  196. label: item.name,
  197. value: item.id,
  198. };
  199. });
  200. if (!currentMuseum.value) {
  201. currentMuseum.value = museumList.value[0].value;
  202. }
  203. };
  204. onMounted(() => {
  205. getAge((data) => {
  206. ages.value = data.data.data.map((item) => {
  207. return {
  208. ...item,
  209. label: item.name,
  210. value: item.id,
  211. };
  212. });
  213. });
  214. getType((data) => {
  215. types.value = data.data.data.map((item) => {
  216. return {
  217. ...item,
  218. label: item.name,
  219. value: item.id,
  220. };
  221. });
  222. });
  223. getMuseumListOrInfoFu();
  224. // getMuseumList({
  225. // "cityId": '',
  226. // "pageNum": 1,
  227. // "pageSize": 1000,
  228. // }, data => {
  229. // museumList.value = data.data.records.map(item => {
  230. // return {
  231. // ...item,
  232. // label: item.name,
  233. // value: item.id
  234. // }
  235. // })
  236. // if (!currentMuseum.value) {
  237. // currentMuseum.value = museumList.value[0].value
  238. // }
  239. // })
  240. });
  241. return {
  242. ages,
  243. types,
  244. currentMuseum,
  245. museumList,
  246. menu,
  247. currentAge,
  248. menuActive,
  249. currentType,
  250. inputKey,
  251. busy,
  252. };
  253. },
  254. components: { showCollection, mb_select },
  255. data() {
  256. return {
  257. showInput: false,
  258. list: [],
  259. activeCollection: null,
  260. paging: {
  261. pageSize: 10,
  262. pageNum: 1,
  263. showSize: 4,
  264. current: 1,
  265. },
  266. };
  267. },
  268. watch: {
  269. inputKey() {
  270. this.getData(true);
  271. },
  272. currentAge() {
  273. this.getData(true);
  274. },
  275. currentMuseum() {
  276. this.getData(true);
  277. this.$emit(
  278. "updateMuseum",
  279. this.museumList.find((item) => item.id == this.currentMuseum)
  280. );
  281. },
  282. currentType() {
  283. this.getData(true);
  284. },
  285. menuActive() {
  286. this.getData(true);
  287. },
  288. },
  289. methods: {
  290. handleTab() {},
  291. getData(reset) {
  292. if (reset) {
  293. this.list = [];
  294. }
  295. this.busy = true;
  296. getCollectionList(
  297. {
  298. ageId: this.currentAge,
  299. museumId: this.currentMuseum,
  300. type: this.menuActive,
  301. pageNum: this.paging.pageNum,
  302. pageSize: this.paging.pageSize,
  303. searchKey: this.inputKey,
  304. textureId: this.currentType,
  305. },
  306. (data) => {
  307. this.busy = false;
  308. if (data.data.total <= this.list.length) {
  309. this.busy = true;
  310. return;
  311. }
  312. this.list = this.list.concat(data.data.records);
  313. this.paging.pageNum += 1;
  314. this.$nextTick(() => {
  315. this.$redrawVueMasonry(this.containerId);
  316. });
  317. }
  318. );
  319. // console.log(this);
  320. // this.list = this.list.concat([]);
  321. // // list.value = list.value.concat(list.value);
  322. // this.$nextTick(() => {
  323. // this.$redrawVueMasonry(this.containerId);
  324. // });
  325. },
  326. onClickCollection(data) {
  327. this.activeCollection = data;
  328. },
  329. },
  330. mounted() {
  331. emitter.on("closeCollection", () => {
  332. this.activeCollection = "";
  333. });
  334. },
  335. };
  336. </script>
  337. <style lang="scss" scoped>
  338. .collections {
  339. width: 100vw;
  340. padding-top: 10px;
  341. background: #e8e3d1;
  342. .slebar {
  343. display: flex;
  344. color: #333;
  345. align-items: center;
  346. width: 90vw;
  347. margin: 0 auto;
  348. font-size: 14px;
  349. padding-bottom: 20px;
  350. > ul {
  351. display: flex;
  352. align-items: center;
  353. > li {
  354. text-align: center;
  355. margin: 0 6px;
  356. cursor: pointer;
  357. white-space: nowrap;
  358. &.active {
  359. height: 30px;
  360. color: var(--main-color);
  361. line-height: 30px;
  362. border-radius: 60px;
  363. padding: 0 8px;
  364. border: 1px solid var(--main-color);
  365. }
  366. }
  367. }
  368. }
  369. .masonrycon {
  370. height: calc(100vh - 60px);
  371. overflow-y: auto;
  372. .masonry {
  373. width: 90vw;
  374. margin: 0 auto 16px;
  375. .item {
  376. width: calc(45vw - 5px);
  377. height: 200px;
  378. border-radius: 10px;
  379. margin-bottom: 10px;
  380. overflow: hidden;
  381. cursor: pointer;
  382. .itemimg {
  383. background: linear-gradient(180deg, #d9d9d9 0%, #b9b9b9 100%);
  384. font-size: 0;
  385. height: calc(100% - 40px);
  386. width: 100%;
  387. > div {
  388. height: 100%;
  389. width: 100%;
  390. background-repeat: no-repeat;
  391. background-size: cover;
  392. background-position: center;
  393. }
  394. }
  395. p {
  396. background: #fffef6;
  397. color: #999;
  398. height: 40px;
  399. line-height: 40px;
  400. padding: 0 10px;
  401. &.active {
  402. color: var(--main-color);
  403. }
  404. }
  405. }
  406. .odd {
  407. height: 310px;
  408. }
  409. }
  410. }
  411. }
  412. .fnbar {
  413. position: absolute;
  414. bottom: 20px;
  415. right: 5%;
  416. background: var(--main-color);
  417. z-index: 99;
  418. width: 90%;
  419. display: flex;
  420. align-items: center;
  421. border-radius: 50px;
  422. font-size: 0;
  423. .barsub {
  424. width: calc((100% - 5% - 16px) / 3);
  425. flex-shrink: 0;
  426. }
  427. .searchimg {
  428. position: absolute;
  429. right: 5%;
  430. > img {
  431. width: 16px;
  432. height: 16px;
  433. }
  434. }
  435. .searchcon {
  436. width: 100%;
  437. position: absolute;
  438. left: 0;
  439. top: 0;
  440. height: 100%;
  441. z-index: 999;
  442. background: var(--main-color);
  443. border-radius: 50px;
  444. display: flex;
  445. align-items: center;
  446. font-size: 14px;
  447. padding: 0 10px;
  448. justify-content: space-around;
  449. > img {
  450. width: 20px;
  451. height: 20px;
  452. }
  453. > input {
  454. width: 100%;
  455. height: 100%;
  456. padding-left: 16px;
  457. color: #fff;
  458. &::placeholder {
  459. color: #d2d2d2;
  460. }
  461. }
  462. > span {
  463. display: inline-block;
  464. color: var(--font-active);
  465. width: 30px;
  466. white-space: nowrap;
  467. }
  468. }
  469. }
  470. </style>