List.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. <template>
  2. <div class="ExhibitionsList">
  3. <div class="conten">
  4. <div class="search" data-aria-interaction-area tabindex="0"
  5. aria-label aria-description="You've reached search box under the Exhibitions page; please use the tab key to go through the content."
  6. >
  7. <div class="left">
  8. <div
  9. class="text-input-wrapper"
  10. @keydown.enter.passive="search"
  11. >
  12. <input
  13. type="text"
  14. autocomplete="off"
  15. v-model="txt"
  16. tabindex="0"
  17. :aria-description="txt || 'search'"
  18. />
  19. <img v-if="themeIdx === 0" :src="require('@/assets/images/search-default-color.svg')" alt=""
  20. @click="search"
  21. tabindex="0"
  22. aria-label="Link"
  23. aria-description="search"
  24. >
  25. <img v-if="[1, 3].includes(themeIdx)" :src="require('@/assets/images/search-black.svg')" alt=""
  26. @click="search"
  27. tabindex="0"
  28. aria-label="Link"
  29. aria-description="search"
  30. >
  31. <img v-if="[2, 4].includes(themeIdx)" :src="require('@/assets/images/search-yellow.svg')" alt=""
  32. @click="search"
  33. tabindex="0"
  34. aria-label="Link"
  35. aria-description="search"
  36. >
  37. </div>
  38. <!-- 使用el-select组件会无法在选择年份过程中得到选项的无障碍信息,所以改用原生元素 -->
  39. <select
  40. id="year-selector"
  41. v-model="year"
  42. @change="onSelectorChange"
  43. tabindex="0"
  44. class="yearSelector"
  45. aria-label="Select"
  46. aria-description="Select Year"
  47. >
  48. <option value="">Select Year</option>
  49. <option value="2024">2024</option>
  50. <option value="2021">2021</option>
  51. <option value="2020">2020</option>
  52. <option value="2019">2019</option>
  53. <option value="2018">2018</option>
  54. <option value="2017">2017</option>
  55. <option value="2016">2016</option>
  56. <option value="2015">2015</option>
  57. </select>
  58. </div>
  59. <div class="right">
  60. <img
  61. @click="cut = false"
  62. @keydown.enter.passive="cut = false"
  63. :src="
  64. require(`@/assets/images/Exhibitions/${
  65. cut ? 'cut1' : 'cut1Ac'
  66. }.png`)
  67. "
  68. alt="Button: List mode"
  69. tabindex="0"
  70. aria-label="Button"
  71. aria-description="List mode"
  72. />
  73. <img
  74. @click="cut = true"
  75. @keydown.enter.passive="cut = true"
  76. :src="
  77. require(`@/assets/images/Exhibitions/${
  78. cut ? 'cut2Ac' : 'cut2'
  79. }.png`)
  80. "
  81. alt="Button: Big image mode"
  82. tabindex="0"
  83. aria-label="Button"
  84. aria-description="Big image mode"
  85. />
  86. </div>
  87. </div>
  88. <div class="null" v-if="data.length === 0" tabindex="0">no information...</div>
  89. <!-- 列表详情信息 -->
  90. <div class="listAreaWrapper" data-aria-viewport-area tabindex="0"
  91. aria-label :aria-description="`You've reached the content area of the ${$parent.topLi[$route.params.id - 1].name} page. To browse the content, please use the tab key.`">
  92. <div class="list" v-if="!cut">
  93. <div
  94. class="row"
  95. v-for="item in dataShow"
  96. :key="item.id"
  97. @click="toInfo(item.id)"
  98. @keydown.enter.passive="toInfo(item.id)"
  99. >
  100. <img :src="item.cover" :alt="item.h3"
  101. tabindex="0"
  102. aria-label="Image link"
  103. :aria-description="item.h3"
  104. />
  105. <div class="txt">
  106. <h3 tabindex="0"
  107. aria-label="Link"
  108. >
  109. {{ item.h3 }}
  110. </h3>
  111. <p tabindex="0"
  112. aria-label="Link"
  113. >
  114. {{ item.p }}
  115. </p>
  116. <span v-if="item.yrahTxt" tabindex="0">{{ item.yrahTxt }}</span>
  117. </div>
  118. </div>
  119. </div>
  120. <!-- 列表图片信息 -->
  121. <div class="listImg" v-else>
  122. <div class="rowImg" v-for="item in dataShow" :key="item.id" @click="toInfo(item.id)">
  123. <img :src="item.cover" alt=""
  124. tabindex="0"
  125. aria-label="Image link"
  126. :aria-description="item.h3"
  127. />
  128. <p tabindex="0">{{ item.h3 }}</p>
  129. </div>
  130. </div>
  131. <!-- 点击显示更多 -->
  132. <div class="more" v-show="data.length>9&&dataShow.length<data.length" @click="dataShowArr(dataShow.length+9)">Show More</div>
  133. </div>
  134. </div>
  135. </div>
  136. </template>
  137. <script>
  138. import { dataAll } from "@/views/dataAll.js";
  139. import accessibilityMixin from "/src/views/accessibilityMixin.js"
  140. export default {
  141. name: "ExhibitionsList",
  142. components: {},
  143. mixins: [accessibilityMixin],
  144. data() {
  145. //这里存放数据
  146. return {
  147. txt: "",
  148. year: "",
  149. // 切换图像信息或文章信息---默认详情
  150. cut: false,
  151. topId: null,
  152. data: [],
  153. dataShow: [],
  154. };
  155. },
  156. //监听属性 类似于data概念
  157. computed: {},
  158. //监控data中的数据变化
  159. watch: {
  160. // 监听地址栏参数变化
  161. $route() {
  162. // 改变数据
  163. this.getIdChangeData();
  164. this.dataShowArr(9);
  165. // 把试图变成详情
  166. this.cut = false;
  167. // 清空输入框和下拉框
  168. this.txt = this.year = "";
  169. },
  170. },
  171. //方法集合
  172. methods: {
  173. // 点击单个文章跳转详情
  174. toInfo(id){
  175. let k = this.$route.params.id;
  176. this.$router.push({
  177. name:'ExhibitionsInfo',
  178. query:{id,k}
  179. })
  180. },
  181. // 选择年份
  182. onSelectorChange() {
  183. this.$eventBus.$emit('request-magnify', {
  184. elemType: 'Text',
  185. elemDisc: this.year,
  186. })
  187. if (!this.year) {
  188. this.getIdChangeData();
  189. this.dataShowArr(9);
  190. return;
  191. }
  192. this.getIdChangeData();
  193. this.txt = "";
  194. this.data = this.data.filter((v) => {
  195. return v.year.includes(this.year) || v.year === "";
  196. });
  197. this.dataShowArr(9);
  198. },
  199. elSelectChange(val) {
  200. if (!val) {
  201. this.getIdChangeData();
  202. this.dataShowArr(9);
  203. return;
  204. }
  205. this.getIdChangeData();
  206. this.txt = "";
  207. this.data = this.data.filter((v) => {
  208. return v.year.includes(val) || v.year === "";
  209. });
  210. this.dataShowArr(9);
  211. },
  212. // 点击搜索
  213. search() {
  214. if (this.txt.trim() === "" || this.txt.trim().length < 4) {
  215. this.getIdChangeData();
  216. this.dataShowArr(9);
  217. return;
  218. }
  219. this.data = this.data.filter((v) => {
  220. return v.h3.includes(this.txt) || v.p.includes(this.txt);
  221. });
  222. this.dataShowArr(9);
  223. },
  224. // 封装通过地址栏参数改变数据的方法
  225. getIdChangeData() {
  226. // 拿到路由参数id
  227. let temp = this.$route.params.id;
  228. if (temp === "1") this.data = dataAll.Exhibitions.Current;
  229. else if (temp === "2") this.data = dataAll.Exhibitions.Permanent;
  230. else if (temp === "3") this.data = dataAll.Exhibitions.Past;
  231. else if (temp === "4") this.data = dataAll.Exhibitions.Overseas;
  232. },
  233. // 处理显示在页面的数组初始数据为9
  234. dataShowArr(val) {
  235. let temp = [];
  236. this.data.forEach((v, i) => {
  237. if (i < val) temp.push(v);
  238. });
  239. this.dataShow = temp;
  240. },
  241. },
  242. //生命周期 - 创建完成(可以访问当前this实例)
  243. created() {},
  244. //生命周期 - 挂载完成(可以访问DOM元素)
  245. mounted() {
  246. this.getIdChangeData();
  247. this.dataShowArr(9);
  248. },
  249. beforeCreate() {}, //生命周期 - 创建之前
  250. beforeMount() {}, //生命周期 - 挂载之前
  251. beforeUpdate() {}, //生命周期 - 更新之前
  252. updated() {}, //生命周期 - 更新之后
  253. beforeDestroy() {}, //生命周期 - 销毁之前
  254. destroyed() {}, //生命周期 - 销毁完成
  255. activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
  256. };
  257. </script>
  258. <style lang='less' scoped>
  259. .ExhibitionsList {
  260. .conten {
  261. width: 1180px;
  262. margin: 0 auto;
  263. .search {
  264. display: flex;
  265. justify-content: space-between;
  266. align-items: center;
  267. .left {
  268. position: relative;
  269. display: flex;
  270. width: 820px;
  271. height: 48px;
  272. .text-input-wrapper {
  273. height: 48px;
  274. background: white;
  275. border: 1px solid #c7c7c7;
  276. display: flex;
  277. align-items: center;
  278. margin-right: 30px;
  279. > input {
  280. height: 100%;
  281. font-size: 24px;
  282. border: none;
  283. padding: 0px 10px;
  284. width: 500px;
  285. box-sizing: border-box;
  286. border: none;
  287. margin: 0;
  288. outline: none;
  289. }
  290. > img {
  291. height: 30px;
  292. width: 30px;
  293. margin-left: 10px;
  294. margin-right: 10px;
  295. cursor: pointer;
  296. }
  297. }
  298. .yearSelector {
  299. border-color: #c0c4cc;
  300. width: 180px;
  301. padding-left: 10px;
  302. cursor: pointer;
  303. font-size: 18px;
  304. option {
  305. cursor: pointer;
  306. color: #606266;
  307. font-size: 18px;
  308. }
  309. }
  310. }
  311. .right {
  312. & > img {
  313. cursor: pointer;
  314. width: 48px;
  315. height: 48px;
  316. }
  317. }
  318. }
  319. .null {
  320. font-size: 30px;
  321. margin-top: 50px;
  322. text-align: center;
  323. }
  324. .list {
  325. margin: 20px 0 40px;
  326. .row {
  327. cursor: pointer;
  328. display: flex;
  329. height: 240px;
  330. background-color: #fff;
  331. & > img {
  332. width: 240px;
  333. height: 240px;
  334. object-fit: cover;
  335. }
  336. .txt {
  337. flex: 1;
  338. border: 1px solid #c7c7c7;
  339. border-left: 0;
  340. padding: 0 25px;
  341. position: relative;
  342. & > h3 {
  343. font-size: 18px;
  344. line-height: 22px;
  345. padding: 16px 0;
  346. margin-bottom: 13px;
  347. font-weight: bold;
  348. }
  349. & > p {
  350. font-size: 14px;
  351. line-height: 20px;
  352. color: #666;
  353. }
  354. & > span {
  355. display: block;
  356. position: absolute;
  357. left: 25px;
  358. bottom: 15px;
  359. font-size: 14px;
  360. line-height: 20px;
  361. font-weight: bold;
  362. }
  363. }
  364. }
  365. }
  366. .listImg {
  367. margin: 20px 0 40px;
  368. display: flex;
  369. flex-wrap: wrap;
  370. .rowImg {
  371. overflow: hidden;
  372. position: relative;
  373. cursor: pointer;
  374. width: 393px;
  375. height: 393px;
  376. & > img {
  377. width: 393px;
  378. height: 393px;
  379. }
  380. & > p {
  381. font-weight: 700;
  382. width: 100%;
  383. font-size: 16px;
  384. line-height: 32px;
  385. color: #fff;
  386. overflow: hidden;
  387. transition: all 0.3s;
  388. position: absolute;
  389. left: 0;
  390. bottom: -300px;
  391. padding: 15px 25px;
  392. background-color: rgba(0, 0, 0, 0.8);
  393. }
  394. &:hover {
  395. & > p {
  396. bottom: 0;
  397. }
  398. }
  399. }
  400. }
  401. .more {
  402. height: 38px;
  403. width: 160px;
  404. margin: 0 auto 60px;
  405. border: 1px solid #000;
  406. font-size: 16px;
  407. line-height: 38px;
  408. text-align: center;
  409. font-weight: bold;
  410. cursor: pointer;
  411. }
  412. }
  413. }
  414. </style>