index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <template>
  2. <div id="index">
  3. <el-row>
  4. <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
  5. <el-col :span="24" class="innovation">
  6. <el-image class="image" :src="innovation" fit="fill" />
  7. </el-col>
  8. <div class="w_1200">
  9. <el-col :span="24" class="one">
  10. <el-row class="one_1">
  11. <el-col :span="12" class="oneLeft">
  12. <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
  13. <el-tab-pane label="全部比赛" name="first"></el-tab-pane>
  14. <el-tab-pane label="大奖赛" name="second"></el-tab-pane>
  15. <el-tab-pane label="经典赛" name="third"></el-tab-pane>
  16. <el-tab-pane label="训练赛" name="fourth"></el-tab-pane>
  17. </el-tabs>
  18. </el-col>
  19. <el-col :span="12" class="oneRight">
  20. <el-input v-model="input" placeholder="请输入赛题名称搜索..." class="input">
  21. <template #append>
  22. <el-button :icon="Search" />
  23. </template>
  24. </el-input>
  25. </el-col>
  26. </el-row>
  27. <el-row class="one_2" v-for="(val, indexs) in searchList" :key="indexs">
  28. <el-col :span="1" class="left">{{ val.title }}:</el-col>
  29. <el-col :span="23" class="right">
  30. <a-button
  31. class="title"
  32. v-for="(item, index) in val.list"
  33. :key="index"
  34. type="link"
  35. size="samll"
  36. >
  37. {{ item.label }}
  38. </a-button>
  39. </el-col>
  40. </el-row>
  41. </el-col>
  42. <el-col :span="24" class="two">
  43. <el-row
  44. :span="24"
  45. class="list"
  46. v-for="(item, index) in list"
  47. :key="index"
  48. @click="toView(item)"
  49. >
  50. <div class="join" :class="[item.match_status == '0' ? 'join0' : 'join1']">
  51. {{ getDict(item.match_status, 'status') }}
  52. </div>
  53. <el-col :span="4" class="left">
  54. <el-image
  55. v-if="item.file && item.file.length > 0"
  56. class="image"
  57. :src="item.file[0].url"
  58. fit="fill"
  59. />
  60. <el-image v-else class="image" :src="news" fit="fill" />
  61. </el-col>
  62. <el-col :span="20" class="right">
  63. <el-col :span="24" class="right_1">
  64. <span class="type">{{ getDict(item.form, 'form') }}</span>
  65. <span class="title">{{ item.name || '暂无比赛名称' }}</span>
  66. </el-col>
  67. <el-col :span="24" class="right_2">
  68. 组织单位:{{ item.organization || '暂无组织单位' }}
  69. </el-col>
  70. <el-col :span="24" class="right_3">
  71. <el-col :span="20" class="right_3Left">
  72. 比赛日期:{{ getTime(item.time) }}
  73. </el-col>
  74. <el-col :span="4" class="right_3Right">
  75. {{ item.money || '免费' }}
  76. </el-col>
  77. </el-col>
  78. <el-col :span="24" class="right_4">
  79. <el-tag type="primary">{{ getDict(item.type, 'type') }}</el-tag>
  80. </el-col>
  81. </el-col>
  82. </el-row>
  83. </el-col>
  84. <el-col :span="24" class="thr">
  85. <el-pagination
  86. background
  87. layout="total, prev, pager, next"
  88. :page-sizes="[10, 20, 50, 100, 200]"
  89. :total="total"
  90. :page-size="limit"
  91. v-model:current-page="currentPage"
  92. @current-change="changePage"
  93. @size-change="sizeChange"
  94. >
  95. </el-pagination>
  96. </el-col>
  97. </div>
  98. </el-col>
  99. </el-row>
  100. </div>
  101. </template>
  102. <script setup>
  103. const $checkRes = inject('$checkRes')
  104. import { Search } from '@element-plus/icons-vue'
  105. import { get } from 'lodash-es'
  106. // 接口
  107. import { DictDataStore } from '@/store/api/system/dictData'
  108. import { MatchStore } from '@/store/api/platform/match'
  109. const store = MatchStore()
  110. const dictDataStore = DictDataStore()
  111. // 图片引入
  112. import innovation from '@/assets/innovation.png'
  113. import news from '@/assets/news.png'
  114. // 路由
  115. const router = useRouter()
  116. // 加载中
  117. const loading = ref(false)
  118. const searchForm = ref({})
  119. const searchList = ref([
  120. {
  121. title: '状态',
  122. list: [
  123. { value: '0', label: '全部' },
  124. { value: '1', label: '可报名' },
  125. { value: '2', label: '已报名' },
  126. { value: '3', label: '不可报名' }
  127. ]
  128. },
  129. {
  130. title: '类别',
  131. list: [
  132. { value: '0', label: '全部' },
  133. { value: '1', label: '智能算法' },
  134. { value: '2', label: '方案应用' }
  135. ]
  136. },
  137. {
  138. title: '技术',
  139. list: [
  140. { value: '0', label: '数据挖掘' },
  141. { value: '1', label: '自然语言处理' },
  142. { value: '2', label: '计算机视觉' },
  143. { value: '3', label: 'AI其他' }
  144. ]
  145. }
  146. ])
  147. // 搜索
  148. const input = ref('')
  149. // 列表
  150. const list = ref([])
  151. let skip = 0
  152. let limit = inject('limit')
  153. const total = ref(20)
  154. const typeList = ref([])
  155. const formList = ref([])
  156. const statusList = ref([])
  157. // 请求
  158. onMounted(async () => {
  159. loading.value = true
  160. await searchOther()
  161. await search({ skip, limit })
  162. loading.value = false
  163. })
  164. const searchOther = async () => {
  165. let result
  166. // 类型
  167. result = await dictDataStore.query({ code: 'matchType', is_use: '0' })
  168. if ($checkRes(result)) typeList.value = result.data
  169. // 类别
  170. result = await dictDataStore.query({ code: 'matchForm', is_use: '0' })
  171. if ($checkRes(result)) formList.value = result.data
  172. // 赛事状态
  173. result = await dictDataStore.query({ code: 'matchStatus', is_use: '0' })
  174. if ($checkRes(result)) statusList.value = result.data
  175. }
  176. const search = async (query = { skip: 0, limit }) => {
  177. const info = {
  178. skip: query.skip,
  179. limit: query.limit,
  180. ...searchForm.value,
  181. is_use: '0',
  182. status: '1'
  183. }
  184. const res = await store.query(info)
  185. if (res.errcode == '0') {
  186. list.value = res.data
  187. total.value = res.total
  188. }
  189. }
  190. const activeName = ref('first')
  191. const handleClick = (tab, event) => {
  192. console.log(tab, event)
  193. }
  194. // 字典数据转换
  195. const getDict = (data, model) => {
  196. let res
  197. if (model == 'form') res = formList.value.find((f) => f.value == data)
  198. else if (model == 'type') res = typeList.value.find((f) => f.value == data)
  199. else if (model == 'status') res = statusList.value.find((f) => f.value == data)
  200. return get(res, 'label')
  201. }
  202. // 查看
  203. const toView = (item) => {
  204. router.push({ path: '/innovation/detail', query: { id: item.id || item._id } })
  205. }
  206. // 时间
  207. const getTime = (data) => {
  208. if (data) return `${data[0]} - ${data[1]}`
  209. }
  210. </script>
  211. <style scoped lang="scss">
  212. .main {
  213. background: rgb(248, 248, 248);
  214. .innovation {
  215. .image {
  216. width: 100%;
  217. height: 250px;
  218. }
  219. }
  220. .one {
  221. background: #ffffff;
  222. border-radius: 10px;
  223. padding: 15px;
  224. margin: 10px 0;
  225. .one_1 {
  226. border-bottom: 2px solid #e4e7ed;
  227. :deep(.el-tabs__nav-wrap:after) {
  228. background-color: transparent !important;
  229. }
  230. }
  231. .one_2 {
  232. display: flex;
  233. align-items: center;
  234. padding: 10px 0;
  235. border-bottom: #9d9898 1px dashed;
  236. .left {
  237. text-align: center;
  238. overflow: hidden;
  239. white-space: nowrap;
  240. text-overflow: ellipsis;
  241. font-family: PingFangSC-Medium;
  242. }
  243. .right {
  244. .title {
  245. color: #666;
  246. font-size: 14px;
  247. line-height: 15px;
  248. display: inline-block;
  249. overflow: hidden;
  250. text-decoration: none;
  251. }
  252. .title:hover {
  253. color: #2374ff;
  254. }
  255. }
  256. }
  257. }
  258. .two {
  259. margin-top: 20px;
  260. background: #ffffff;
  261. border-radius: 10px;
  262. padding: 15px;
  263. .list {
  264. display: flex;
  265. align-items: center;
  266. min-height: 150px;
  267. width: 100%;
  268. margin-bottom: 10px;
  269. position: relative;
  270. overflow: hidden;
  271. border: 1px solid #f5f5f5;
  272. .left {
  273. display: flex;
  274. align-items: center;
  275. justify-content: center;
  276. .image {
  277. width: 180px;
  278. height: 120px;
  279. }
  280. }
  281. .right {
  282. .right_1 {
  283. padding: 10px 0 0 0;
  284. .type {
  285. padding-left: 4px;
  286. padding-right: 4px;
  287. height: 22px;
  288. line-height: 20px;
  289. background: #f8f9fc;
  290. border-radius: 1px;
  291. border: 1px solid #dde2e7;
  292. font-size: 12px;
  293. font-family:
  294. PingFangSC-Regular,
  295. PingFang SC;
  296. font-weight: 400;
  297. color: #a9b2c6;
  298. text-align: center;
  299. vertical-align: top;
  300. display: inline-block;
  301. margin-right: 8px;
  302. }
  303. .title {
  304. max-width: 88%;
  305. display: inline-block;
  306. overflow: hidden;
  307. text-overflow: ellipsis;
  308. white-space: nowrap;
  309. font-size: 16px;
  310. font-family:
  311. PingFangSC-Medium,
  312. PingFang SC;
  313. font-weight: 500;
  314. color: #222;
  315. line-height: 22px;
  316. }
  317. }
  318. .right_2 {
  319. padding: 5px 0;
  320. font-size: 12px;
  321. font-family:
  322. PingFangSC-Regular,
  323. PingFang SC;
  324. font-weight: 400;
  325. color: #666;
  326. }
  327. .right_3 {
  328. padding: 5px 0;
  329. display: flex;
  330. justify-content: space-between;
  331. .right_3Left {
  332. font-size: 12px;
  333. font-family:
  334. PingFangSC-Regular,
  335. PingFang SC;
  336. font-weight: 400;
  337. color: #949fb8;
  338. }
  339. .right_3Right {
  340. text-align: right;
  341. font-size: 16px;
  342. font-family:
  343. PingFangSC-Semibold,
  344. PingFang SC;
  345. font-weight: 600;
  346. color: #ff5602;
  347. }
  348. }
  349. .right_4 {
  350. padding-top: 10px;
  351. border-top: 1px solid #f3f3f3;
  352. }
  353. }
  354. .join {
  355. position: absolute;
  356. right: -23px;
  357. top: 10px;
  358. font-size: 12px;
  359. font-family:
  360. PingFangSC-Normal,
  361. PingFang SC;
  362. color: #fff;
  363. line-height: 21px;
  364. height: 21px;
  365. width: 100px;
  366. text-align: center;
  367. -ms-transform: rotate(45deg);
  368. transform: rotate(45deg);
  369. -webkit-transform: rotate(45deg);
  370. -moz-transform: rotate(45deg);
  371. padding-left: 9px;
  372. }
  373. .join0 {
  374. background: #e6f4fe;
  375. color: #638aa5;
  376. }
  377. .join1 {
  378. background: #ededed;
  379. color: #666c7d;
  380. }
  381. }
  382. }
  383. .thr {
  384. display: flex;
  385. flex-direction: row-reverse;
  386. padding: 20px;
  387. }
  388. }
  389. </style>