Browse Source

修改搜索

zs 8 months ago
parent
commit
05be38ec9e

+ 5 - 1
src/components/custom/custom-layout.vue

@@ -177,7 +177,11 @@ const toCenter = () => {
 }
 // 消息
 const toChat = () => {
-  router.push({ path: `/chat` })
+  if (user.value && user.value.id) {
+    router.push({ path: `/chat` })
+  } else {
+    router.push({ path: '/login', query: { status: '1' } })
+  }
 }
 const handleMouseOver = (index) => {
   data.value[index].hover = true

+ 8 - 0
src/router/index.js

@@ -201,11 +201,13 @@ const router = createRouter({
     },
     {
       path: '/help',
+      name: 'help',
       meta: { title: '产学研用协同创新数字化平台-帮助中心' },
       component: () => import('@/views/help/index.vue')
     },
     {
       path: '/brain',
+      name: 'brain',
       meta: { title: '产学研用协同创新数字化平台-产业大脑' },
       component: () => import('@/views/brain/index.vue')
     },
@@ -239,6 +241,12 @@ const router = createRouter({
       meta: { title: '产学研用协同创新数字化平台-产业大脑' },
       component: () => import('@/views/brain/six.vue')
     },
+    {
+      path: '/search',
+      name: 'search',
+      meta: { title: '产学研用协同创新数字化平台-搜索' },
+      component: () => import('@/views/search/index.vue')
+    },
     {
       path: '/loading',
       name: 'loading',

+ 18 - 69
src/views/chat/index.vue

@@ -1,51 +1,28 @@
 <template>
   <custom-layout class="main" v-loading="loading">
     <div class="one w_1300">
-      <div class="left">
+      <!-- <div class="left">
         <el-image class="image" :src="userLogo" fit="fill" />
-        <div class="name">{{ user.name || '测试用户' }}</div>
+        <div class="name">{{ user.nick_name || '测试用户' }}</div>
         <div class="menu">
-          <div class="menu_1">
+          <div class="menu_1" :class="[active == '1' ? 'menuTrue' : '']" @click="toActive('1')">
             <el-icon><User /></el-icon>
             <span>我的信息</span>
           </div>
-          <div class="menu_1">
+          <div class="menu_1" :class="[active == '2' ? 'menuTrue' : '']" @click="toActive('2')">
             <el-icon><Document /></el-icon>
             <span>对接记录</span>
           </div>
-          <div class="menu_1 menuTrue">
+          <div class="menu_1" :class="[active == '3' ? 'menuTrue' : '']" @click="toActive('3')">
             <el-icon><Bell /></el-icon>
             <span>消息中心</span>
           </div>
         </div>
-      </div>
+      </div> -->
       <div class="right">
-        <div class="right_1">
-          <div class="rightLeft">
-            <el-tabs v-model="activeName" @tab-click="handleClick">
-              <el-tab-pane label="全部" name="0"></el-tab-pane>
-              <el-tab-pane label="未读" name="1"></el-tab-pane>
-              <el-tab-pane label="已读" name="2"></el-tab-pane>
-            </el-tabs>
-          </div>
-          <div class="rightRight">
-            <div class="menu">
-              <span>标记已读</span>
-            </div>
-            <div class="menu">
-              <span>删除</span>
-            </div>
-            <div class="menu">
-              <span>全部已读</span>
-            </div>
-            <div class="menu">
-              <span>全部删除</span>
-            </div>
-          </div>
-        </div>
-        <div class="right_2">
-          <el-image class="image" :src="chat" fit="fill" />
-        </div>
+        <!-- <info v-if="active == '1'"></info>
+        <abutment v-else-if="active == '2'"></abutment> -->
+        <talk></talk>
       </div>
     </div>
   </custom-layout>
@@ -53,26 +30,20 @@
 
 <script setup>
 import userLogo from '/images/userLogo.png'
-import chat from '/images/chat.png'
-// 基础
-import moment from 'moment'
-// 接口
-import { ChatStore } from '@/store/api/platform/chat'
-import { UsersStore } from '@/store/api/user/user'
-const store = UsersStore()
-const chatstore = ChatStore()
+import talk from './parts/talk.vue'
+import abutment from './parts/abutment.vue'
+import info from './parts/info.vue'
+
 import { UserStore } from '@/store/user'
 const userStore = UserStore()
 
 const user = computed(() => userStore.user)
-// 路由
-const route = useRoute()
 // 加载中
 const loading = ref(false)
-const activeName = ref('0')
+const active = ref('3')
 
-const handleClick = (tab, event) => {
-  console.log(tab, event)
+const toActive = (item) => {
+  active.value = item
 }
 </script>
 <style scoped lang="scss">
@@ -117,31 +88,9 @@ const handleClick = (tab, event) => {
       }
     }
     .right {
-      width: 1020px;
+      width: 100%;
+      // width: 1020px;
       padding: 20px;
-      .right_1 {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        .rightRight {
-          display: flex;
-          align-items: center;
-          justify-content: flex-end;
-          .menu {
-            background: #f8f8f8;
-            padding: 10px 20px;
-            margin: 0 10px 0 0;
-            color: #666666;
-            border: 1px solid #bbbbbb;
-          }
-        }
-      }
-      .right_2 {
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        margin: 30px 0;
-      }
     }
   }
 }

+ 23 - 0
src/views/chat/parts/abutment.vue

@@ -0,0 +1,23 @@
+<template>
+  <div class="index">
+    <el-row>
+      <el-col :span="24" class="animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">首页 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+import { UserStore } from '@/store/user'
+const userStore = UserStore()
+const user = computed(() => userStore.user)
+// 加载中
+const loading = ref(false)
+// 路由
+const router = useRouter()
+</script>
+<style scoped lang="scss">
+.main {
+}
+</style>

+ 23 - 0
src/views/chat/parts/info.vue

@@ -0,0 +1,23 @@
+<template>
+  <div class="main">
+    <el-row>
+      <el-col :span="24" class="animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one">首页 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+import { UserStore } from '@/store/user'
+const userStore = UserStore()
+const user = computed(() => userStore.user)
+// 加载中
+const loading = ref(false)
+// 路由
+const router = useRouter()
+</script>
+<style scoped lang="scss">
+.main {
+}
+</style>

+ 69 - 0
src/views/chat/parts/talk.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="main">
+    <div class="right_1">
+      <div class="rightLeft">
+        <el-tabs v-model="activeName" @tab-click="handleClick">
+          <el-tab-pane label="全部" name="0"></el-tab-pane>
+          <el-tab-pane label="未读" name="1"></el-tab-pane>
+          <el-tab-pane label="已读" name="2"></el-tab-pane>
+        </el-tabs>
+      </div>
+      <div class="rightRight">
+        <div class="menu">
+          <span>标记已读</span>
+        </div>
+        <div class="menu">
+          <span>删除</span>
+        </div>
+        <div class="menu">
+          <span>全部已读</span>
+        </div>
+        <div class="menu">
+          <span>全部删除</span>
+        </div>
+      </div>
+    </div>
+    <div class="right_2">
+      <el-image class="image" :src="chat" fit="fill" />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import chat from '/images/chat.png'
+// 基础
+import moment from 'moment'
+
+const activeName = ref('0')
+
+const handleClick = (tab, event) => {
+  console.log(tab, event)
+}
+</script>
+<style scoped lang="scss">
+.main {
+  .right_1 {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    .rightRight {
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      .menu {
+        background: #f8f8f8;
+        padding: 10px 20px;
+        margin: 0 10px 0 0;
+        color: #666666;
+        border: 1px solid #bbbbbb;
+      }
+    }
+  }
+  .right_2 {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin: 30px 0;
+  }
+}
+</style>

+ 1 - 5
src/views/detail/project.vue

@@ -18,7 +18,7 @@
                 <span>行业</span>
               </div>
               <div v-if="!twoShow" class="OneRight">
-                <el-checkbox class="label" @change="oneChange" v-for="(item, index) in plateList.slice(0, 5)" :key="index" v-model="checked1" :label="item.title" size="large" />
+                <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" />
               </div>
               <div v-else class="OneRight">
                 <el-checkbox class="label" @change="oneChange" v-for="(item, index) in plateList" :key="index" v-model="checked1" :label="item.title" size="large" />
@@ -150,22 +150,18 @@ const searchOther = async () => {
   // 成熟度
   result = await dictDataStore.query({ code: 'projectMaturity', is_use: '0' })
   if ($checkRes(result)) maturityList.value = result.data
-  maturityList.value.unshift({ value: '-1', label: '不限' })
   // // 行业分类
   // result = await dictDataStore.query({ code: 'industry', is_use: '0' })
   // if ($checkRes(result)) industryList.value = result.data
   // 技术领域
   result = await dictDataStore.query({ code: 'field', is_use: '0' })
   if ($checkRes(result)) typeList.value = result.data
-  typeList.value.unshift({ value: '-1', label: '不限' })
   // 地区
   result = await regionStore.list({ level: 'city', parent_code: 22 })
   if ($checkRes(result)) cityList.value = result.data
-  cityList.value.unshift({ code: '-1', name: '不限' })
   // 行业
   result = await sectorStore.query({ is_use: '0' })
   if ($checkRes(result)) plateList.value = result.data
-  plateList.value.unshift({ id: '-1', title: '不限' })
 }
 const search = async (query = { skip, limit }) => {
   skip = query.skip

+ 3 - 12
src/views/elevenHatch/index.vue

@@ -16,18 +16,9 @@
                 </div>
                 <div class="boxall">
                   <div class="alltitle">孵化项目列表</div>
-                  <div class="wraptit">
-                    <span>项目名称</span><span>金额</span><span>风险概率</span><span>时间</span>
-                  </div>
+                  <div class="wraptit"><span>项目名称</span><span>金额</span><span>风险概率</span><span>时间</span></div>
                   <div class="one">
-                    <vue3-seamless-scroll
-                      :list="oneList"
-                      :hover="true"
-                      :step="0.2"
-                      :wheel="true"
-                      :isWatch="true"
-                      class="scroll"
-                    >
+                    <vue3-seamless-scroll :list="oneList" :hover="true" :step="0.2" :wheel="true" :isWatch="true" class="scroll">
                       <div class="wrap" v-for="(item, index) in oneList" :key="index">
                         <div class="other">{{ item.name }}</div>
                         <div class="other">{{ item.money }}</div>
@@ -230,7 +221,7 @@ onBeforeUnmount(() => {
         left: 0;
       }
       .image {
-        width: 430px;
+        width: 100%;
         height: 187px;
       }
       .wraptit span {

+ 0 - 1
src/views/five/index.vue

@@ -64,7 +64,6 @@
           </el-row>
         </el-col>
         <div class="two_ipunt">
-          <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="活动名称" />
           <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
           <a-input class="input" size="large" v-model:value="searchForm.industry" placeholder="所属产业" />
           <a-input class="input" size="large" v-model:value="searchForm.work" placeholder="组织单位" />

+ 52 - 16
src/views/four/index.vue

@@ -10,22 +10,16 @@
           <a-tab-pane key="4" tab="找需求"> </a-tab-pane>
           <a-tab-pane key="5" tab="更多+"> </a-tab-pane>
         </a-tabs>
-        <a-input-search
-          v-model:value="searchValue"
-          placeholder="请输入想要搜索的内容"
-          enter-button="搜索"
-          size="large"
-          @search="onSearch"
-        />
+        <div class="input_1">
+          <el-select size="large" v-model="searchValue" filterable remote reserve-keyword placeholder="请输入想要搜索的内容" :remote-method="remoteMethod" :loading="searchLoading">
+            <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
+          </el-select>
+          <el-button size="large" @click="onSearch" type="primary">搜索</el-button>
+        </div>
         <div class="hot">
           <div class="hot_1">热门搜索:</div>
           <div class="hot_2">
-            <span>商贸</span>
-            <span>红旗</span>
-            <span>有机发光器件</span>
-            <span>车载显示屏</span>
-            <span>政府质量奖</span>
-            <span>科技</span>
+            <span v-for="(item, index) in list" :key="index" @click="toSelect(item)">{{ item.title }}</span>
           </div>
         </div>
       </div>
@@ -38,19 +32,58 @@
 
 <script setup>
 // 组件
-// import expert from '@/views/expert/index.vue'
-// import demand from '@/views/demand/index.vue'
 import index from './parts/index.vue'
+import { TagsStore } from '@/store/api/system/tags'
+const store = TagsStore()
 // 加载中
 const loading = ref(false)
+const searchLoading = ref(false)
 const activeKey = ref('1')
+const searchValue = ref('')
+const list = ref([])
+const tagsList = ref([])
+// 路由
+const router = useRouter()
 // 请求
 onMounted(async () => {
   loading.value = true
   await search()
   loading.value = false
 })
-const search = async () => {}
+const search = async () => {
+  const info = {
+    skip: 0,
+    limit: 6,
+    is_use: '0',
+    status: '1'
+  }
+  const res = await store.query(info)
+  if (res.errcode == '0') list.value = res.data
+}
+const onSearch = async () => {
+  router.push({ path: '/search', query: { name: searchValue.value, type: activeKey.value } })
+}
+const toSelect = (item) => {
+  searchValue.value = item.title
+  router.push({ path: '/search', query: { name: item.title, type: activeKey.value } })
+}
+const remoteMethod = (query) => {
+  if (query) {
+    searchLoading.value = true
+    setTimeout(async () => {
+      searchLoading.value = false
+      const info = {
+        is_use: '0',
+        status: '1',
+        title: query
+      }
+      const res = await store.query(info)
+      if (res.errcode == '0') tagsList.value = res.data
+    }, 200)
+  } else {
+    tagsList.value = []
+  }
+}
 </script>
 <style scoped lang="scss">
 .main {
@@ -65,6 +98,9 @@ const search = async () => {}
 
     .input {
       width: 830px;
+      .input_1 {
+        display: flex;
+      }
       .hot {
         display: flex;
         margin: 10px 0 0 0;

+ 153 - 0
src/views/search/index.vue

@@ -0,0 +1,153 @@
+<template>
+  <custom-layout v-loading="loading">
+    <el-col :span="24" class="one">
+      <!-- <el-image class="image" :src="news" fit="fill" /> -->
+      <div class="input">
+        <a-tabs v-model:activeKey="activeKey" centered>
+          <a-tab-pane key="1" tab="企业"> </a-tab-pane>
+          <a-tab-pane key="2" tab="专家"> </a-tab-pane>
+          <a-tab-pane key="3" tab="项目"> </a-tab-pane>
+          <a-tab-pane key="4" tab="需求"> </a-tab-pane>
+          <a-tab-pane key="5" tab="供给"> </a-tab-pane>
+          <a-tab-pane key="6" tab="成果"> </a-tab-pane>
+        </a-tabs>
+        <div class="input_1">
+          <el-select size="large" v-model="searchValue" filterable remote reserve-keyword placeholder="请输入想要搜索的内容" :remote-method="remoteMethod" :loading="searchLoading">
+            <el-option v-for="item in tagsList" :key="item.id" :label="item.title" :value="item.title" />
+          </el-select>
+          <el-button size="large" @click="onSearch" type="primary">搜索</el-button>
+        </div>
+        <div class="hot">
+          <div class="hot_1">热门搜索:</div>
+          <div class="hot_2">
+            <span v-for="(item, index) in list" :key="index" @click="toSelect(item)">{{ item.title }}</span>
+          </div>
+        </div>
+      </div>
+    </el-col>
+    <el-col :span="24" class="two">
+      <company v-if="activeKey == '1'"></company>
+      <expert v-if="activeKey == '2'"></expert>
+      <project v-if="activeKey == '3'"></project>
+      <demand v-if="activeKey == '4'"></demand>
+      <supply v-if="activeKey == '5'"></supply>
+      <achievement v-if="activeKey == '6'"></achievement>
+    </el-col>
+  </custom-layout>
+</template>
+
+<script setup>
+// 组件
+import expert from './parts/expert.vue'
+import company from './parts/company.vue'
+import project from './parts/project.vue'
+import demand from './parts/demand.vue'
+import supply from './parts/supply.vue'
+import achievement from './parts/achievement.vue'
+
+import { TagsStore } from '@/store/api/system/tags'
+const store = TagsStore()
+
+const activeKey = ref('1')
+// 加载中
+const loading = ref(false)
+// 路由
+const route = useRoute()
+const router = useRouter()
+const searchValue = ref('')
+// 加载中
+const searchLoading = ref(false)
+const list = ref([])
+const tagsList = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  searchValue.value = route.query.name
+  activeKey.value = route.query.type
+  await search()
+  router.replace({ name: 'search' })
+  loading.value = false
+})
+const search = async () => {
+  const info = {
+    skip: 0,
+    limit: 6,
+    is_use: '0',
+    status: '1'
+  }
+  const res = await store.query(info)
+  if (res.errcode == '0') list.value = res.data
+}
+const toSelect = (item) => {
+  searchValue.value = item.name
+}
+const remoteMethod = (query) => {
+  if (query) {
+    searchLoading.value = true
+    setTimeout(async () => {
+      searchLoading.value = false
+      const info = {
+        is_use: '0',
+        status: '1',
+        title: query
+      }
+      const res = await store.query(info)
+      if (res.errcode == '0') tagsList.value = res.data
+    }, 200)
+  } else {
+    tagsList.value = []
+  }
+}
+provide('searchValue', searchValue)
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 200px;
+    background: url(/images/bg.png);
+    background-size: 100% 100%;
+
+    .input {
+      width: 830px;
+      .input_1 {
+        display: flex;
+      }
+      .hot {
+        display: flex;
+        margin: 10px 0 0 0;
+        padding: 10px;
+        .hot_1 {
+          font-size: $global-font-size-18;
+          font-family:
+            PingFangSC-Regular,
+            PingFang SC;
+          font-weight: 400;
+        }
+        .hot_2 {
+          span {
+            margin: 0 10px;
+            font-size: $global-font-size-18;
+            font-family:
+              PingFangSC-Regular,
+              PingFang SC;
+            font-weight: 400;
+            color: #666;
+            line-height: $global-font-size-18;
+            cursor: pointer;
+          }
+          span:hover {
+            color: #1989fa;
+          }
+        }
+      }
+      :deep(.ant-tabs .ant-tabs-tab) {
+        font-size: $global-font-size-18 !important;
+      }
+    }
+  }
+}
+</style>

+ 666 - 0
src/views/search/parts/achievement.vue

@@ -0,0 +1,666 @@
+<template>
+  <div class="main">
+    <div class="w_1300">
+      <!-- <div class="active">
+        <div class="active_1" v-show="industry && industry.length > 0">
+          <div class="active_left">行业:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in industry" :key="index">
+              {{ item.title }}<el-icon @click="toDel(item, '1')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="field && field.length > 0">
+          <div class="active_left">技术领域:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in field" :key="index">
+              {{ item.label }}<el-icon @click="toDel(item, '2')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="mature && mature.length > 0">
+          <div class="active_left">成熟度:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in mature" :key="index">
+              {{ item.label }}<el-icon @click="toDel(item, '3')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="sell && sell.length > 0">
+          <div class="active_left">出让方式:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in sell" :key="index">
+              {{ item.label }}<el-icon @click="toDel(item, '4')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="money && money.length > 0">
+          <div class="active_left">价格:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in money" :key="index">
+              {{ item.label }}<el-icon @click="toDel(item, '5')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="city && city.length > 0">
+          <div class="active_left">所在地:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in city" :key="index">
+              {{ item.name }}<el-icon @click="toDel(item, '6')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+      </div> -->
+      <div class="two">
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>行业</span>
+          </div>
+          <div v-if="!oneShow" class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList.slice(0, 6)" :key="index" @click="toSelect(item, '1')">
+              {{ item.title }}
+            </div>
+          </div>
+          <div v-else class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList" :key="index" @click="toSelect(item, '1')">
+              {{ item.title }}
+            </div>
+          </div>
+          <div class="button">
+            <span v-if="!oneShow" @click="oneShow = true">
+              <el-icon><ArrowDown /></el-icon>
+            </span>
+            <span v-else @click="oneShow = false">
+              <el-icon><ArrowUp /></el-icon>
+            </span>
+          </div>
+        </div>
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>技术领域</span>
+          </div>
+          <div v-if="!twoShow" class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList.slice(0, 10)" :key="index" @click="toSelect(item, '2')">
+              {{ item.label }}
+            </div>
+          </div>
+          <div v-else class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList" :key="index" @click="toSelect(item, '2')">
+              {{ item.label }}
+            </div>
+          </div>
+          <div class="button">
+            <span v-if="!twoShow" @click="twoShow = true">
+              <el-icon><ArrowDown /></el-icon>
+            </span>
+            <span v-else @click="twoShow = false">
+              <el-icon><ArrowUp /></el-icon>
+            </span>
+          </div>
+        </div>
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>成熟度</span>
+          </div>
+          <div class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in matureList" :key="index" @click="toSelect(item, '3')">
+              {{ item.label }}
+            </div>
+          </div>
+        </div>
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>出让方式</span>
+          </div>
+          <div class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in sellList" :key="index" @click="toSelect(item, '4')">
+              {{ item.label }}
+            </div>
+          </div>
+        </div>
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>价格</span>
+          </div>
+          <div class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in moneyList" :key="index" @click="toSelect(item, '5')">
+              {{ item.label }}
+            </div>
+          </div>
+        </div>
+        <div class="twoSeacher border">
+          <div class="twoLeft">
+            <span>所在地</span>
+          </div>
+          <div class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in cityList" :key="index" @click="toSelect(item, '6')">
+              {{ item.name }}
+            </div>
+          </div>
+        </div>
+        <div class="two_ipunt">
+          <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="成果名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.source" placeholder="项目来源" />
+          <a-input class="input" size="large" v-model:value="searchForm.industry" placeholder="所属产业" />
+          <a-button class="button" size="large" type="primary" @click="toSearchInfo">检索</a-button>
+        </div>
+      </div>
+      <div class="thr">
+        <div class="list" v-for="(item, index) in list" :key="index" @click="toView(item)">
+          <div class="list_1">
+            <el-image class="image" :src="file[index]" fit="fill" />
+            <div class="box">
+              <p class="name textMore">{{ item.name || '暂无' }}</p>
+            </div>
+            <div class="list_2">
+              <div class="other">
+                <el-image class="image" :src="one" fit="fill" />
+                <div class="text textOne">{{ item.field || '暂无' }}</div>
+              </div>
+              <div class="other">
+                <el-image class="image" :src="two" fit="fill" />
+                <div class="text textOne">{{ item.person || '暂无' }}</div>
+              </div>
+              <div class="other">
+                <el-image class="image" :src="thr" fit="fill" />
+                <div class="text textOne">{{ item.source || '暂无' }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="four">
+        <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+// 图片引入
+import bg_1 from '/images/achievement/tec_bg_1.png'
+import bg_2 from '/images/achievement/tec_bg_2.png'
+import bg_3 from '/images/achievement/tec_bg_3.png'
+import bg_4 from '/images/achievement/tec_bg_4.png'
+import bg_5 from '/images/achievement/tec_bg_6.png'
+import bg_6 from '/images/achievement/tec_bg_8.png'
+import bg_7 from '/images/achievement/tec_bg_9.png'
+import bg_8 from '/images/achievement/tec_bg_10.png'
+import bg_9 from '/images/achievement/tec_bg_7.png'
+import one from '/images/achievement/bg-cgyx-list-icon1.png'
+import two from '/images/achievement/bg-cgyx-list-icon2.png'
+import thr from '/images/achievement/bg-cgyx-list-icon3.png'
+
+const $checkRes = inject('$checkRes')
+// 接口
+import { AchievementStore } from '@/store/api/platform/achievement'
+import { DictDataStore } from '@/store/api/system/dictData'
+import { RegionStore } from '@/store/api/system/region'
+import { SectorStore } from '@/store/api/platform/sector'
+const store = AchievementStore()
+const dictDataStore = DictDataStore()
+const regionStore = RegionStore()
+const sectorStore = SectorStore()
+// 路由
+const router = useRouter()
+
+const searchValue = inject('searchValue')
+
+// 加载中
+const loading = ref(false)
+const file = ref([bg_1, bg_2, bg_3, bg_4, bg_5, bg_6, bg_7, bg_8, bg_9, bg_1, bg_2, bg_3])
+// 列表
+const list = ref([])
+let skip = 0
+let limit = inject('limit')
+const total = ref(0)
+// 是否展开
+const oneShow = ref(false)
+const twoShow = ref(false)
+// 字典表
+const moneyList = ref([])
+const matureList = ref([])
+const sellList = ref([])
+const cityList = ref([])
+const typeList = ref([])
+const plateList = ref([])
+// 搜索
+const searchForm = ref({})
+// 查询
+const industry = ref([])
+const field = ref([])
+const mature = ref([])
+const sell = ref([])
+const money = ref([])
+const city = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search()
+  loading.value = false
+})
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    ...searchForm.value
+  }
+  if (searchValue.value) info.tags = searchValue.value
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+const searchOther = async () => {
+  let result
+  // 技术领域
+  result = await dictDataStore.query({ code: 'field', is_use: '0' })
+  if ($checkRes(result)) typeList.value = result.data
+  // 成熟度
+  result = await dictDataStore.query({ code: 'mature', is_use: '0' })
+  if ($checkRes(result)) matureList.value = result.data
+  // 出让方式
+  result = await dictDataStore.query({ code: 'sell', is_use: '0' })
+  if ($checkRes(result)) sellList.value = result.data
+  // // 技术分类
+  // result = await dictDataStore.query({ code: 'technology', is_use: '0' })
+  // if ($checkRes(result)) technologyList.value = result.data
+  // 价格
+  result = await dictDataStore.query({ code: 'money', is_use: '0' })
+  if ($checkRes(result)) moneyList.value = result.data
+  // 处理数据
+  for (const val of moneyList.value) {
+    if (val.value == '0') val.is_active = true
+  }
+  matureList.value.unshift({ id: '-1', is_active: true, value: '-1', label: '不限' })
+  sellList.value.unshift({ id: '-1', is_active: true, value: '-1', label: '不限' })
+  typeList.value.unshift({ id: '-1', is_active: true, value: '-1', label: '不限' })
+  result = await regionStore.list({ level: 'city', parent_code: 22 })
+  if (result.errcode == '0') cityList.value = result.data
+  cityList.value.unshift({ id: '-1', is_active: true, code: '-1', name: '不限' })
+  result = await sectorStore.query({ is_use: '0' })
+  if (result.errcode == '0') plateList.value = result.data
+  plateList.value.unshift({ id: '-1', is_active: true, title: '不限' })
+}
+// 搜索
+const toSearchInfo = async () => {
+  await search({ skip, limit })
+}
+// 查看详情
+const toView = async (item) => {
+  router.push({ path: '/achievement/detail', query: { id: item.id || item._id } })
+}
+const currentPage = ref(1)
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  console.log(limits)
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+const toSelect = (data, type) => {
+  if (data.is_active) {
+    toDel(data, type)
+  } else {
+    if (data.id != '-1') {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = industry.value.find((i) => i.id == data.id)
+        if (!res) industry.value.push(data)
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = field.value.find((i) => i.id == data.id)
+        if (!res) field.value.push(data)
+      } else if (type == '3') {
+        for (const val of matureList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = mature.value.find((i) => i.id == data.id)
+        if (!res) mature.value.push(data)
+      } else if (type == '4') {
+        for (const val of sellList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = sell.value.find((i) => i.id == data.id)
+        if (!res) sell.value.push(data)
+      } else if (type == '5') {
+        if (data.value != '0') {
+          for (const val of moneyList.value) {
+            if (data.id == val.id) val.is_active = true
+            if (val.value == '0') val.is_active = false
+          }
+          const res = money.value.find((i) => i.id == data.id)
+          if (!res) money.value.push(data)
+        } else {
+          for (const val of moneyList.value) {
+            if (val.value == '0') val.is_active = true
+            else val.is_active = false
+          }
+          money.value = []
+        }
+      } else {
+        for (const val of cityList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = city.value.find((i) => i.id == data.id)
+        if (!res) city.value.push(data)
+      }
+    } else {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        industry.value = []
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        field.value = []
+      } else if (type == '3') {
+        for (const val of matureList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        mature.value = []
+      } else if (type == '4') {
+        for (const val of sellList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        sell.value = []
+      } else if (type == '5') {
+        for (const val of moneyList.value) {
+          if (val.value == '0') val.is_active = true
+          else val.is_active = false
+        }
+        money.value = []
+      } else {
+        for (const val of cityList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        city.value = []
+      }
+    }
+  }
+}
+const toDel = (data, type) => {
+  if (type == '1') {
+    for (const val of plateList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    industry.value = industry.value.filter((f) => f.id != data.id)
+    if (industry.value.length == 0) {
+      for (const val of plateList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '2') {
+    for (const val of typeList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    field.value = field.value.filter((f) => f.id != data.id)
+    if (field.value.length == 0) {
+      for (const val of typeList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '3') {
+    for (const val of matureList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    mature.value = mature.value.filter((f) => f.id != data.id)
+    if (mature.value.length == 0) {
+      for (const val of matureList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '4') {
+    for (const val of sellList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    sell.value = sell.value.filter((f) => f.id != data.id)
+    if (sell.value.length == 0) {
+      for (const val of sellList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '5') {
+    for (const val of moneyList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    money.value = money.value.filter((f) => f.id != data.id)
+    if (money.value.length == 0) {
+      for (const val of moneyList.value) {
+        if (val.value == '0') val.is_active = true
+      }
+    }
+  } else {
+    for (const val of cityList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    city.value = city.value.filter((f) => f.id != data.id)
+    if (city.value.length == 0) {
+      for (const val of cityList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    .image {
+      width: 100%;
+      height: 350px;
+    }
+  }
+  .active {
+    .active_1 {
+      display: inline-flex;
+      background: #f5f7f9;
+      border-radius: 2px;
+      min-height: 28px;
+      line-height: 28px;
+      margin: 0 10px 0 0;
+      position: relative;
+      background-color: #fff;
+      padding: 0 10px;
+      .active_left {
+        flex: 0 0 auto;
+        font-family: PingFangSC-Regular;
+        color: #525a68;
+        line-height: 36px;
+      }
+      .active_right {
+        font-family: PingFangSC-Regular;
+        color: rgba(0, 0, 0, 0.85);
+        line-height: 28px;
+        padding-right: 4px;
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        .active_label {
+          overflow: hidden;
+          display: inline-block;
+          margin-right: 10px;
+          margin-top: 3px;
+          margin-bottom: 3px;
+          padding: 10px;
+          display: flex;
+          align-items: center;
+          flex: none;
+          box-sizing: border-box;
+          max-width: 100%;
+          height: 30px;
+          background: #f5f5f5;
+          border: 1px solid #f0f0f0;
+          border-radius: 2px;
+          cursor: default;
+        }
+      }
+    }
+  }
+  .two {
+    margin: 10px 0;
+    background-color: $global-color-fff;
+    .twoSeacher {
+      display: flex;
+      justify-content: center;
+      align-items: stretch;
+      position: relative;
+      border: solid 1px #e5e5e5;
+      border-bottom: 0;
+      font-size: $global-font-size-18;
+      color: #666;
+      min-height: 60px;
+      overflow: hidden;
+      .twoLeft {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-shrink: 0;
+        width: 110px;
+        text-align: center;
+        color: #000;
+        font-weight: bold;
+        background-color: #fafafa;
+      }
+      .twoRight {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        padding: 12px;
+        flex: 1;
+        border-left: solid 1px #e5e5e5;
+        background-color: #fff;
+        .label {
+          margin-right: 3px;
+          color: #313131;
+          margin-bottom: 10px;
+          padding: 8px 10px;
+          border-radius: 3px;
+          background-color: #fff;
+          border: solid 1px transparent;
+          cursor: pointer;
+        }
+        .show {
+          color: #0a58c2;
+          border: solid 1px #006dd2;
+        }
+        .label:hover {
+          color: $global-color-107;
+        }
+      }
+      .button {
+        display: flex;
+        align-items: center;
+        margin: 0 5px 0 0;
+      }
+    }
+    .border {
+      border: solid 1px #e5e5e5;
+      border-bottom: 1 !important;
+    }
+    .two_ipunt {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin: 10px 0;
+      .input {
+        margin: 0 5px 0 0;
+      }
+      .button {
+        margin: 0 0 0 5px;
+      }
+    }
+  }
+  .thr {
+    margin: 10px 0;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    .list {
+      margin-right: 10px;
+      margin-bottom: 15px;
+      padding-top: 3px;
+      width: 317px;
+      height: 325px;
+      background-color: #fff;
+      box-shadow: 0 2px 5px 0 rgba(159, 158, 158, 0.3);
+      .list_1 {
+        position: relative;
+
+        .image {
+          height: 100%;
+          width: 100%;
+        }
+        .box {
+          display: flex !important;
+          align-items: center;
+          position: absolute;
+          top: 45px;
+          left: 0;
+          padding: 15px 10px;
+          width: 100%;
+          height: 82px;
+          background-color: rgba(0, 25, 79, 0.5);
+          font-size: $global-font-size-18;
+          line-height: 24px;
+          color: #fff;
+        }
+      }
+      .list_2 {
+        margin: 10px 13px 0;
+        .other {
+          display: flex;
+          align-items: center;
+          margin: 0 0 5px 0;
+          .image {
+            width: 25px;
+            height: 25px;
+            margin: 0 5px 0 0;
+          }
+          .text {
+            max-width: 260px;
+            font-size: $global-font-size-16;
+            line-height: 32px;
+            color: #404040;
+          }
+        }
+      }
+    }
+    .list:nth-child(4n) {
+      margin-right: 0;
+    }
+    .list:hover {
+      box-shadow: 0 2px 5px 0 rgba(159, 158, 158, 0.8);
+    }
+  }
+  .four {
+    display: flex;
+    justify-content: center;
+    margin: 20px 0;
+  }
+}
+</style>

+ 500 - 0
src/views/search/parts/company.vue

@@ -0,0 +1,500 @@
+<template>
+  <div class="main">
+    <div class="w_1300">
+      <!-- <div class="active">
+        <div class="active_1" v-show="industry && industry.length > 0">
+          <div class="active_left">行业:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in industry" :key="index">
+              {{ item.title }}<el-icon @click="toDel(item, '1')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="pattern && pattern.length > 0">
+          <div class="active_left">企业类型:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in pattern" :key="index">
+              {{ item.label }}<el-icon @click="toDel(item, '2')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="city && city.length > 0">
+          <div class="active_left">所在地:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in city" :key="index">
+              {{ item.name }}<el-icon @click="toDel(item, '3')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+      </div> -->
+      <el-col :span="24" class="two">
+        <div class="Seacher">
+          <div class="Left">
+            <span>行业</span>
+          </div>
+          <div v-if="!oneShow" class="Right">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList.slice(0, 6)" :key="index" @click="toSelect(item, '1')">
+              {{ item.title }}
+            </div>
+          </div>
+          <div v-else class="Right">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList" :key="index" @click="toSelect(item, '1')">
+              {{ item.title }}
+            </div>
+          </div>
+          <div class="button">
+            <span v-if="!oneShow" @click="oneShow = true">
+              <el-icon><ArrowDown /></el-icon>
+            </span>
+            <span v-else @click="oneShow = false">
+              <el-icon><ArrowUp /></el-icon>
+            </span>
+          </div>
+        </div>
+        <div class="Seacher">
+          <div class="Left">
+            <span>企业类型</span>
+          </div>
+          <div class="Right">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in patternList" :key="index" @click="toSelect(item, '2')">
+              {{ item.label }}
+            </div>
+          </div>
+        </div>
+        <div class="Seacher border">
+          <div class="Left">
+            <span>所在地</span>
+          </div>
+          <div class="Right">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in cityList" :key="index" @click="toSelect(item, '3')">
+              {{ item.name }}
+            </div>
+          </div>
+        </div>
+        <div class="two_ipunt">
+          <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="公司名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.direction" placeholder="研究方向" />
+          <a-input class="input" size="large" v-model:value="searchForm.scale" placeholder="公司规模" />
+          <a-button class="button" size="large" type="primary" @click="toSearchInfo">检索</a-button>
+        </div>
+      </el-col>
+      <div class="thr">
+        <div class="list" :class="['list' + index]" v-for="(item, index) in list" :key="index" @click="toView(item)">
+          <div class="name">{{ item.name || '暂无' }}</div>
+          <div class="other">
+            <div class="other_1">
+              <el-image class="image" :src="getUrl(item.logo)" fit="fill">
+                <template v-slot:error>
+                  <el-image class="image" :src="companyLogo" fit="fill" />
+                </template>
+              </el-image>
+            </div>
+            <div class="other_2">
+              <span class="text"><em>企业类型:</em>{{ getDict(item.pattern, 'pattern') || '暂无' }}</span>
+              <span class="text"><em>员工人数:</em>{{ item.person || '暂无' }}人</span>
+              <span class="text"><em>地址:</em>{{ getArea(item.area) || '暂无' }}</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="four">
+        <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+// 图片引入
+import companyLogo from '/images/companyLogo.jpg'
+
+const $checkRes = inject('$checkRes')
+import { get } from 'lodash-es'
+// 接口
+import { CompanyStore } from '@/store/api/user/company'
+import { RegionStore } from '@/store/api/system/region'
+import { SectorStore } from '@/store/api/platform/sector'
+import { DictDataStore } from '@/store/api/system/dictData'
+const store = CompanyStore()
+const regionStore = RegionStore()
+const sectorStore = SectorStore()
+const dictDataStore = DictDataStore()
+// 加载中
+const loading = ref(false)
+
+const searchValue = inject('searchValue')
+
+// 路由
+const router = useRouter()
+const list = ref([])
+let skip = 0
+let limit = 15
+const total = ref(0)
+// 是否展开
+const oneShow = ref(false)
+// 字典表
+const fieldList = ref([])
+const statusList = ref([])
+const patternList = ref([])
+const scaleList = ref([])
+const cityList = ref([])
+const plateList = ref([])
+// 搜索
+const searchForm = ref({})
+// 查询
+const industry = ref([])
+const pattern = ref([])
+const city = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+const searchOther = async () => {
+  let result
+  // // 技术领域
+  // result = await dictDataStore.query({ code: 'field', is_use: '0' })
+  // if ($checkRes(result)) fieldList.value = result.data
+  // // 企业状态
+  // result = await dictDataStore.query({ code: 'companyStatus', is_use: '0' })
+  // if ($checkRes(result)) statusList.value = result.data
+  // 企业类型
+  result = await dictDataStore.query({ code: 'companyType', is_use: '0' })
+  if ($checkRes(result)) patternList.value = result.data
+  patternList.value.unshift({ id: '-1', value: '-1', label: '不限', is_active: true })
+  // // 企业规模
+  // result = await dictDataStore.query({ code: 'companyScale', is_use: '0' })
+  // if ($checkRes(result)) scaleList.value = result.data
+  // // 企业所属行业
+  // result = await dictDataStore.query({ code: 'companyIndustry', is_use: '0' })
+  // if ($checkRes(result)) IndustryList.value = result.data
+  result = await regionStore.list({ level: 'city', parent_code: 22 })
+  if ($checkRes(result)) cityList.value = result.data
+  cityList.value.unshift({ id: '-1', code: '-1', name: '不限', is_active: true })
+  result = await sectorStore.query({ is_use: '0' })
+  if ($checkRes(result)) plateList.value = result.data
+  plateList.value.unshift({ id: '-1', title: '不限', is_active: true })
+}
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    ...searchForm.value
+  }
+  if (searchValue.value) info.tags = searchValue.value
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+// 地区
+const getArea = (data) => {
+  if (data) return data.join('-')
+  else return '暂无地区'
+}
+// 字典数据转换
+const getDict = (data, model) => {
+  let res
+  if (model == 'field') res = fieldList.value.find((f) => f.value == data)
+  else if (model == 'status') res = statusList.value.find((f) => f.value == data)
+  else if (model == 'pattern') res = patternList.value.find((f) => f.value == data)
+  else if (model == 'scale') res = scaleList.value.find((f) => f.value == data)
+  return get(res, 'label')
+}
+// 搜索
+const toSearchInfo = async () => {
+  await search({ skip, limit })
+}
+// 查看
+const toView = (item) => {
+  router.push({ path: `/company/detail`, query: { id: item.id || item._id } })
+}
+const getUrl = (item) => {
+  if (item && item.length > 0) return `${import.meta.env.VITE_APP_HOST}${item[0].uri}`
+}
+const currentPage = ref(1)
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+const toSelect = (data, type) => {
+  if (data.is_active) {
+    toDel(data, type)
+  } else {
+    if (data.id != '-1') {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = industry.value.find((i) => i.id == data.id)
+        if (!res) industry.value.push(data)
+      } else if (type == '2') {
+        for (const val of patternList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = pattern.value.find((i) => i.id == data.id)
+        if (!res) pattern.value.push(data)
+      } else {
+        for (const val of cityList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = city.value.find((i) => i.id == data.id)
+        if (!res) city.value.push(data)
+      }
+    } else {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        industry.value = []
+      } else if (type == '2') {
+        for (const val of patternList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        pattern.value = []
+      } else {
+        for (const val of cityList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        city.value = []
+      }
+    }
+  }
+}
+const toDel = (data, type) => {
+  if (type == '1') {
+    for (const val of plateList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    industry.value = industry.value.filter((f) => f.id != data.id)
+    if (industry.value.length == 0) {
+      for (const val of plateList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '2') {
+    for (const val of patternList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    pattern.value = pattern.value.filter((f) => f.id != data.id)
+    if (pattern.value.length == 0) {
+      for (const val of patternList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else {
+    for (const val of cityList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    city.value = city.value.filter((f) => f.id != data.id)
+    if (city.value.length == 0) {
+      for (const val of cityList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.main {
+  padding: 10px 0;
+  .one {
+    .image {
+      width: 100%;
+      height: 350px;
+    }
+  }
+  .active {
+    .active_1 {
+      display: inline-flex;
+      background: #f5f7f9;
+      border-radius: 2px;
+      min-height: 28px;
+      line-height: 28px;
+      margin: 0 10px 0 0;
+      position: relative;
+      background-color: #fff;
+      padding: 10px;
+      .active_left {
+        flex: 0 0 auto;
+        font-family: PingFangSC-Regular;
+        color: #525a68;
+        line-height: 36px;
+      }
+      .active_right {
+        font-family: PingFangSC-Regular;
+        color: rgba(0, 0, 0, 0.85);
+        line-height: 28px;
+        padding-right: 4px;
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        .active_label {
+          overflow: hidden;
+          display: inline-block;
+          margin-right: 10px;
+          margin-top: 3px;
+          margin-bottom: 3px;
+          padding: 10px;
+          display: flex;
+          align-items: center;
+          flex: none;
+          box-sizing: border-box;
+          max-width: 100%;
+          height: 30px;
+          background: #f5f5f5;
+          border: 1px solid #f0f0f0;
+          border-radius: 2px;
+          cursor: default;
+        }
+      }
+    }
+  }
+  .two {
+    .Seacher {
+      display: flex;
+      justify-content: center;
+      align-items: stretch;
+      position: relative;
+      border: solid 1px #e5e5e5;
+      border-bottom: 0;
+      font-size: $global-font-size-18;
+      color: #666;
+      min-height: 60px;
+      overflow: hidden;
+      .Left {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-shrink: 0;
+        width: 110px;
+        text-align: center;
+        color: #000;
+        font-weight: bold;
+        background-color: #fafafa;
+      }
+      .Right {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        padding: 12px;
+        flex: 1;
+        border-left: solid 1px #e5e5e5;
+        background-color: #fff;
+        .label {
+          margin-right: 3px;
+          color: #313131;
+          margin-bottom: 10px;
+          padding: 8px 10px;
+          border-radius: 3px;
+          background-color: #fff;
+          border: solid 1px transparent;
+          cursor: pointer;
+        }
+        .show {
+          color: #0a58c2;
+          border: solid 1px #006dd2;
+        }
+        .label:hover {
+          color: $global-color-107;
+        }
+      }
+      .button {
+        display: flex;
+        align-items: center;
+        margin: 0 5px 0 0;
+      }
+    }
+    .border {
+      border: solid 1px #e5e5e5;
+      border-bottom: 1;
+    }
+    .two_ipunt {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin: 10px 0;
+      .input {
+        margin: 0 5px 0 0;
+      }
+      .button {
+        margin: 0 0 0 5px;
+      }
+    }
+  }
+  .thr {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-wrap: wrap;
+    .list {
+      float: left;
+      width: 405px;
+      padding: 15px;
+      margin: 0 10px 25px 10px;
+      background: #f0f8ff;
+      color: #000;
+      .name {
+        height: 57px;
+        line-height: 57px;
+        overflow: hidden;
+        font-size: $global-font-size-18;
+        font-weight: bold;
+      }
+      .other {
+        display: flex;
+        .other_1 {
+          .image {
+            width: 95px;
+            height: 95px;
+            display: inline-block;
+          }
+        }
+        .other_2 {
+          display: flex;
+          flex-direction: column;
+          margin: 0 0 0 10px;
+          .text {
+            height: 25px;
+            display: block;
+            line-height: 24px;
+            overflow: hidden;
+            color: #666;
+            margin-bottom: 10px;
+            em {
+              border: 1px #ccc solid;
+              background: #fff;
+              border: 1px #ab94f8 solid;
+              padding: 1px 5px;
+              color: #4131bb;
+              margin-right: 6px;
+            }
+          }
+        }
+      }
+    }
+  }
+  .four {
+    display: flex;
+    justify-content: center;
+    margin: 20px 0;
+  }
+}
+</style>

+ 499 - 0
src/views/search/parts/demand.vue

@@ -0,0 +1,499 @@
+<template>
+  <div class="main">
+    <div class="w_1300">
+      <!-- <div class="active">
+    <div class="active_1" v-show="industry && industry.length > 0">
+      <div class="active_left">行业:</div>
+      <div class="active_right">
+        <div class="active_label" v-for="(item, index) in industry" :key="index">
+          {{ item.title }}<el-icon @click="toDel(item, '1')"><Close /></el-icon>
+        </div>
+      </div>
+    </div>
+    <div class="active_1" v-show="field && field.length > 0">
+      <div class="active_left">技术领域:</div>
+      <div class="active_right">
+        <div class="active_label" v-for="(item, index) in field" :key="index">
+          {{ item.label }}<el-icon @click="toDel(item, '2')"><Close /></el-icon>
+        </div>
+      </div>
+    </div>
+    <div class="active_1" v-show="city && city.length > 0">
+      <div class="active_left">所在地:</div>
+      <div class="active_right">
+        <div class="active_label" v-for="(item, index) in city" :key="index">
+          {{ item.name }}<el-icon @click="toDel(item, '3')"><Close /></el-icon>
+        </div>
+      </div>
+    </div>
+  </div> -->
+      <div class="demand">
+        <div class="demandOne">
+          <div class="demandSeacher">
+            <div class="demandOneLeft">
+              <span>行业</span>
+            </div>
+            <div v-if="!oneShow" class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList.slice(0, 6)" :key="index" @click="toSelect(item, '1')">
+                {{ item.title }}
+              </div>
+            </div>
+            <div v-else class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList" :key="index" @click="toSelect(item, '1')">
+                {{ item.title }}
+              </div>
+            </div>
+            <div class="button">
+              <span v-if="!oneShow" @click="oneShow = true">
+                <el-icon><ArrowDown /></el-icon>
+              </span>
+              <span v-else @click="oneShow = false">
+                <el-icon><ArrowUp /></el-icon>
+              </span>
+            </div>
+          </div>
+          <div class="demandSeacher">
+            <div class="demandOneLeft">
+              <span>技术领域</span>
+            </div>
+            <div v-if="!twoShow" class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList.slice(0, 10)" :key="index" @click="toSelect(item, '2')">
+                {{ item.label }}
+              </div>
+            </div>
+            <div v-else class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList" :key="index" @click="toSelect(item, '2')">
+                {{ item.label }}
+              </div>
+            </div>
+            <div class="button">
+              <span v-if="!twoShow" @click="twoShow = true">
+                <el-icon><ArrowDown /></el-icon>
+              </span>
+              <span v-else @click="twoShow = false">
+                <el-icon><ArrowUp /></el-icon>
+              </span>
+            </div>
+          </div>
+          <div class="demandSeacher border">
+            <div class="demandOneLeft">
+              <span>所在地</span>
+            </div>
+            <div class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in cityList" :key="index" @click="toSelect(item, '3')">
+                {{ item.name }}
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="demandIpunt">
+          <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="需求名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.industry" placeholder="所属产业" />
+          <a-input class="input" size="large" v-model:value="searchForm.company" placeholder="所属企业" />
+          <a-button class="button" size="large" type="primary" @click="toSearchInfo(searchForm, '0')">检索</a-button>
+        </div>
+        <div class="demandTwo">
+          <div class="demandTable">
+            <div class="label" v-for="(item, index) in column" :key="index" :style="item.style">
+              {{ item.name }}
+            </div>
+          </div>
+          <div class="demandValue">
+            <div class="value" v-for="(item, index) in list" :key="index">
+              <div class="table-colunm table-colunm1 textOne">{{ index + 1 }}</div>
+              <div class="table-colunm table-colunm2 textOne">{{ item.name || '暂无' }}</div>
+              <div class="table-colunm textOne">{{ item.field || '暂无' }}</div>
+              <div class="table-colunm table-colunm3 textOne">{{ getArea(item.area) }}</div>
+              <div class="table-colunm table-colunm1 textOne">{{ item.money || '面议' }}</div>
+              <div class="table-colunm table-colunm1 textOne">{{ getDict(item.status, 'status') || '未解决' }}</div>
+              <div class="table-colunm button" @click="toView(item)">查看详情</div>
+            </div>
+          </div>
+          <div class="demandTotal">
+            <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { get } from 'lodash-es'
+import { DemandStore } from '@/store/api/platform/demand'
+import { RegionStore } from '@/store/api/system/region'
+import { SectorStore } from '@/store/api/platform/sector'
+import { DictDataStore } from '@/store/api/system/dictData'
+const regionStore = RegionStore()
+const sectorStore = SectorStore()
+const demandStore = DemandStore()
+const dictDataStore = DictDataStore()
+// 路由
+const router = useRouter()
+
+const searchValue = inject('searchValue')
+
+// 字典表
+const cityList = ref([])
+const typeList = ref([])
+const plateList = ref([])
+const statusList = ref([])
+// 加载中
+const loading = ref(false)
+// 列表
+const list = ref([])
+let skip = 0
+let limit = inject('limit')
+const total = ref(0)
+const searchForm = ref({})
+// 查询
+const industry = ref([])
+const field = ref([])
+const city = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+const searchOther = async () => {
+  let res
+  res = await regionStore.list({ level: 'city', parent_code: 22 })
+  if (res.errcode == '0') cityList.value = res.data
+  cityList.value.unshift({ id: '-1', code: '-1', name: '不限', is_active: true })
+  res = await sectorStore.query({ is_use: '0' })
+  if (res.errcode == '0') plateList.value = res.data
+  plateList.value.unshift({ id: '-1', title: '不限', is_active: true })
+  // 技术领域
+  res = await dictDataStore.query({ code: 'field', is_use: '0' })
+  if (res.errcode == '0') typeList.value = res.data
+  typeList.value.unshift({ id: '-1', value: '-1', label: '不限', is_active: true })
+  // 状态
+  res = await dictDataStore.query({ code: 'examStatus', is_use: '0' })
+  if (res.errcode == '0') statusList.value = res.data
+}
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    // is_use: '0',
+    // status: '1',
+    ...searchForm.value
+  }
+  if (searchValue.value) info.tags = searchValue.value
+  let res = await demandStore.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+// 搜索
+const toSearchInfo = async (data) => {
+  searchForm.value = data
+  await search({ skip, limit })
+}
+const currentPage = ref(1)
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  console.log(limits)
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+// 是否展开
+const oneShow = ref(false)
+const twoShow = ref(false)
+const column = ref([
+  { name: '序号', style: { width: '100px' }, key: 'num' },
+  { name: '需方名称', style: { width: '250px' }, key: 'name' },
+  { name: '技术领域', style: { width: '185px' }, key: 'time' },
+  { name: '所在地', style: { width: '360px' }, key: 'area' },
+  { name: '投入预算', style: { width: '100px' }, key: 'money' },
+  { name: '状态', style: { width: '100px' }, key: 'status' },
+  { name: '操作', style: { width: '185px' }, key: 'operation' }
+])
+// 查看详情
+const toView = (item) => {
+  router.push({ path: '/demand/detail', query: { id: item.id || item._id } })
+}
+// 转换地区
+const getArea = (data) => {
+  if (data) return data.join('-')
+  else return '暂无'
+}
+// 字典数据转换
+const getDict = (data, model) => {
+  if (data) {
+    let res
+    if (model == 'status') res = statusList.value.find((f) => f.value == data)
+    return get(res, 'label')
+  }
+}
+const toSelect = (data, type) => {
+  if (data.is_active) {
+    toDel(data, type)
+  } else {
+    if (data.id != '-1') {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = industry.value.find((i) => i.id == data.id)
+        if (!res) industry.value.push(data)
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = field.value.find((i) => i.id == data.id)
+        if (!res) field.value.push(data)
+      } else {
+        for (const val of cityList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = city.value.find((i) => i.id == data.id)
+        if (!res) city.value.push(data)
+      }
+    } else {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        industry.value = []
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        field.value = []
+      } else {
+        for (const val of cityList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        city.value = []
+      }
+    }
+  }
+}
+const toDel = (data, type) => {
+  if (type == '1') {
+    for (const val of plateList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    industry.value = industry.value.filter((f) => f.id != data.id)
+    if (industry.value.length == 0) {
+      for (const val of plateList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '2') {
+    for (const val of typeList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    field.value = field.value.filter((f) => f.id != data.id)
+    if (field.value.length == 0) {
+      for (const val of typeList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else {
+    for (const val of cityList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    city.value = city.value.filter((f) => f.id != data.id)
+    if (city.value.length == 0) {
+      for (const val of cityList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/images/demand.png) no-repeat top center;
+  background-size: 100% 100%;
+  .active {
+    .active_1 {
+      display: inline-flex;
+      background: #f5f7f9;
+      border-radius: 2px;
+      min-height: 28px;
+      line-height: 28px;
+      margin: 10px 10px 0 0;
+      position: relative;
+      background-color: #fff;
+      padding: 10px;
+      .active_left {
+        flex: 0 0 auto;
+        font-family: PingFangSC-Regular;
+        color: #525a68;
+        line-height: 36px;
+      }
+      .active_right {
+        font-family: PingFangSC-Regular;
+        color: rgba(0, 0, 0, 0.85);
+        line-height: 28px;
+        padding-right: 4px;
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        .active_label {
+          overflow: hidden;
+          display: inline-block;
+          margin-right: 10px;
+          margin-top: 3px;
+          margin-bottom: 3px;
+          padding: 10px;
+          display: flex;
+          align-items: center;
+          flex: none;
+          box-sizing: border-box;
+          max-width: 100%;
+          height: 30px;
+          background: #f5f5f5;
+          border: 1px solid #f0f0f0;
+          border-radius: 2px;
+          cursor: default;
+        }
+      }
+    }
+  }
+  .demand {
+    padding: 10px 0;
+    .demandOne {
+      background-color: $global-color-fff;
+      .demandSeacher {
+        display: flex;
+        justify-content: center;
+        align-items: stretch;
+        position: relative;
+        border: solid 1px #e5e5e5;
+        border-bottom: 0;
+        font-size: $global-font-size-18;
+        color: #666;
+        min-height: 60px;
+        overflow: hidden;
+        .demandOneLeft {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          flex-shrink: 0;
+          width: 110px;
+          text-align: center;
+          color: #000;
+          font-weight: bold;
+          background-color: #fafafa;
+        }
+        .demandOneRight {
+          display: flex;
+          flex-wrap: wrap;
+          align-items: center;
+          padding: 12px;
+          flex: 1;
+          border-left: solid 1px #e5e5e5;
+          background-color: #fff;
+          .label {
+            margin-right: 3px;
+            color: #313131;
+            margin-bottom: 10px;
+            padding: 8px 10px;
+            border-radius: 3px;
+            background-color: #fff;
+            border: solid 1px transparent;
+            cursor: pointer;
+          }
+          .label:hover {
+            color: $global-color-107;
+          }
+          .show {
+            color: #0a58c2;
+            border: solid 1px #006dd2;
+          }
+        }
+        .button {
+          display: flex;
+          align-items: center;
+          margin: 0 5px 0 0;
+        }
+      }
+      .border {
+        border: solid 1px #e5e5e5;
+        border-bottom: 1 !important;
+      }
+    }
+    .demandIpunt {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin: 10px 0;
+      .input {
+        margin: 0 5px 0 0;
+      }
+      .button {
+        margin: 0 0 0 5px;
+      }
+    }
+    .demandTwo {
+      margin: 10px 0;
+      .demandTable {
+        display: flex;
+        justify-content: space-between;
+        color: $global-color-fff;
+        font-size: $global-font-size-20;
+        background-color: rgba(255, 255, 255, 0.1);
+        padding: 12px 0;
+        .label {
+          text-align: center;
+        }
+      }
+      .demandValue {
+        color: $global-color-fff;
+        font-size: $global-font-size-20;
+        .value {
+          display: flex;
+          justify-content: space-between;
+          padding: 12px 0;
+          .table-colunm {
+            width: 185px;
+            text-align: center;
+          }
+          .table-colunm1 {
+            width: 100px !important;
+          }
+          .table-colunm2 {
+            width: 250px !important;
+          }
+          .table-colunm3 {
+            width: 360px !important;
+          }
+          .button {
+            cursor: pointer; /* 改变鼠标样式为手形 */
+          }
+          .button:hover {
+            color: $global-color-107;
+          }
+        }
+        .value:nth-child(2n) {
+          background-color: rgba(255, 255, 255, 0.1);
+        }
+      }
+      .demandTotal {
+        display: flex;
+        justify-content: center;
+        margin: 20px 0;
+      }
+    }
+  }
+}
+</style>

+ 469 - 0
src/views/search/parts/expert.vue

@@ -0,0 +1,469 @@
+<template>
+  <div class="main">
+    <div class="w_1300">
+      <!-- <div class="active">
+        <div class="active_1" v-show="industry && industry.length > 0">
+          <div class="active_left">行业:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in industry" :key="index">
+              {{ item.title }}<el-icon @click="toDel(item, '1')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="field && field.length > 0">
+          <div class="active_left">技术领域:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in field" :key="index">
+              {{ item.label }}<el-icon @click="toDel(item, '2')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+        <div class="active_1" v-show="city && city.length > 0">
+          <div class="active_left">所在地:</div>
+          <div class="active_right">
+            <div class="active_label" v-for="(item, index) in city" :key="index">
+              {{ item.name }}<el-icon @click="toDel(item, '3')"><Close /></el-icon>
+            </div>
+          </div>
+        </div>
+      </div> -->
+      <div class="two">
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>行业</span>
+          </div>
+          <div v-if="!oneShow" class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList.slice(0, 6)" :key="index" @click="toSelect(item, '1')">
+              {{ item.title }}
+            </div>
+          </div>
+          <div v-else class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList" :key="index" @click="toSelect(item, '1')">
+              {{ item.title }}
+            </div>
+          </div>
+          <div class="button">
+            <span v-if="!oneShow" @click="oneShow = true">
+              <el-icon><ArrowDown /></el-icon>
+            </span>
+            <span v-else @click="oneShow = false">
+              <el-icon><ArrowUp /></el-icon>
+            </span>
+          </div>
+        </div>
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>技术领域</span>
+          </div>
+          <div v-if="!twoShow" class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList.slice(0, 10)" :key="index" @click="toSelect(item, '2')">
+              {{ item.label }}
+            </div>
+          </div>
+          <div v-else class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList" :key="index" @click="toSelect(item, '2')">
+              {{ item.label }}
+            </div>
+          </div>
+          <div class="button">
+            <span v-if="!twoShow" @click="twoShow = true">
+              <el-icon><ArrowDown /></el-icon>
+            </span>
+            <span v-else @click="twoShow = false">
+              <el-icon><ArrowUp /></el-icon>
+            </span>
+          </div>
+        </div>
+        <div class="twoSeacher">
+          <div class="twoLeft">
+            <span>所在地</span>
+          </div>
+          <div class="twoRight">
+            <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in cityList" :key="index" @click="toSelect(item, '3')">
+              {{ item.name }}
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="two_ipunt">
+        <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="专家名称" />
+        <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
+        <a-input class="input" size="large" v-model:value="searchForm.direction" placeholder="研究方向" />
+        <a-input class="input" size="large" v-model:value="searchForm.industry" placeholder="所属产业" />
+        <a-button class="button" size="large" type="primary" @click="toSearchInfo">检索</a-button>
+      </div>
+      <div class="twoTwo">
+        <div class="twoTable">
+          <div class="label" v-for="(item, index) in column" :key="index" :style="item.style">
+            {{ item.name }}
+          </div>
+        </div>
+        <div class="twoValue">
+          <div class="value" v-for="(item, index) in list" :key="index">
+            <div class="table-colunm table-colunm1">{{ index + 1 }}</div>
+            <div class="table-colunm textOne">{{ item.name || '暂无' }}</div>
+            <div class="table-colunm textOne table-colunm2">{{ item.work || '暂无' }}</div>
+            <div class="table-colunm textOne">{{ item.title || '暂无' }}</div>
+            <div class="table-colunm textOne">{{ item.industry || '暂无' }}</div>
+            <div class="table-colunm button" @click="toView(item)">查看详情</div>
+          </div>
+        </div>
+        <div class="twoTotal">
+          <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+const $checkRes = inject('$checkRes')
+
+// 接口
+import { ExpertStore } from '@/store/api/user/expert'
+import { RegionStore } from '@/store/api/system/region'
+import { SectorStore } from '@/store/api/platform/sector'
+import { DictDataStore } from '@/store/api/system/dictData'
+const regionStore = RegionStore()
+const sectorStore = SectorStore()
+const store = ExpertStore()
+const dictDataStore = DictDataStore()
+// 加载中
+const loading = ref(false)
+// 路由
+const router = useRouter()
+
+const searchValue = inject('searchValue')
+
+// 是否展开
+const oneShow = ref(false)
+const twoShow = ref(false)
+const cityList = ref([])
+const typeList = ref([])
+const plateList = ref([])
+const column = ref([
+  { name: '序号', style: { width: '116px' }, key: 'key' },
+  { name: '名称', style: { width: '216px' }, key: 'name' },
+  { name: '工作单位', style: { width: '316px' }, key: 'area' },
+  { name: '学历/职称', style: { width: '216px' }, key: 'education' },
+  { name: '所属产业', style: { width: '216px' }, key: 'industry' },
+  { name: '操作', style: { width: '216px' }, key: 'operation' }
+])
+// 列表
+const list = ref([])
+let skip = 0
+let limit = 15
+const total = ref(0)
+// 搜索
+const searchForm = ref({})
+// 查询
+const industry = ref([])
+const field = ref([])
+const city = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+const searchOther = async () => {
+  let result
+  // 技术领域
+  result = await dictDataStore.query({ code: 'field', is_use: '0' })
+  if ($checkRes(result)) typeList.value = result.data
+  typeList.value.unshift({ id: '-1', value: '-1', label: '不限', is_active: true })
+  result = await regionStore.list({ level: 'city', parent_code: 22 })
+  if ($checkRes(result)) cityList.value = result.data
+  cityList.value.unshift({ id: '-1', code: '-1', name: '不限', is_active: true })
+  result = await sectorStore.query({ is_use: '0' })
+  if ($checkRes(result)) plateList.value = result.data
+  plateList.value.unshift({ id: '-1', title: '不限', is_active: true })
+}
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    ...searchForm.value
+  }
+  if (searchValue.value) info.tags = searchValue.value
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+// 搜索
+const toSearchInfo = async () => {
+  await search({ skip, limit })
+}
+// 查看
+const toView = (item) => {
+  router.push({ path: `/expert/detail`, query: { id: item.id || item._id } })
+}
+const currentPage = ref(1)
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+const toSelect = (data, type) => {
+  if (data.is_active) {
+    toDel(data, type)
+  } else {
+    if (data.id != '-1') {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = industry.value.find((i) => i.id == data.id)
+        if (!res) industry.value.push(data)
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = field.value.find((i) => i.id == data.id)
+        if (!res) field.value.push(data)
+      } else {
+        for (const val of cityList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = city.value.find((i) => i.id == data.id)
+        if (!res) city.value.push(data)
+      }
+    } else {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        industry.value = []
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        field.value = []
+      } else {
+        for (const val of cityList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        city.value = []
+      }
+    }
+  }
+}
+const toDel = (data, type) => {
+  if (type == '1') {
+    for (const val of plateList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    industry.value = industry.value.filter((f) => f.id != data.id)
+    if (industry.value.length == 0) {
+      for (const val of plateList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '2') {
+    for (const val of typeList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    field.value = field.value.filter((f) => f.id != data.id)
+    if (field.value.length == 0) {
+      for (const val of typeList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else {
+    for (const val of cityList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    city.value = city.value.filter((f) => f.id != data.id)
+    if (city.value.length == 0) {
+      for (const val of cityList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/images/information.jpg) no-repeat top center;
+  background-size: 100% 100%;
+  padding: 20px 0;
+  .active {
+    .active_1 {
+      display: inline-flex;
+      background: #f5f7f9;
+      border-radius: 2px;
+      min-height: 28px;
+      line-height: 28px;
+      margin: 10px 10px 0 0;
+      position: relative;
+      background-color: #fff;
+      padding: 10px;
+      .active_left {
+        flex: 0 0 auto;
+        font-family: PingFangSC-Regular;
+        color: #525a68;
+        line-height: 36px;
+      }
+      .active_right {
+        font-family: PingFangSC-Regular;
+        color: rgba(0, 0, 0, 0.85);
+        line-height: 28px;
+        padding-right: 4px;
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        .active_label {
+          overflow: hidden;
+          display: inline-block;
+          margin-right: 10px;
+          margin-top: 3px;
+          margin-bottom: 3px;
+          padding: 10px;
+          display: flex;
+          align-items: center;
+          flex: none;
+          box-sizing: border-box;
+          max-width: 100%;
+          height: 30px;
+          background: #f5f5f5;
+          border: 1px solid #f0f0f0;
+          border-radius: 2px;
+          cursor: default;
+        }
+      }
+    }
+  }
+  .two {
+    padding: 10px 0;
+    background-color: $global-color-fff;
+    .twoSeacher {
+      display: flex;
+      justify-content: center;
+      align-items: stretch;
+      position: relative;
+      border: solid 1px #e5e5e5;
+      border-bottom: 0;
+      font-size: $global-font-size-18;
+      color: #666;
+      min-height: 60px;
+      overflow: hidden;
+      .twoLeft {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        flex-shrink: 0;
+        width: 110px;
+        text-align: center;
+        color: #000;
+        font-weight: bold;
+        background-color: #fafafa;
+      }
+      .twoRight {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        padding: 12px;
+        flex: 1;
+        border-left: solid 1px #e5e5e5;
+        background-color: #fff;
+        .label {
+          margin-right: 3px;
+          color: #313131;
+          margin-bottom: 10px;
+          padding: 8px 10px;
+          border-radius: 3px;
+          background-color: #fff;
+          border: solid 1px transparent;
+          cursor: pointer;
+        }
+        .show {
+          color: #0a58c2;
+          border: solid 1px #006dd2;
+        }
+        .label:hover {
+          color: $global-color-107;
+        }
+      }
+      .button {
+        display: flex;
+        align-items: center;
+        margin: 0 5px 0 0;
+      }
+    }
+  }
+  .two_ipunt {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin: 10px 0;
+    .input {
+      margin: 0 5px 0 0;
+    }
+    .button {
+      margin: 0 0 0 5px;
+    }
+  }
+  .twoTwo {
+    margin: 10px 0;
+    .twoTable {
+      display: flex;
+      justify-content: space-between;
+      color: $global-color-fff;
+      font-size: $global-font-size-20;
+      background-color: rgba(255, 255, 255, 0.1);
+      padding: 12px 0;
+      .label {
+        text-align: center;
+      }
+    }
+    .twoValue {
+      color: $global-color-fff;
+      font-size: $global-font-size-20;
+      .value {
+        display: flex;
+        justify-content: space-between;
+        padding: 12px 0;
+        .table-colunm {
+          width: 216px;
+          text-align: center;
+        }
+        .table-colunm1 {
+          width: 116px !important;
+        }
+        .table-colunm2 {
+          width: 316px !important;
+        }
+        .button {
+          cursor: pointer; /* 改变鼠标样式为手形 */
+        }
+        .button:hover {
+          color: $global-color-107;
+        }
+      }
+      .value:nth-child(2n) {
+        background-color: rgba(255, 255, 255, 0.1);
+      }
+    }
+    .twoTotal {
+      display: flex;
+      justify-content: center;
+      margin: 20px 0;
+    }
+  }
+}
+</style>

+ 409 - 0
src/views/search/parts/project.vue

@@ -0,0 +1,409 @@
+<template>
+  <div class="main">
+    <el-col :span="24" class="one">
+      <div class="w_1300">
+        <el-col :span="24" class="one_2">
+          <div class="one_2_1">
+            <div class="Seacher">
+              <div class="OneLeft">
+                <span>行业</span>
+              </div>
+              <div v-if="!twoShow" class="OneRight">
+                <el-checkbox class="label" @change="oneChange" v-for="(item, index) in plateList.slice(0, 5)" :key="index" v-model="checked1" :label="item.title" size="large" />
+              </div>
+              <div v-else class="OneRight">
+                <el-checkbox class="label" @change="oneChange" v-for="(item, index) in plateList" :key="index" v-model="checked1" :label="item.title" size="large" />
+              </div>
+              <div class="button">
+                <span v-if="!twoShow" @click="twoShow = true">
+                  <el-icon><ArrowDown /></el-icon>
+                </span>
+                <span v-else @click="twoShow = false">
+                  <el-icon><ArrowUp /></el-icon>
+                </span>
+              </div>
+            </div>
+            <div class="Seacher">
+              <div class="OneLeft">
+                <span>技术领域</span>
+              </div>
+              <div v-if="!oneShow" class="OneRight">
+                <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" />
+              </div>
+              <div v-else class="OneRight">
+                <el-checkbox class="label" @change="oneChange" v-for="(item, index) in typeList" :key="index" v-model="checked2" :label="item.label" size="large" />
+              </div>
+              <div class="button">
+                <span v-if="!oneShow" @click="oneShow = true">
+                  <el-icon><ArrowDown /></el-icon>
+                </span>
+                <span v-else @click="oneShow = false">
+                  <el-icon><ArrowUp /></el-icon>
+                </span>
+              </div>
+            </div>
+            <div class="Seacher">
+              <div class="OneLeft">
+                <span>所在地</span>
+              </div>
+              <div class="OneRight">
+                <el-checkbox class="label" @change="oneChange" v-for="(item, index) in cityList" :key="index" v-model="checked3" :label="item.name" size="large" />
+              </div>
+            </div>
+            <div class="Seacher">
+              <div class="OneLeft">
+                <span>项目成熟度</span>
+              </div>
+              <div class="OneRight">
+                <el-checkbox class="label" @change="oneChange" v-for="(item, index) in maturityList" :key="index" v-model="checked4" :label="item.label" size="large" />
+              </div>
+            </div>
+            <div class="one_ipunt">
+              <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="项目名称" />
+              <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
+              <a-input class="input" size="large" v-model:value="searchForm.source" placeholder="项目来源" />
+              <a-input class="input" size="large" v-model:value="searchForm.industry" placeholder="所属产业" />
+              <a-button class="button" size="large" type="primary" @click="toSearchInfo">检索</a-button>
+            </div>
+          </div>
+          <div class="one_2_2">
+            <div class="list" :class="['list' + index]" v-for="(item, index) in list" :key="index" @click="toView(item)">
+              <div class="type textOne">{{ item.industry || '暂无' }}</div>
+              <div class="title">
+                <p class="ellipsis-3">{{ item.name || '暂无' }}</p>
+              </div>
+              <div class="address">
+                <el-icon color="#595959"><Location /></el-icon>
+                <span class="textOne">{{ item.main || '暂无' }}</span>
+              </div>
+              <div class="biaoqian textOne">
+                <span v-if="item.technology">{{ item.technology }}</span>
+                <span v-if="item.sell">{{ item.sell }}</span>
+              </div>
+              <span class="state" :class="['state1']"></span>
+            </div>
+          </div>
+          <div class="one_2_3">
+            <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+          </div>
+        </el-col>
+      </div>
+    </el-col>
+  </div>
+</template>
+
+<script setup>
+const $checkRes = inject('$checkRes')
+// 接口
+import { ProjectStore } from '@/store/api/platform/project'
+import { DictDataStore } from '@/store/api/system/dictData'
+import { RegionStore } from '@/store/api/system/region'
+import { SectorStore } from '@/store/api/platform/sector'
+const store = ProjectStore()
+const dictDataStore = DictDataStore()
+const regionStore = RegionStore()
+const sectorStore = SectorStore()
+// 路由
+const router = useRouter()
+
+const searchValue = inject('searchValue')
+
+// 是否展开
+const twoShow = ref(false)
+const oneShow = ref(false)
+// 加载中
+const loading = ref(false)
+const checked1 = ref([])
+const checked2 = ref([])
+const checked3 = ref([])
+const checked4 = ref([])
+const typeList = ref([])
+const plateList = ref([])
+// 字典表
+const maturityList = ref([])
+const cityList = ref([])
+// 列表
+const list = ref([])
+let skip = 0
+let limit = 15
+const total = ref(0)
+// 搜索
+const searchForm = ref({})
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+const searchOther = async () => {
+  let result
+  // // 合作类型
+  // result = await dictDataStore.query({ code: 'projectType', is_use: '0' })
+  // if ($checkRes(result)) projectList.value = result.data
+  // 成熟度
+  result = await dictDataStore.query({ code: 'projectMaturity', is_use: '0' })
+  if ($checkRes(result)) maturityList.value = result.data
+  maturityList.value.unshift({ value: '-1', label: '不限' })
+  // // 行业分类
+  // result = await dictDataStore.query({ code: 'industry', is_use: '0' })
+  // if ($checkRes(result)) industryList.value = result.data
+  // 技术领域
+  result = await dictDataStore.query({ code: 'field', is_use: '0' })
+  if ($checkRes(result)) typeList.value = result.data
+  typeList.value.unshift({ value: '-1', label: '不限' })
+  // 地区
+  result = await regionStore.list({ level: 'city', parent_code: 22 })
+  if ($checkRes(result)) cityList.value = result.data
+  cityList.value.unshift({ code: '-1', name: '不限' })
+  // 行业
+  result = await sectorStore.query({ is_use: '0' })
+  if ($checkRes(result)) plateList.value = result.data
+  plateList.value.unshift({ id: '-1', title: '不限' })
+}
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    ...searchForm.value
+  }
+  if (searchValue.value) info.tags = searchValue.value
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+// 搜索
+const toSearchInfo = async () => {
+  await search({ skip, limit })
+}
+// 查看
+const toView = (item) => {
+  router.push({ path: `/project/detail`, query: { id: item.id || item._id } })
+}
+const currentPage = ref(1)
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+// 选择
+const oneChange = (value) => {
+  console.log('1', checked1.value)
+  console.log('2', checked2.value)
+  console.log('3', checked3.value)
+  console.log('4', checked4.value)
+}
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    padding: 20px 0 0 0;
+    background: url(/images/bg-tec-list.jpg) no-repeat;
+    .one_1 {
+      padding: 85px 0 0;
+      .search {
+        margin: 0 auto;
+        width: 810px;
+        :deep(.el-input--large .el-input__inner) {
+          height: 60px;
+        }
+      }
+    }
+    .one_2 {
+      padding: 30px;
+      background-color: $global-color-fff;
+      .one_2_1 {
+        .Seacher {
+          display: flex;
+          justify-content: center;
+          align-items: stretch;
+          position: relative;
+          margin-bottom: 15px;
+          .OneLeft {
+            width: 134px;
+            height: 36px;
+            background-color: #f5f8ff;
+            border-radius: 21px;
+            font-size: $global-font-size-16;
+            font-weight: bold;
+            color: #000000;
+            flex-shrink: 0;
+            line-height: 36px;
+            text-align: center;
+          }
+          .OneRight {
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            padding: 0 12px;
+            flex: 1;
+            background-color: #fff;
+            .label {
+              cursor: pointer;
+            }
+            .label:hover {
+              color: $global-color-107;
+            }
+          }
+          .button {
+            display: flex;
+            align-items: center;
+            margin: 0 5px 0 0;
+          }
+        }
+        .one_ipunt {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          margin: 10px 0;
+          .input {
+            margin: 0 5px 0 0;
+          }
+          .button {
+            margin: 0 0 0 5px;
+          }
+        }
+      }
+      .one_2_2 {
+        margin: 20px 0;
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: center;
+        align-items: center;
+        .list {
+          position: relative;
+          margin: 0 39px 39px 0;
+          width: 208px;
+          height: 286px;
+          box-shadow: 3px 4px 4px 0px rgba(41, 41, 115, 0.32);
+          border: solid 1px #ededed;
+          .type {
+            margin-left: 33px;
+            padding: 22px 10px 0 0;
+            font-size: $global-font-size-16;
+            color: #414141;
+          }
+          .title {
+            display: flex;
+            align-items: center;
+            margin: 24px 18px 0;
+            height: 100px;
+            font-size: $global-font-size-18;
+            font-weight: bold;
+            color: #ffffff;
+            .ellipsis-3 {
+              display: -webkit-box;
+              -webkit-box-orient: vertical;
+              overflow: hidden;
+              -webkit-line-clamp: 3;
+            }
+          }
+          .address {
+            margin-top: 80px;
+            padding: 0 5px;
+            font-size: $global-font-size-16;
+            color: #282828;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+          }
+          .biaoqian {
+            margin: 10px 5px 0 5px;
+            text-align: right;
+            overflow: hidden;
+            span {
+              padding: 0 5px;
+              background-color: #f5f8ff;
+              border-radius: 3px;
+              border: solid 1px #d2daec;
+              font-size: $global-font-size-14;
+              line-height: 23px;
+              color: #7d8aaa;
+              margin-right: 2px;
+            }
+          }
+        }
+        .state {
+          display: block;
+          position: absolute;
+          right: 0px;
+          top: 0px;
+          width: 75px;
+          height: 24px;
+          background: url(/images/project/dbhi-kcxm-item-xmyl.png) no-repeat;
+        }
+        .state1 {
+          background: url(/images/project/dbhi-kcxm-item-xm1.png) no-repeat;
+        }
+        .state2 {
+          background: url(/images/project/dbhi-kcxm-item-xm2.png) no-repeat;
+        }
+        .state3 {
+          background: url(/images/project/dbhi-kcxm-item-xm3.png) no-repeat;
+        }
+        .list0 {
+          background: url(/images/project/dbhi-kcxm-item1.png) no-repeat;
+        }
+        .list1 {
+          background: url(/images/project/dbhi-kcxm-item2.png) no-repeat;
+        }
+        .list2 {
+          background: url(/images/project/dbhi-kcxm-item3.png) no-repeat;
+        }
+        .list3 {
+          background: url(/images/project/dbhi-kcxm-item4.png) no-repeat;
+        }
+        .list4 {
+          background: url(/images/project/dbhi-kcxm-item5.png) no-repeat;
+        }
+        .list5 {
+          background: url(/images/project/dbhi-kcxm-item6.png) no-repeat;
+        }
+        .list6 {
+          background: url(/images/project/dbhi-kcxm-item7.png) no-repeat;
+        }
+        .list7 {
+          background: url(/images/project/dbhi-kcxm-item8.png) no-repeat;
+        }
+        .list8 {
+          background: url(/images/project/dbhi-kcxm-item9.png) no-repeat;
+        }
+        .list9 {
+          background: url(/images/project/dbhi-kcxm-item10.png) no-repeat;
+        }
+        .list10 {
+          background: url(/images/project/dbhi-kcxm-item1.png) no-repeat;
+        }
+        .list11 {
+          background: url(/images/project/dbhi-kcxm-item2.png) no-repeat;
+        }
+        .list12 {
+          background: url(/images/project/dbhi-kcxm-item3.png) no-repeat;
+        }
+        .list13 {
+          background: url(/images/project/dbhi-kcxm-item4.png) no-repeat;
+        }
+        .list14 {
+          background: url(/images/project/dbhi-kcxm-item5.png) no-repeat;
+        }
+        .list:nth-child(5n) {
+          margin-right: 0;
+        }
+      }
+      .one_2_3 {
+        display: flex;
+        justify-content: center;
+        margin: 20px 0;
+      }
+    }
+  }
+}
+</style>

+ 487 - 0
src/views/search/parts/supply.vue

@@ -0,0 +1,487 @@
+<template>
+  <div class="main">
+    <div class="w_1300">
+      <!-- <div class="active">
+    <div class="active_1" v-show="industry && industry.length > 0">
+      <div class="active_left">行业:</div>
+      <div class="active_right">
+        <div class="active_label" v-for="(item, index) in industry" :key="index">
+          {{ item.title }}<el-icon @click="toDel(item, '1')"><Close /></el-icon>
+        </div>
+      </div>
+    </div>
+    <div class="active_1" v-show="field && field.length > 0">
+      <div class="active_left">技术领域:</div>
+      <div class="active_right">
+        <div class="active_label" v-for="(item, index) in field" :key="index">
+          {{ item.label }}<el-icon @click="toDel(item, '2')"><Close /></el-icon>
+        </div>
+      </div>
+    </div>
+    <div class="active_1" v-show="city && city.length > 0">
+      <div class="active_left">所在地:</div>
+      <div class="active_right">
+        <div class="active_label" v-for="(item, index) in city" :key="index">
+          {{ item.name }}<el-icon @click="toDel(item, '3')"><Close /></el-icon>
+        </div>
+      </div>
+    </div>
+  </div> -->
+      <div class="demand">
+        <div class="demandOne">
+          <div class="demandSeacher">
+            <div class="demandOneLeft">
+              <span>行业</span>
+            </div>
+            <div v-if="!oneShow" class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList.slice(0, 6)" :key="index" @click="toSelect(item, '1')">
+                {{ item.title }}
+              </div>
+            </div>
+            <div v-else class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in plateList" :key="index" @click="toSelect(item, '1')">
+                {{ item.title }}
+              </div>
+            </div>
+            <div class="button">
+              <span v-if="!oneShow" @click="oneShow = true">
+                <el-icon><ArrowDown /></el-icon>
+              </span>
+              <span v-else @click="oneShow = false">
+                <el-icon><ArrowUp /></el-icon>
+              </span>
+            </div>
+          </div>
+          <div class="demandSeacher">
+            <div class="demandOneLeft">
+              <span>技术领域</span>
+            </div>
+            <div v-if="!twoShow" class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList.slice(0, 10)" :key="index" @click="toSelect(item, '2')">
+                {{ item.label }}
+              </div>
+            </div>
+            <div v-else class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in typeList" :key="index" @click="toSelect(item, '2')">
+                {{ item.label }}
+              </div>
+            </div>
+            <div class="button">
+              <span v-if="!twoShow" @click="twoShow = true">
+                <el-icon><ArrowDown /></el-icon>
+              </span>
+              <span v-else @click="twoShow = false">
+                <el-icon><ArrowUp /></el-icon>
+              </span>
+            </div>
+          </div>
+          <div class="demandSeacher border">
+            <div class="demandOneLeft">
+              <span>所在地</span>
+            </div>
+            <div class="demandOneRight">
+              <div class="label" :class="[item.is_active ? 'show' : '']" v-for="(item, index) in cityList" :key="index" @click="toSelect(item, '3')">
+                {{ item.name }}
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="demandIpunt">
+          <a-input class="input" size="large" v-model:value="searchForm.name" placeholder="供应名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.tags" placeholder="标签名称" />
+          <a-input class="input" size="large" v-model:value="searchForm.industry" placeholder="所属产业" />
+          <a-input class="input" size="large" v-model:value="searchForm.source" placeholder="所属来源" />
+          <a-button class="button" size="large" type="primary" @click="toSearchInfo(searchForm, '1')">检索</a-button>
+        </div>
+        <div class="demandTwo">
+          <div class="demandTable">
+            <div class="label" v-for="(item, index) in column" :key="index" :style="item.style">
+              {{ item.name }}
+            </div>
+          </div>
+          <div class="demandValue">
+            <div class="value" v-for="(item, index) in list" :key="index">
+              <div class="table-colunm table-colunm1 textOne">{{ index + 1 }}</div>
+              <div class="table-colunm table-colunm2 textOne">{{ item.name || '暂无' }}</div>
+              <div class="table-colunm textOne">{{ item.field || '暂无' }}</div>
+              <div class="table-colunm table-colunm4 textOne">{{ item.industry || '暂无' }}</div>
+              <!-- <div class="table-colunm">{{ item.status || '暂无' }}</div> -->
+              <div class="table-colunm table-colunm3 textOne">{{ item.source || '暂无' }}</div>
+              <div class="table-colunm textOne table-colunm3 button" @click="toView(item)">查看详情</div>
+            </div>
+          </div>
+          <div class="demandTotal">
+            <el-pagination background layout="prev, pager, next" :total="total" :page-size="limit" v-model:current-page="currentPage" @current-change="changePage" @size-change="sizeChange" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup>
+import { SupplyStore } from '@/store/api/platform/supply'
+import { RegionStore } from '@/store/api/system/region'
+import { SectorStore } from '@/store/api/platform/sector'
+import { DictDataStore } from '@/store/api/system/dictData'
+const regionStore = RegionStore()
+const sectorStore = SectorStore()
+const supplyStore = SupplyStore()
+const dictDataStore = DictDataStore()
+
+const router = useRouter()
+
+const searchValue = inject('searchValue')
+
+// 加载中
+const loading = ref(false)
+// 字典表
+const cityList = ref([])
+const typeList = ref([])
+const plateList = ref([])
+const statusList = ref([])
+// 列表
+const list = ref([])
+let skip = 0
+let limit = inject('limit')
+const total = ref(0)
+const searchForm = ref({})
+// 查询
+const industry = ref([])
+const field = ref([])
+const city = ref([])
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+const searchOther = async () => {
+  let res
+  res = await regionStore.list({ level: 'city', parent_code: 22 })
+  if (res.errcode == '0') cityList.value = res.data
+  cityList.value.unshift({ id: '-1', code: '-1', name: '不限', is_active: true })
+  res = await sectorStore.query({ is_use: '0' })
+  if (res.errcode == '0') plateList.value = res.data
+  plateList.value.unshift({ id: '-1', title: '不限', is_active: true })
+  // 技术领域
+  res = await dictDataStore.query({ code: 'field', is_use: '0' })
+  if (res.errcode == '0') typeList.value = res.data
+  typeList.value.unshift({ id: '-1', value: '-1', label: '不限', is_active: true })
+  // 状态
+  res = await dictDataStore.query({ code: 'examStatus', is_use: '0' })
+  if (res.errcode == '0') statusList.value = res.data
+}
+const search = async (query = { skip, limit }) => {
+  skip = query.skip
+  limit = query.limit
+  const info = {
+    skip: query.skip,
+    limit: query.limit,
+    // is_use: '0',
+    // status: '1',
+    ...searchForm.value
+  }
+  if (searchValue.value) info.tags = searchValue.value
+  let res = await supplyStore.query(info)
+  if (res.errcode == '0') {
+    list.value = res.data
+    total.value = res.total
+  }
+}
+// 搜索
+const toSearchInfo = async (data) => {
+  searchForm.value = data
+  await search({ skip, limit })
+}
+const currentPage = ref(1)
+// 分页
+const changePage = (page = currentPage.value) => {
+  search({ skip: (page - 1) * limit, limit: limit })
+}
+const sizeChange = (limits) => {
+  console.log(limits)
+  limit = limits
+  currentPage.value = 1
+  search({ skip: 0, limit: limit })
+}
+// 是否展开
+const oneShow = ref(false)
+const twoShow = ref(false)
+const column = ref([
+  { name: '序号', style: { width: '100px' }, key: 'num' },
+  { name: '供方内容', style: { width: '320px' }, key: 'name' },
+  { name: '技术领域', style: { width: '220px' }, key: 'field' },
+  { name: '所属产业', style: { width: '240px' }, key: 'industry' },
+  { name: '来源', style: { width: '200px' }, key: 'source' },
+  { name: '操作', style: { width: '200px' }, key: 'operation' }
+])
+// 查看详情
+const toView = (item) => {
+  router.push({ path: '/supply/detail', query: { id: item.id || item._id } })
+}
+const toSelect = (data, type) => {
+  if (data.is_active) {
+    toDel(data, type)
+  } else {
+    if (data.id != '-1') {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = industry.value.find((i) => i.id == data.id)
+        if (!res) industry.value.push(data)
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = field.value.find((i) => i.id == data.id)
+        if (!res) field.value.push(data)
+      } else {
+        for (const val of cityList.value) {
+          if (data.id == val.id) val.is_active = true
+          if (val.id == '-1') val.is_active = false
+        }
+        const res = city.value.find((i) => i.id == data.id)
+        if (!res) city.value.push(data)
+      }
+    } else {
+      if (type == '1') {
+        for (const val of plateList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        industry.value = []
+      } else if (type == '2') {
+        for (const val of typeList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        field.value = []
+      } else {
+        for (const val of cityList.value) {
+          if (val.id == '-1') val.is_active = true
+          else val.is_active = false
+        }
+        city.value = []
+      }
+    }
+  }
+}
+const toDel = (data, type) => {
+  if (type == '1') {
+    for (const val of plateList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    industry.value = industry.value.filter((f) => f.id != data.id)
+    if (industry.value.length == 0) {
+      for (const val of plateList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else if (type == '2') {
+    for (const val of typeList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    field.value = field.value.filter((f) => f.id != data.id)
+    if (field.value.length == 0) {
+      for (const val of typeList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  } else {
+    for (const val of cityList.value) {
+      if (data.id == val.id) val.is_active = false
+    }
+    city.value = city.value.filter((f) => f.id != data.id)
+    if (city.value.length == 0) {
+      for (const val of cityList.value) {
+        if (val.id == '-1') val.is_active = true
+      }
+    }
+  }
+}
+</script>
+<style scoped lang="scss">
+.main {
+  background: url(/images/demand.png) no-repeat top center;
+  background-size: 100% 100%;
+  .active {
+    .active_1 {
+      display: inline-flex;
+      background: #f5f7f9;
+      border-radius: 2px;
+      min-height: 28px;
+      line-height: 28px;
+      margin: 10px 10px 0 0;
+      position: relative;
+      background-color: #fff;
+      padding: 10px;
+      .active_left {
+        flex: 0 0 auto;
+        font-family: PingFangSC-Regular;
+        color: #525a68;
+        line-height: 36px;
+      }
+      .active_right {
+        font-family: PingFangSC-Regular;
+        color: rgba(0, 0, 0, 0.85);
+        line-height: 28px;
+        padding-right: 4px;
+        display: flex;
+        flex-wrap: wrap;
+        overflow: hidden;
+        .active_label {
+          overflow: hidden;
+          display: inline-block;
+          margin-right: 10px;
+          margin-top: 3px;
+          margin-bottom: 3px;
+          padding: 10px;
+          display: flex;
+          align-items: center;
+          flex: none;
+          box-sizing: border-box;
+          max-width: 100%;
+          height: 30px;
+          background: #f5f5f5;
+          border: 1px solid #f0f0f0;
+          border-radius: 2px;
+          cursor: default;
+        }
+      }
+    }
+  }
+  .demand {
+    padding: 10px 0;
+    .demandOne {
+      background-color: $global-color-fff;
+      .demandSeacher {
+        display: flex;
+        justify-content: center;
+        align-items: stretch;
+        position: relative;
+        border: solid 1px #e5e5e5;
+        border-bottom: 0;
+        font-size: $global-font-size-18;
+        color: #666;
+        min-height: 60px;
+        overflow: hidden;
+        .demandOneLeft {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          flex-shrink: 0;
+          width: 110px;
+          text-align: center;
+          color: #000;
+          font-weight: bold;
+          background-color: #fafafa;
+        }
+        .demandOneRight {
+          display: flex;
+          flex-wrap: wrap;
+          align-items: center;
+          padding: 12px;
+          flex: 1;
+          border-left: solid 1px #e5e5e5;
+          background-color: #fff;
+          .label {
+            margin-right: 3px;
+            color: #313131;
+            margin-bottom: 10px;
+            padding: 8px 10px;
+            border-radius: 3px;
+            background-color: #fff;
+            border: solid 1px transparent;
+            cursor: pointer;
+          }
+          .label:hover {
+            color: $global-color-107;
+          }
+          .show {
+            color: #0a58c2;
+            border: solid 1px #006dd2;
+          }
+        }
+        .button {
+          display: flex;
+          align-items: center;
+          margin: 0 5px 0 0;
+        }
+      }
+      .border {
+        border: solid 1px #e5e5e5;
+        border-bottom: 1 !important;
+      }
+    }
+    .demandIpunt {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin: 10px 0;
+      .input {
+        margin: 0 5px 0 0;
+      }
+      .button {
+        margin: 0 0 0 5px;
+      }
+    }
+    .demandTwo {
+      margin: 10px 0;
+      .demandTable {
+        display: flex;
+        justify-content: space-between;
+        color: $global-color-fff;
+        font-size: $global-font-size-20;
+        background-color: rgba(255, 255, 255, 0.1);
+        padding: 12px 0;
+        .label {
+          text-align: center;
+        }
+      }
+      .demandValue {
+        color: $global-color-fff;
+        font-size: $global-font-size-20;
+        .value {
+          display: flex;
+          justify-content: space-between;
+          padding: 12px 0;
+          .table-colunm {
+            width: 220px;
+            text-align: center;
+          }
+          .table-colunm1 {
+            width: 100px !important;
+          }
+          .table-colunm2 {
+            width: 320px !important;
+          }
+          .table-colunm3 {
+            width: 200px !important;
+          }
+          .table-colunm4 {
+            width: 240px !important;
+          }
+          .button {
+            cursor: pointer; /* 改变鼠标样式为手形 */
+          }
+          .button:hover {
+            color: $global-color-107;
+          }
+        }
+        .value:nth-child(2n) {
+          background-color: rgba(255, 255, 255, 0.1);
+        }
+      }
+      .demandTotal {
+        display: flex;
+        justify-content: center;
+        margin: 20px 0;
+      }
+    }
+  }
+}
+</style>

+ 0 - 7
src/views/two/parts/demand.vue

@@ -4,37 +4,30 @@
       <el-form-item label="需求名称" prop="name">
         <el-input size="large" clearable v-model="form.name" placeholder="请输入需求名称"> </el-input>
       </el-form-item>
-
       <el-form-item label="行业领域" prop="field">
         <el-select size="large" v-model="form.field" clearable placeholder="请选择行业领域">
           <el-option v-for="(item, index) in fieldList" :key="index" :label="item.label" :value="item.value" />
         </el-select>
       </el-form-item>
-
       <el-form-item label="需求紧急度" prop="urgent">
         <el-select size="large" v-model="form.urgent" clearable placeholder="请选择需求紧急度">
           <el-option v-for="(item, index) in urgentList" :key="index" :label="item.label" :value="item.value" />
         </el-select>
       </el-form-item>
-
       <el-form-item label="合作方式" prop="method">
         <el-select size="large" v-model="form.method" clearable placeholder="请选择合作方式">
           <el-option v-for="(item, index) in methodList" :key="index" :label="item.label" :value="item.value" />
         </el-select>
       </el-form-item>
-
       <el-form-item label="价格(万元)" prop="money">
         <el-input size="large" clearable v-model="form.money" placeholder="请输入价格(万元)"> </el-input>
       </el-form-item>
-
       <el-form-item label="需求地区" prop="area">
         <el-cascader size="large" v-model="form.area" :props="{ value: 'name', label: 'name' }" :options="cityList" style="width: 100%" />
       </el-form-item>
-
       <el-form-item label="有效期" prop="time">
         <el-date-picker size="large" v-model="form.time" type="daterange" format="YYYY-MM-DD" value-format="YYYY-MM-DD" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
       </el-form-item>
-
       <el-form-item label="是否启用" prop="is_use">
         <el-radio-group v-model="form.is_use">
           <el-radio v-for="(item, index) in isUseList" :key="index" :value="item.value">{{ item.label }}</el-radio>

+ 0 - 4
src/views/two/parts/supply.vue

@@ -9,7 +9,6 @@
           <el-option v-for="(item, index) in fieldList" :key="index" :label="item.label" :value="item.value" />
         </el-select>
       </el-form-item>
-
       <el-form-item label="供应紧急度" prop="urgent">
         <el-select size="large" v-model="form.urgent" clearable placeholder="请选择供应紧急度">
           <el-option v-for="(item, index) in urgentList" :key="index" :label="item.label" :value="item.value" />
@@ -20,15 +19,12 @@
           <el-option v-for="(item, index) in methodList" :key="index" :label="item.label" :value="item.value" />
         </el-select>
       </el-form-item>
-
       <el-form-item label="价格(万元)" prop="money">
         <el-input size="large" clearable v-model="form.money" placeholder="请输入价格(万元)"> </el-input>
       </el-form-item>
-
       <el-form-item label="供应地区" prop="area">
         <el-cascader size="large" v-model="form.area" :props="{ value: 'name', label: 'name' }" :options="cityList" style="width: 100%" />
       </el-form-item>
-
       <el-form-item label="有效期" prop="time">
         <el-date-picker size="large" v-model="form.time" type="daterange" format="YYYY-MM-DD" value-format="YYYY-MM-DD" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
       </el-form-item>