index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. <template>
  2. <custom-layout class="main">
  3. <el-col :span="24" class="one">
  4. <el-image class="image" :src="lists" fit="fill" />
  5. </el-col>
  6. <div class="two">
  7. <div class="w_1300">
  8. <div class="active">
  9. <div class="active_1" v-show="industry && industry.length > 0">
  10. <div class="active_left">行业:</div>
  11. <div class="active_right">
  12. <div class="active_label" v-for="(item, index) in industry" :key="index">
  13. {{ item.title }}<el-icon @click="toDel(item, '1')"><Close /></el-icon>
  14. </div>
  15. </div>
  16. </div>
  17. <div class="active_1" v-show="city && city.length > 0">
  18. <div class="active_left">所在地:</div>
  19. <div class="active_right">
  20. <div class="active_label" v-for="(item, index) in city" :key="index">
  21. {{ item.name }}<el-icon @click="toDel(item, '2')"><Close /></el-icon>
  22. </div>
  23. </div>
  24. </div>
  25. </div>
  26. <div class="twoSeacher">
  27. <div class="twoLeft">
  28. <span>行业</span>
  29. </div>
  30. <div v-if="!oneShow" class="twoRight">
  31. <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList.slice(0, 6)" :key="index" @click="toSelect(item, '1')">
  32. {{ item.title }}
  33. </div>
  34. </div>
  35. <div v-else class="twoRight">
  36. <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList" :key="index" @click="toSelect(item, '2')">
  37. {{ item.title }}
  38. </div>
  39. </div>
  40. <div class="button">
  41. <span v-if="!oneShow" @click="oneShow = true">
  42. <el-icon><ArrowDown /></el-icon>
  43. </span>
  44. <span v-else @click="oneShow = false">
  45. <el-icon><ArrowUp /></el-icon>
  46. </span>
  47. </div>
  48. </div>
  49. <div class="twoSeacher">
  50. <div class="twoLeft">
  51. <span>所在地</span>
  52. </div>
  53. <div class="twoRight">
  54. <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in cityList" :key="index" @click="toSelect(item, '2')">
  55. {{ item.name }}
  56. </div>
  57. </div>
  58. </div>
  59. <div class="twoIpunt">
  60. <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="中试平台/实验室名称" />
  61. <a-input class="input" size="large" v-model:value="searchForm.build" placeholder="建设主体" />
  62. <a-input class="input" size="large" v-model:value="searchForm.operate" placeholder="运营主体" />
  63. <a-input class="input" size="large" v-model:value="searchForm.field" placeholder="服务产业领域" />
  64. <a-button class="button" size="large" type="primary" @click="toSearchInfo">检索</a-button>
  65. </div>
  66. </div>
  67. </div>
  68. <el-col :span="24" class="thr">
  69. <div class="w_1300">
  70. <el-row :gutter="16">
  71. <el-col :span="6" v-for="(item, index) in list" :key="index" @click="toView(item)">
  72. <div class="list">
  73. <el-image class="image" :src="getUrl(item.file)" fit="cover"> </el-image>
  74. <el-col :span="24" class="name textOne">
  75. <el-tooltip effect="dark" :content="item.name" placement="top">
  76. {{ item.name || '暂无名称' }}
  77. </el-tooltip>
  78. </el-col>
  79. <el-col :span="24" class="other_1">
  80. <span>建设主体:</span>
  81. {{ item.build || '暂无建设主体' }}
  82. </el-col>
  83. <el-col :span="24" class="other_1">
  84. <span>运营主体:</span>
  85. {{ item.operate || '暂无运营主体' }}
  86. </el-col>
  87. <el-col :span="24" class="other_1">
  88. <span>服务产业领域:</span>
  89. {{ item.field || '暂无服务产业领域' }}
  90. </el-col>
  91. <el-col :span="24" class="other_1">
  92. <span>地址:</span>
  93. {{ item.address || '暂无地址' }}
  94. </el-col>
  95. <el-col :span="24" class="other_1">
  96. <span>联系人:</span>
  97. {{ item.contacts || '暂无联系人' }}
  98. </el-col>
  99. <el-col :span="24" class="other_1">
  100. <span>联系电话:</span>
  101. {{ item.phone || '暂无联系电话' }}
  102. </el-col>
  103. </div>
  104. </el-col>
  105. </el-row>
  106. </div>
  107. </el-col>
  108. <el-col :span="24" class="four">
  109. <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
  110. </el-col>
  111. </custom-layout>
  112. </template>
  113. <script setup>
  114. // 图片引入
  115. import lists from '/images/bg-khal-list.jpg'
  116. // 接口
  117. import { FootplateStore } from '@/store/api/platform/footplate'
  118. import { RegionStore } from '@/store/api/system/region'
  119. import { SectorStore } from '@/store/api/platform/sector'
  120. const store = FootplateStore()
  121. const regionStore = RegionStore()
  122. const sectorStore = SectorStore()
  123. import { UserStore } from '@/store/user'
  124. const userStore = UserStore()
  125. const user = computed(() => userStore.user)
  126. // 加载中
  127. const loading = ref(false)
  128. // 路由
  129. const router = useRouter()
  130. // 是否展开
  131. const oneShow = ref(false)
  132. const cityList = ref([])
  133. const plateList = ref([])
  134. // 列表
  135. const searchForm = ref({})
  136. const list = ref([])
  137. let skip = 0
  138. let limit = inject('limit')
  139. const total = ref(6)
  140. // 查询
  141. const industry = ref([])
  142. const city = ref([])
  143. // 请求
  144. onMounted(async () => {
  145. loading.value = true
  146. await searchOther()
  147. await search({ skip, limit })
  148. loading.value = false
  149. })
  150. const searchOther = async () => {
  151. let res
  152. res = await regionStore.list({ level: 'city', parent_code: 22 })
  153. if (res.errcode == '0') cityList.value = res.data
  154. cityList.value.unshift({ id: '-1', code: '-1', name: '不限', is_active: true })
  155. res = await sectorStore.query({ is_use: '0' })
  156. if (res.errcode == '0') plateList.value = res.data
  157. plateList.value.unshift({ id: '-1', title: '不限', is_active: true })
  158. }
  159. const search = async (query = { skip, limit }) => {
  160. skip = query.skip
  161. limit = query.limit
  162. const info = { skip: query.skip, limit: query.limit, ...searchForm.value }
  163. const res = await store.query(info)
  164. if (res.errcode == '0') {
  165. list.value = res.data
  166. total.value = res.total
  167. }
  168. }
  169. // 搜索
  170. const toSearchInfo = async () => {
  171. await search({ skip, limit })
  172. }
  173. // 查看
  174. const toView = (item) => {
  175. router.push({ path: '/platform/detail', query: { id: item.id || item._id } })
  176. }
  177. const currentPage = ref(1)
  178. // 分页
  179. const changePage = (page = currentPage.value) => {
  180. search({ skip: (page - 1) * limit, limit: limit })
  181. }
  182. const sizeChange = (limits) => {
  183. limit = limits
  184. currentPage.value = 1
  185. search({ skip: 0, limit: limit })
  186. }
  187. const getUrl = (item) => {
  188. if (item && item.length > 0) return `${import.meta.env.VITE_APP_HOST}${item[0].uri}`
  189. }
  190. const toSelect = (data, type) => {
  191. if (data.id != '-1') {
  192. if (type == '1') {
  193. for (const val of plateList.value) {
  194. if (data.id == val.id) val.is_active = true
  195. if (val.id == '-1') val.is_active = false
  196. }
  197. const res = industry.value.find((i) => i.id == data.id)
  198. if (!res) industry.value.push(data)
  199. } else {
  200. for (const val of cityList.value) {
  201. if (data.id == val.id) val.is_active = true
  202. if (val.id == '-1') val.is_active = false
  203. }
  204. const res = city.value.find((i) => i.id == data.id)
  205. if (!res) city.value.push(data)
  206. }
  207. } else {
  208. if (type == '1') {
  209. for (const val of plateList.value) {
  210. if (val.id == '-1') val.is_active = true
  211. else val.is_active = false
  212. }
  213. industry.value = []
  214. } else {
  215. for (const val of cityList.value) {
  216. if (val.id == '-1') val.is_active = true
  217. else val.is_active = false
  218. }
  219. city.value = []
  220. }
  221. }
  222. }
  223. const toDel = (data, type) => {
  224. if (type == '1') {
  225. for (const val of plateList.value) {
  226. if (data.id == val.id) val.is_active = false
  227. }
  228. industry.value = industry.value.filter((f) => f.id != data.id)
  229. if (industry.value.length == 0) {
  230. for (const val of plateList.value) {
  231. if (val.id == '-1') val.is_active = true
  232. }
  233. }
  234. } else {
  235. for (const val of cityList.value) {
  236. if (data.id == val.id) val.is_active = false
  237. }
  238. city.value = city.value.filter((f) => f.id != data.id)
  239. if (city.value.length == 0) {
  240. for (const val of cityList.value) {
  241. if (val.id == '-1') val.is_active = true
  242. }
  243. }
  244. }
  245. }
  246. </script>
  247. <style scoped lang="scss">
  248. .main {
  249. .one {
  250. .image {
  251. width: 100%;
  252. height: 350px;
  253. }
  254. }
  255. .two {
  256. margin: 10px 0;
  257. background-color: $global-color-fff;
  258. .active {
  259. margin: 0 0 10px 0;
  260. .active_1 {
  261. display: inline-flex;
  262. background: #f5f7f9;
  263. border-radius: 2px;
  264. min-height: 28px;
  265. line-height: 28px;
  266. margin: 0 10px 0 0;
  267. position: relative;
  268. background-color: #fff;
  269. .active_left {
  270. flex: 0 0 auto;
  271. font-family: PingFangSC-Regular;
  272. color: #525a68;
  273. line-height: 36px;
  274. }
  275. .active_right {
  276. font-family: PingFangSC-Regular;
  277. color: rgba(0, 0, 0, 0.85);
  278. line-height: 28px;
  279. padding-right: 4px;
  280. display: flex;
  281. flex-wrap: wrap;
  282. overflow: hidden;
  283. .active_label {
  284. overflow: hidden;
  285. display: inline-block;
  286. margin-right: 10px;
  287. margin-top: 3px;
  288. margin-bottom: 3px;
  289. padding: 10px;
  290. display: flex;
  291. align-items: center;
  292. flex: none;
  293. box-sizing: border-box;
  294. max-width: 100%;
  295. height: 30px;
  296. background: #f5f5f5;
  297. border: 1px solid #f0f0f0;
  298. border-radius: 2px;
  299. cursor: default;
  300. }
  301. }
  302. }
  303. }
  304. .twoSeacher {
  305. display: flex;
  306. justify-content: center;
  307. align-items: stretch;
  308. position: relative;
  309. border: solid 1px #e5e5e5;
  310. // border-bottom: 0;
  311. font-size: $global-font-size-18;
  312. color: #666;
  313. min-height: 60px;
  314. overflow: hidden;
  315. .twoLeft {
  316. display: flex;
  317. justify-content: center;
  318. align-items: center;
  319. flex-shrink: 0;
  320. width: 110px;
  321. text-align: center;
  322. color: #000;
  323. font-weight: bold;
  324. background-color: #fafafa;
  325. }
  326. .twoRight {
  327. display: flex;
  328. flex-wrap: wrap;
  329. align-items: center;
  330. padding: 12px;
  331. flex: 1;
  332. border-left: solid 1px #e5e5e5;
  333. background-color: #fff;
  334. .label {
  335. margin-right: 3px;
  336. color: #313131;
  337. margin-bottom: 10px;
  338. padding: 8px 10px;
  339. border-radius: 3px;
  340. background-color: #fff;
  341. border: solid 1px transparent;
  342. cursor: pointer;
  343. }
  344. .show {
  345. color: #0a58c2;
  346. border: solid 1px #006dd2;
  347. }
  348. .label:hover {
  349. color: $global-color-107;
  350. }
  351. }
  352. .button {
  353. display: flex;
  354. align-items: center;
  355. margin: 0 5px 0 0;
  356. }
  357. }
  358. .twoSeacher:first-child {
  359. border-bottom: 0;
  360. }
  361. .twoIpunt {
  362. display: flex;
  363. align-items: center;
  364. justify-content: space-between;
  365. margin: 10px 0 0 0;
  366. .input {
  367. margin: 0 5px 0 0;
  368. }
  369. .button {
  370. margin: 0 0 0 5px;
  371. }
  372. }
  373. }
  374. .thr {
  375. .list {
  376. padding: 15px;
  377. border: 1px solid #f2f4f6;
  378. border-radius: 8px;
  379. margin: 0 0 15px 0;
  380. .name {
  381. font-size: $global-font-size-20;
  382. font-weight: bold;
  383. display: inline-block;
  384. margin: 0 0 8px 0;
  385. }
  386. .name:hover {
  387. color: #2374ff;
  388. cursor: pointer;
  389. }
  390. .other_1 {
  391. font-family: 'PingFangSC-Light', 'Microsoft YaHei', 'WenQuanYi Micro Hei', arial, sans-serif;
  392. font-size: $global-font-size-18;
  393. font-weight: normal;
  394. color: #666;
  395. }
  396. .other_1:hover {
  397. color: #2374ff;
  398. cursor: pointer;
  399. }
  400. }
  401. }
  402. .four {
  403. display: flex;
  404. justify-content: center;
  405. margin: 20px 0;
  406. }
  407. }
  408. </style>