project.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <template>
  2. <custom-layout class="main">
  3. <el-col :span="24" class="one">
  4. <div class="w_1300">
  5. <el-col :span="24" class="one_1">
  6. <div class="search">
  7. <el-input v-model="searchForm.name" size="large" placeholder="请输入关键字" :suffix-icon="Search">
  8. <template #append>
  9. <el-button type="primary" size="large" @click="toSearchInfo">搜索</el-button>
  10. </template>
  11. </el-input>
  12. </div>
  13. </el-col>
  14. <el-col :span="24" class="one_2">
  15. <div class="one_2_1">
  16. <div class="Seacher">
  17. <div class="OneLeft">
  18. <span>行业</span>
  19. </div>
  20. <div v-if="!twoShow" class="OneRight">
  21. <el-checkbox class="label" @change="oneChange" v-for="(item, index) in plateList.slice(0, 4)" :key="index" v-model="checked1" :label="item.title" size="large" />
  22. </div>
  23. <div v-else class="OneRight">
  24. <el-checkbox class="label" @change="oneChange" v-for="(item, index) in plateList" :key="index" v-model="checked1" :label="item.title" size="large" />
  25. </div>
  26. <div class="button">
  27. <span v-if="!twoShow" @click="twoShow = true">
  28. <el-icon><ArrowDown /></el-icon>
  29. </span>
  30. <span v-else @click="twoShow = false">
  31. <el-icon><ArrowUp /></el-icon>
  32. </span>
  33. </div>
  34. </div>
  35. <div class="Seacher">
  36. <div class="OneLeft">
  37. <span>技术领域</span>
  38. </div>
  39. <div v-if="!oneShow" class="OneRight">
  40. <el-checkbox class="label" @change="oneChange" v-for="(item, index) in typeList.slice(0, 8)" :key="index" v-model="checked2" :label="item.label" size="large" />
  41. </div>
  42. <div v-else class="OneRight">
  43. <el-checkbox class="label" @change="oneChange" v-for="(item, index) in typeList" :key="index" v-model="checked2" :label="item.label" size="large" />
  44. </div>
  45. <div class="button">
  46. <span v-if="!oneShow" @click="oneShow = true">
  47. <el-icon><ArrowDown /></el-icon>
  48. </span>
  49. <span v-else @click="oneShow = false">
  50. <el-icon><ArrowUp /></el-icon>
  51. </span>
  52. </div>
  53. </div>
  54. <div class="Seacher">
  55. <div class="OneLeft">
  56. <span>所在地</span>
  57. </div>
  58. <div class="OneRight">
  59. <el-checkbox class="label" @change="oneChange" v-for="(item, index) in cityList" :key="index" v-model="checked3" :label="item.name" size="large" />
  60. </div>
  61. </div>
  62. <div class="Seacher">
  63. <div class="OneLeft">
  64. <span>项目成熟度</span>
  65. </div>
  66. <div class="OneRight">
  67. <el-checkbox class="label" @change="oneChange" v-for="(item, index) in maturityList" :key="index" v-model="checked4" :label="item.label" size="large" />
  68. </div>
  69. </div>
  70. <div class="one_ipunt">
  71. <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
  72. <a-input class="input" size="large" v-model:value="searchForm.source" placeholder="项目来源" />
  73. <a-input class="input" size="large" v-model:value="searchForm.main" placeholder="项目主体" />
  74. <a-input class="input" size="large" v-model:value="searchForm.progress" placeholder="项目进展" />
  75. <a-button class="button" size="large" type="primary" @click="toSearchInfo">检索</a-button>
  76. </div>
  77. </div>
  78. <div class="one_2_2">
  79. <div class="list" :class="['list' + index]" v-for="(item, index) in list" :key="index" @click="toView(item)">
  80. <div class="type textOne">{{ item.industry || '暂无' }}</div>
  81. <div class="title">
  82. <p class="ellipsis-3">{{ item.name || '暂无' }}</p>
  83. </div>
  84. <div class="address">
  85. <el-icon color="#595959"><Location /></el-icon>
  86. <span class="textOne">{{ item.main || '暂无' }}</span>
  87. </div>
  88. <div class="biaoqian textOne">
  89. <span v-if="item.technology">{{ item.technology }}</span>
  90. <span v-if="item.sell">{{ item.sell }}</span>
  91. </div>
  92. <span class="state" :class="['state1']"></span>
  93. </div>
  94. </div>
  95. <div class="one_2_3">
  96. <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
  97. </div>
  98. </el-col>
  99. </div>
  100. </el-col>
  101. </custom-layout>
  102. </template>
  103. <script setup>
  104. const $checkRes = inject('$checkRes')
  105. // 接口
  106. import { ProjectStore } from '@/store/api/platform/project'
  107. import { DictDataStore } from '@/store/api/system/dictData'
  108. import { RegionStore } from '@/store/api/system/region'
  109. import { SectorStore } from '@/store/api/platform/sector'
  110. const store = ProjectStore()
  111. const dictDataStore = DictDataStore()
  112. const regionStore = RegionStore()
  113. const sectorStore = SectorStore()
  114. // 路由
  115. const router = useRouter()
  116. // 是否展开
  117. const twoShow = ref(false)
  118. const oneShow = ref(false)
  119. // 加载中
  120. const loading = ref(false)
  121. const checked1 = ref([])
  122. const checked2 = ref([])
  123. const checked3 = ref([])
  124. const checked4 = ref([])
  125. const typeList = ref([])
  126. const plateList = ref([])
  127. // 字典表
  128. const maturityList = ref([])
  129. const cityList = ref([])
  130. // 列表
  131. const list = ref([])
  132. let skip = 0
  133. let limit = 15
  134. const total = ref(0)
  135. // 搜索
  136. const searchForm = ref({})
  137. // 请求
  138. onMounted(async () => {
  139. loading.value = true
  140. await searchOther()
  141. await search({ skip, limit })
  142. loading.value = false
  143. })
  144. const searchOther = async () => {
  145. let result
  146. // // 合作类型
  147. // result = await dictDataStore.query({ code: 'projectType', is_use: '0' })
  148. // if ($checkRes(result)) projectList.value = result.data
  149. // 成熟度
  150. result = await dictDataStore.query({ code: 'projectMaturity', is_use: '0' })
  151. if ($checkRes(result)) maturityList.value = result.data
  152. // // 行业分类
  153. // result = await dictDataStore.query({ code: 'industry', is_use: '0' })
  154. // if ($checkRes(result)) industryList.value = result.data
  155. // 技术领域
  156. result = await dictDataStore.query({ code: 'field', is_use: '0' })
  157. if ($checkRes(result)) typeList.value = result.data
  158. // 地区
  159. result = await regionStore.list({ level: 'city', parent_code: 22 })
  160. if ($checkRes(result)) cityList.value = result.data
  161. // 行业
  162. result = await sectorStore.query({ is_use: '0' })
  163. if ($checkRes(result)) plateList.value = result.data
  164. }
  165. const search = async (query = { skip, limit }) => {
  166. skip = query.skip
  167. limit = query.limit
  168. const info = {
  169. skip: query.skip,
  170. limit: query.limit,
  171. ...searchForm.value
  172. }
  173. const res = await store.list(info)
  174. if (res.errcode == '0') {
  175. list.value = res.data
  176. total.value = res.total
  177. }
  178. }
  179. // 搜索
  180. const toSearchInfo = async () => {
  181. await search({ skip, limit })
  182. }
  183. // 查看
  184. const toView = (item) => {
  185. router.push({ path: `/project/detail`, query: { id: item.id || item._id } })
  186. }
  187. const currentPage = ref(1)
  188. // 分页
  189. const changePage = (page = currentPage.value) => {
  190. search({ skip: (page - 1) * limit, limit: limit })
  191. }
  192. const sizeChange = (limits) => {
  193. limit = limits
  194. currentPage.value = 1
  195. search({ skip: 0, limit: limit })
  196. }
  197. // 选择
  198. const oneChange = async (value) => {
  199. if (checked1.value && checked1.value.length > 0) {
  200. searchForm.value.industryList = checked1.value
  201. } else if (checked2.value && checked2.value.length > 0) {
  202. searchForm.value.fieldList = checked2.value
  203. } else if (checked3.value && checked3.value.length > 0) {
  204. searchForm.value.cityList = checked3.value
  205. } else if (checked4.value && checked4.value.length > 0) {
  206. searchForm.value.maturityList = checked4.value
  207. } else searchForm.value = {}
  208. await search({ skip, limit })
  209. }
  210. </script>
  211. <style scoped lang="scss">
  212. .main {
  213. .one {
  214. background: url(/images/bg-tec-list.jpg) no-repeat;
  215. .one_1 {
  216. padding: 85px 0 0;
  217. .search {
  218. margin: 0 auto;
  219. width: 810px;
  220. :deep(.el-input--large .el-input__inner) {
  221. height: 60px;
  222. }
  223. }
  224. }
  225. .one_2 {
  226. margin-top: 100px;
  227. padding: 30px;
  228. background-color: $global-color-fff;
  229. .one_2_1 {
  230. .Seacher {
  231. display: flex;
  232. justify-content: center;
  233. align-items: stretch;
  234. position: relative;
  235. margin-bottom: 15px;
  236. .OneLeft {
  237. width: 134px;
  238. height: 36px;
  239. background-color: #f5f8ff;
  240. border-radius: 21px;
  241. font-size: $global-font-size-16;
  242. font-weight: bold;
  243. color: #000000;
  244. flex-shrink: 0;
  245. line-height: 36px;
  246. text-align: center;
  247. }
  248. .OneRight {
  249. display: flex;
  250. flex-wrap: wrap;
  251. align-items: center;
  252. padding: 0 12px;
  253. flex: 1;
  254. background-color: #fff;
  255. .label {
  256. cursor: pointer;
  257. }
  258. .label:hover {
  259. color: $global-color-107;
  260. }
  261. }
  262. .button {
  263. display: flex;
  264. align-items: center;
  265. margin: 0 5px 0 0;
  266. }
  267. }
  268. .one_ipunt {
  269. display: flex;
  270. align-items: center;
  271. justify-content: space-between;
  272. margin: 10px 0;
  273. .input {
  274. margin: 0 5px 0 0;
  275. }
  276. .button {
  277. margin: 0 0 0 5px;
  278. }
  279. }
  280. }
  281. .one_2_2 {
  282. margin: 20px 0;
  283. display: flex;
  284. flex-wrap: wrap;
  285. justify-content: center;
  286. align-items: center;
  287. .list {
  288. position: relative;
  289. margin: 0 39px 39px 0;
  290. width: 208px;
  291. height: 286px;
  292. box-shadow: 3px 4px 4px 0px rgba(41, 41, 115, 0.32);
  293. border: solid 1px #ededed;
  294. .type {
  295. margin-left: 33px;
  296. padding: 22px 10px 0 0;
  297. font-size: $global-font-size-16;
  298. color: #414141;
  299. }
  300. .title {
  301. display: flex;
  302. align-items: center;
  303. margin: 24px 18px 0;
  304. height: 100px;
  305. font-size: $global-font-size-18;
  306. font-weight: bold;
  307. color: #ffffff;
  308. .ellipsis-3 {
  309. display: -webkit-box;
  310. -webkit-box-orient: vertical;
  311. overflow: hidden;
  312. -webkit-line-clamp: 3;
  313. }
  314. }
  315. .address {
  316. margin-top: 80px;
  317. padding: 0 5px;
  318. font-size: $global-font-size-16;
  319. color: #282828;
  320. display: flex;
  321. align-items: center;
  322. justify-content: flex-end;
  323. }
  324. .biaoqian {
  325. margin: 10px 5px 0 5px;
  326. text-align: right;
  327. overflow: hidden;
  328. span {
  329. padding: 0 5px;
  330. background-color: #f5f8ff;
  331. border-radius: 3px;
  332. border: solid 1px #d2daec;
  333. font-size: $global-font-size-14;
  334. line-height: 23px;
  335. color: #7d8aaa;
  336. margin-right: 2px;
  337. }
  338. }
  339. }
  340. .state {
  341. display: block;
  342. position: absolute;
  343. right: 0px;
  344. top: 0px;
  345. width: 75px;
  346. height: 24px;
  347. background: url(/images/project/dbhi-kcxm-item-xmyl.png) no-repeat;
  348. }
  349. .state1 {
  350. background: url(/images/project/dbhi-kcxm-item-xm1.png) no-repeat;
  351. }
  352. .state2 {
  353. background: url(/images/project/dbhi-kcxm-item-xm2.png) no-repeat;
  354. }
  355. .state3 {
  356. background: url(/images/project/dbhi-kcxm-item-xm3.png) no-repeat;
  357. }
  358. .list0 {
  359. background: url(/images/project/dbhi-kcxm-item1.png) no-repeat;
  360. }
  361. .list1 {
  362. background: url(/images/project/dbhi-kcxm-item2.png) no-repeat;
  363. }
  364. .list2 {
  365. background: url(/images/project/dbhi-kcxm-item3.png) no-repeat;
  366. }
  367. .list3 {
  368. background: url(/images/project/dbhi-kcxm-item4.png) no-repeat;
  369. }
  370. .list4 {
  371. background: url(/images/project/dbhi-kcxm-item5.png) no-repeat;
  372. }
  373. .list5 {
  374. background: url(/images/project/dbhi-kcxm-item6.png) no-repeat;
  375. }
  376. .list6 {
  377. background: url(/images/project/dbhi-kcxm-item7.png) no-repeat;
  378. }
  379. .list7 {
  380. background: url(/images/project/dbhi-kcxm-item8.png) no-repeat;
  381. }
  382. .list8 {
  383. background: url(/images/project/dbhi-kcxm-item9.png) no-repeat;
  384. }
  385. .list9 {
  386. background: url(/images/project/dbhi-kcxm-item10.png) no-repeat;
  387. }
  388. .list10 {
  389. background: url(/images/project/dbhi-kcxm-item1.png) no-repeat;
  390. }
  391. .list11 {
  392. background: url(/images/project/dbhi-kcxm-item2.png) no-repeat;
  393. }
  394. .list12 {
  395. background: url(/images/project/dbhi-kcxm-item3.png) no-repeat;
  396. }
  397. .list13 {
  398. background: url(/images/project/dbhi-kcxm-item4.png) no-repeat;
  399. }
  400. .list14 {
  401. background: url(/images/project/dbhi-kcxm-item5.png) no-repeat;
  402. }
  403. .list:nth-child(5n) {
  404. margin-right: 0;
  405. }
  406. }
  407. .one_2_3 {
  408. display: flex;
  409. justify-content: center;
  410. margin: 20px 0;
  411. }
  412. }
  413. }
  414. }
  415. </style>