zs 8 mesiacov pred
rodič
commit
171a86bac5

+ 432 - 0
src/components/custom/custom-layout copy.vue

@@ -0,0 +1,432 @@
+<template>
+  <div id="c-layout">
+    <div class="header">
+      <el-col :span="24" class="header_1">
+        <div class="left">
+          <el-image class="image" v-if="configInfo && configInfo.logoUrl && configInfo.logoUrl.length > 0" :src="getUrl(configInfo.logoUrl)" fit="fill" />
+          <el-image class="image" v-else :src="siteInfo.logoUrl" fit="fill" />
+          <div class="content">
+            <text class="title">{{ configInfo.zhTitle || siteInfo.zhTitle }}</text>
+          </div>
+        </div>
+        <div class="right">
+          <div class="right_1" v-if="user && user.id">
+            <el-dropdown>
+              <span class="el-dropdown-link">
+                {{ user.nick_name || '暂无昵称' }}
+                <el-icon class="el-icon--right">
+                  <arrow-down />
+                </el-icon>
+              </span>
+              <template #dropdown>
+                <el-dropdown-menu>
+                  <el-dropdown-item @click="toCenter"> 个人中心 </el-dropdown-item>
+                  <el-dropdown-item @click="toOut"> 退出登录 </el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </div>
+          <div class="right_1" v-else>
+            <span @click="toLogin('0')">注册</span>
+            <span>|</span>
+            <span @click="toLogin('1')">登录</span>
+          </div>
+          <div class="right_2" @click="toChat">
+            <el-icon><Bell /></el-icon>
+            <span>消息</span>
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="24" class="header_2">
+        <el-col :span="24" class="list">
+          <div
+            class="text"
+            v-for="(item, index) in data"
+            @click="selectMenu(item.route)"
+            :style="{
+              backgroundColor: item.hover ? '#1073ff' : 'transparent',
+              color: item.hover ? '#ffffff' : ''
+            }"
+            :key="index"
+            @mouseover="handleMouseOver(index)"
+            @mouseout="handleMousOut(index)"
+          >
+            <span>{{ item.title }}</span>
+          </div>
+        </el-col>
+        <el-col :span="24" class="info">
+          <!-- <div class="info_1" v-if="info.key == '3'">
+            <el-col :span="12" class="list_1" v-for="(agg, index) in info.children" :key="index">
+              <div class="title">{{ agg.title }}</div>
+              <div class="list_1_1">
+                <div v-for="(tag, indexs) in agg.children" :key="indexs" class="title1" @click="selectMenu(tag.route)">
+                  {{ tag.title }}
+                </div>
+              </div>
+            </el-col>
+          </div> -->
+          <!-- <div class="info_2" :class="[user && user.id && isIncubator ? 'info_3' : '']" v-if="info.key == '10'">
+            <el-col :span="24" class="list_2">
+              <div v-for="(tag, indexs) in info.children" :key="indexs" class="title1" @click="selectMenu(tag.route)">
+                {{ tag.title }}
+              </div>
+            </el-col>
+          </div> -->
+          <div class="info_4" v-if="info.key == '10'">
+            <div class="w_1300 list4">
+              <div v-for="(tag, indexs) in info.children" :key="indexs" class="list_1" @click="selectMenu(tag.route)">
+                <el-image class="image" :src="tag.url" fit="fill" />
+                <span class="title"> {{ tag.title }}</span>
+              </div>
+            </div>
+          </div>
+        </el-col>
+      </el-col>
+    </div>
+    <div class="main">
+      <slot></slot>
+    </div>
+    <div class="footer" v-if="is_foot">
+      <div class="footer_1">
+        <div class="left">
+          <el-image class="image" v-if="footInfos && footInfos.Logo && footInfos.Logo.length > 0" :src="getUrl(footInfos.Logo)" fit="fill" />
+          <el-image class="image" v-else :src="footInfo.Logo" fit="fill" />
+          <div class="title">电话:{{ footInfos.Phone || footInfo.Phone }}</div>
+          <div class="title">邮箱:{{ footInfos.Email || footInfo.Email }}</div>
+          <div class="title">地址:{{ footInfos.Address || footInfo.Address }}</div>
+        </div>
+        <div class="right">
+          <el-image class="image" v-if="footInfos && footInfos.Code && footInfos.Code.length > 0" :src="getUrl(footInfos.Code)" fit="fill" />
+          <el-image class="image" v-else :src="footInfo.Code" fit="fill" />
+          <div class="title" @click="toHelp">关于我们</div>
+        </div>
+      </div>
+      <div class="footer_2">
+        {{ footInfo.Copyright }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ArrowDown } from '@element-plus/icons-vue'
+import { cloneDeep, get } from 'lodash-es'
+import { siteInfo, footInfo, menuList } from '@/layout/site'
+// 接口
+import { DesignStore } from '@/store/api/platform/design'
+const designStore = DesignStore()
+import { UserStore } from '@/store/user'
+const userStore = UserStore()
+const user = computed(() => userStore.user)
+
+const router = useRouter()
+const route = useRoute()
+const $checkRes = inject('$checkRes')
+const props = defineProps({
+  is_foot: { type: Boolean, default: () => true }
+})
+const configInfo = ref({})
+const footInfos = ref({})
+const data = ref([])
+const info = ref({})
+const isIncubator = ref(false)
+// 请求
+onMounted(async () => {
+  search()
+})
+const search = async () => {
+  for (const val of menuList) {
+    if (route.name === val.route) val.hover = true
+    else val.hover = false
+  }
+  let menus = cloneDeep(menuList)
+  // 判断, 如果没有孵化器角色, 则不显示孵化器菜单
+  if (user.value) {
+    const hasIncubator = get(user.value, 'role', []).find((f) => f === 'Incubator')
+    if (hasIncubator) isIncubator.value = true
+  }
+  if (!isIncubator.value) menus = menus.filter((f) => f.key !== '11')
+  data.value = menus
+
+  // 基础设置
+  const result = await designStore.query({})
+  if ($checkRes(result)) {
+    configInfo.value = result.data[0] || {}
+    footInfo.value = result.data[0].footInfo || {}
+  }
+}
+// 登录|注册
+const toLogin = (status) => {
+  router.push({ path: '/login', query: { status } })
+}
+const selectMenu = (item, query) => {
+  for (const val of data.value) {
+    if (route.name === val.route) val.hover = true
+    else val.hover = false
+  }
+  if (item == 'brain') window.open(`/cxyyWeb/brain`)
+  else router.push({ path: `/${item}`, query })
+}
+// 关于我们
+const toHelp = () => {
+  router.push({ path: `/help` })
+}
+// 个人中心
+const toCenter = () => {
+  router.push({ path: `/center` })
+}
+// 消息
+const toChat = () => {
+  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
+  info.value = data.value[index]
+}
+const handleMousOut = (index) => {
+  data.value[index].hover = false
+  const arr = data.value.every((i) => i.hover === false)
+  if (arr) {
+    for (const val of data.value) {
+      if (route.name === val.route) val.hover = true
+      else val.hover = false
+    }
+  }
+}
+const getUrl = (item) => {
+  if (item && item.length > 0) return `${import.meta.env.VITE_APP_HOST}${item[0].uri}`
+}
+// 退出登录
+const toOut = () => {
+  userStore.logOut()
+  router.push({ path: '/login', query: { status: '1' } })
+}
+</script>
+
+<style lang="scss" scoped>
+#c-layout {
+  .header {
+    padding: 0;
+    position: sticky;
+    top: 0;
+    z-index: 1000;
+    padding: 5px 0;
+    background: $global-color-fff;
+    .header_1 {
+      display: flex;
+      justify-content: space-between;
+      .left {
+        display: flex;
+        .image {
+          height: 60px;
+          width: 240px;
+          margin: 0 5px 0 0;
+        }
+        .content {
+          padding: 10px 0 0 0;
+          font-size: $global-font-size-34;
+          font-family: 'Comic Sans MS', cursive;
+        }
+      }
+      .right {
+        display: flex;
+        font-size: $global-font-size-18;
+        cursor: pointer; /* 改变鼠标样式为手形 */
+        .right_1 {
+          display: flex;
+          align-items: center;
+          color: $global-color-107;
+          margin: 0 10px 0 0;
+          span {
+            margin: 0 5px;
+          }
+          .el-dropdown-link {
+            font-size: $global-font-size-18;
+            cursor: pointer;
+            color: #409eff;
+            display: flex;
+            align-items: center;
+          }
+        }
+        .right_2 {
+          display: flex;
+          align-items: center;
+          margin: 0 5px;
+          span {
+            margin: 0 0 0 5px;
+          }
+        }
+      }
+    }
+    .header_2 {
+      .list {
+        display: flex;
+        justify-content: space-around;
+        .text {
+          text-align: center;
+          padding: 0 10px;
+          height: 58px;
+          line-height: 58px;
+          font-family: Microsoft YaHei;
+          font-size: $global-font-size-24;
+          color: #333333;
+          cursor: pointer; /* 改变鼠标样式为手形 */
+        }
+      }
+
+      .info {
+        display: none;
+        .info_1 {
+          position: absolute;
+          left: 0;
+          top: 128px;
+          display: flex;
+          padding: 10px 0;
+          background: $global-color-107;
+          width: 700px;
+          .list_1 {
+            margin: 0 10px 0 0;
+            .title {
+              margin: 5px 0;
+              font-size: $global-font-size-20;
+              font-weight: 600;
+              text-align: center;
+              color: #fff;
+              cursor: pointer; /* 改变鼠标样式为手形 */
+            }
+            .list_1_1 {
+              display: flex;
+              flex-wrap: wrap;
+              justify-content: center;
+              margin: 5px 0;
+              .title1 {
+                width: 120px;
+                margin: 5px;
+                padding: 5px;
+                text-align: center;
+                color: #ffffff;
+                font-size: $global-font-size-18;
+                cursor: pointer; /* 改变鼠标样式为手形 */
+              }
+            }
+          }
+        }
+        .info_2 {
+          position: absolute;
+          left: 73.3%;
+          top: 128px;
+          display: flex;
+          padding: 10px 0;
+          background: $global-color-107;
+          width: 145px;
+          .list_2 {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            margin: 5px 0;
+            .title1 {
+              width: 110px;
+              margin: 5px;
+              padding: 5px;
+              text-align: center;
+              color: #ffffff;
+              font-size: $global-font-size-18;
+              cursor: pointer; /* 改变鼠标样式为手形 */
+            }
+          }
+        }
+        .info_3 {
+          left: 68.1%;
+        }
+        .info_4 {
+          position: absolute;
+          left: 0;
+          top: 128px;
+          width: 100%;
+          background: $global-color-fff;
+          background: -webkit-linear-gradient(top, white, #6ea6f5, #3b86ee);
+          cursor: pointer; /* 改变鼠标样式为手形 */
+          .list4 {
+            display: flex;
+            justify-content: center;
+            .list_1 {
+              padding: 20px 0;
+              position: relative;
+              margin: 0 10px;
+              span {
+                position: absolute;
+                top: 40px;
+                left: 0;
+                width: 100%;
+                text-align: center;
+                font-size: 20px;
+                color: #000;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  .header:hover {
+    .header_2 {
+      .info {
+        display: block !important;
+      }
+    }
+  }
+  .main {
+    min-height: 62vh;
+  }
+  .footer {
+    padding: 0 5px 10px 5px;
+    background-color: $global-color-2D2;
+    color: $global-color-fff;
+    font-size: $global-font-size-18;
+    .footer_1 {
+      padding: 10px 0;
+      display: flex;
+      justify-content: space-between;
+      border-bottom: 1px solid $global-color-bbb;
+      .left {
+        .image {
+          width: 393px;
+          height: 70px;
+        }
+        .title {
+          margin: 5px 0 0 0;
+        }
+      }
+      .right {
+        text-align: center;
+        .image {
+          width: 130px;
+          height: 130px;
+        }
+        .title {
+          margin: 5px 0 0 0;
+        }
+      }
+    }
+    .footer_2 {
+      padding: 10px 0 0 0;
+    }
+  }
+}
+@media screen and (max-width: 1280px) {
+  #c-layout {
+    min-width: 1920px;
+    margin: 0 auto;
+  }
+}
+@media screen and (min-width: 1921px) {
+  #c-layout {
+    max-width: 1920px;
+    margin: 0 auto;
+  }
+}
+</style>

+ 0 - 17
src/components/custom/custom-layout.vue

@@ -55,23 +55,6 @@
           </div>
         </el-col>
         <el-col :span="24" class="info">
-          <!-- <div class="info_1" v-if="info.key == '3'">
-            <el-col :span="12" class="list_1" v-for="(agg, index) in info.children" :key="index">
-              <div class="title">{{ agg.title }}</div>
-              <div class="list_1_1">
-                <div v-for="(tag, indexs) in agg.children" :key="indexs" class="title1" @click="selectMenu(tag.route)">
-                  {{ tag.title }}
-                </div>
-              </div>
-            </el-col>
-          </div> -->
-          <!-- <div class="info_2" :class="[user && user.id && isIncubator ? 'info_3' : '']" v-if="info.key == '10'">
-            <el-col :span="24" class="list_2">
-              <div v-for="(tag, indexs) in info.children" :key="indexs" class="title1" @click="selectMenu(tag.route)">
-                {{ tag.title }}
-              </div>
-            </el-col>
-          </div> -->
           <div class="info_4" v-if="info.key == '10'">
             <div class="w_1300 list4">
               <div v-for="(tag, indexs) in info.children" :key="indexs" class="list_1" @click="selectMenu(tag.route)">

+ 12 - 1
src/views/detail/achievementDetail.vue

@@ -51,6 +51,12 @@
             <div class="brief">{{ info.brief || '暂无' }}</div>
           </div>
         </div>
+        <div class="info_2" v-if="info.file && info.file.length > 0">
+          <div class="title">成果附件</div>
+          <div class="file">
+            <el-link :href="info.file[0].url" target="_blank">{{ info.file[0].name }}</el-link>
+          </div>
+        </div>
         <div class="info_3">
           <div class="title">相关成果推荐</div>
           <div class="content">
@@ -200,6 +206,12 @@ const toView = async (item) => {
         border-bottom: 5px solid #378cff;
         cursor: pointer;
       }
+      .file {
+        margin: 20px 0 0 0;
+        .el-link {
+          font-size: $global-font-size-20;
+        }
+      }
       .content {
         padding: 20px;
         margin-top: 25px !important;
@@ -223,7 +235,6 @@ const toView = async (item) => {
     }
     .info_3 {
       padding: 80px !important;
-      margin-top: 50px !important;
       background: #fff;
       .title {
         color: #000;

+ 9 - 5
src/views/detail/expertDetail.vue

@@ -60,19 +60,19 @@
             <div class="title">科研成果</div>
             <div class="content">
               <div class="content_1">
-                <div class="menu menuTrue">
+                <div class="menu" :class="[active == '1' ? 'menuTrue' : '']" @click="toActive('1')">
                   <span>期刊论文</span>
                 </div>
-                <div class="menu">
+                <div class="menu" :class="[active == '2' ? 'menuTrue' : '']" @click="toActive('2')">
                   <span>科技成果</span>
                 </div>
-                <div class="menu">
+                <div class="menu" :class="[active == '3' ? 'menuTrue' : '']" @click="toActive('3')">
                   <span>专利</span>
                 </div>
               </div>
               <div class="content_2">
-                <div class="scientific" v-for="(item, index) in scientific" :key="index">
-                  {{ item || '暂无' }}
+                <div class="scientific">
+                  {{ info.brief || '暂无' }}
                 </div>
               </div>
             </div>
@@ -97,6 +97,7 @@ const tableData = ref([
   // { company: '清华大学车辆与运载学院', num: '27' },
   // { company: '原一汽技术中心技术中心', num: '23' }
 ])
+const active = ref('1')
 const info = ref({})
 const scientific = ref([])
 // const scientific = ref(['面向等离子体材料用先进钨复合材料的改性研究进展与趋势', '湿化学法W-Re合金制备与性能', '低能高通量氨离子辐照下W28Ta28V28Zr8Sc8高熵合金损伤行为研究', '配位聚合物衍生的硒化锡@多孔碳纳米棒及其储钠性能研究'])
@@ -132,6 +133,9 @@ const searchOther = async () => {
   // result = await dictDataStore.query({ code: 'technology', is_use: '0' })
   // if ($checkRes(result)) technologyList.value = result.data
 }
+const toActive = (item) => {
+  active.value = item
+}
 </script>
 <style scoped lang="scss">
 .main {

+ 1 - 1
src/views/detail/parts/index.vue

@@ -47,7 +47,7 @@
             </el-form-item>
             <el-form-item>
               <el-col :span="24" class="button">
-                <el-button type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
+                <el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button>
               </el-col>
             </el-form-item>
           </el-form>

+ 60 - 0
src/views/detail/parts/project.vue

@@ -0,0 +1,60 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-col :span="24" class="one">
+          <el-form label-position="top" ref="ruleFormRef" :model="form" :rules="rules" label-width="80px" class="form">
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="姓名" prop="name">
+                  <el-input clearable v-model="form.name" placeholder="请输入姓名"> </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="电话号" prop="phone">
+                  <el-input clearable v-model="form.phone" placeholder="请输入电话号"> </el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-row :gutter="20">
+              <el-col :span="12">
+                <el-form-item label="单位" prop="work">
+                  <el-input clearable v-model="form.work" placeholder="请输入单位名称"> </el-input>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="电子邮箱" prop="email">
+                  <el-input clearable v-model="form.email" placeholder="请输入电子邮箱"> </el-input>
+                </el-form-item>
+              </el-col>
+            </el-row>
+            <el-form-item label="备注" prop="brief">
+              <el-input v-model="form.remark" :autosize="{ minRows: 2, maxRows: 8 }" type="textarea" placeholder="请输入备注" />
+            </el-form-item>
+            <el-form-item>
+              <el-col :span="24" class="button">
+                <el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button>
+              </el-col>
+            </el-form-item>
+          </el-form>
+        </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+const ruleFormRef = inject('ruleFormRef')
+const form = inject('form')
+const rules = inject('rules')
+const submitForm = inject('submitForm')
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    .button {
+      text-align: center;
+    }
+  }
+}
+</style>

+ 71 - 1
src/views/detail/projectDetail.vue

@@ -36,7 +36,7 @@
               </div>
               <div class="other_1">
                 <div class="name">{{ info.person || '暂无' }}</div>
-                <div class="button">预约对接</div>
+                <div class="button" @click="dialog = true">预约对接</div>
               </div>
             </div>
             <div class="inose_top">
@@ -74,6 +74,12 @@
             </div>
           </div>
         </div>
+        <div class="info_4" v-if="info.file && info.file.length > 0">
+          <div class="title">项目附件</div>
+          <div class="file">
+            <el-link :href="info.file[0].url" target="_blank">{{ info.file[0].name }}</el-link>
+          </div>
+        </div>
         <div class="info_3">
           <div class="right_1">
             <div class="title">
@@ -110,6 +116,9 @@
       </div>
     </el-col>
   </custom-layout>
+  <el-dialog v-model="dialog" title="对接预约" :destroy-on-close="true" @close="toClose">
+    <data-form></data-form>
+  </el-dialog>
 </template>
 
 <script setup>
@@ -117,6 +126,9 @@ import liIcon from '/images/li-icon.png'
 import biao_1 from '/images/biao_1.png'
 import biao_2 from '/images/biao_2.png'
 import biao_3 from '/images/biao_3.png'
+
+// 组件
+import dataForm from './parts/project.vue'
 // 接口
 import { ProjectStore } from '@/store/api/platform/project'
 import { ExpertStore } from '@/store/api/user/expert'
@@ -135,6 +147,25 @@ const router = useRouter()
 const info = ref({})
 const expertList = ref([])
 const projectList = ref([])
+
+const form = ref({})
+const dialog = ref(false)
+
+const ruleFormRef = ref()
+const validatePhoneNumber = (rule, value, callback) => {
+  const reg = /^1[3-9]\d{9}$/
+  if (!value) {
+    return callback(new Error('手机号不能为空'))
+  }
+  if (!reg.test(value)) {
+    return callback(new Error('请输入正确的手机号'))
+  }
+  callback()
+}
+const rules = reactive({
+  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+  phone: [{ required: true, validator: validatePhoneNumber, trigger: 'blur' }]
+})
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -193,6 +224,24 @@ const toMore = (type) => {
   if (type == '0') router.push({ path: '/expert' })
   else if (type == '1') router.push({ path: '/project' })
 }
+// 报名
+const submitForm = async (formEl) => {
+  if (user.value.id) {
+    await toClose()
+    ElMessage.success('预约对接成功!')
+  } else {
+    ElMessage.error('用户未登录无法预约对接!')
+  }
+}
+const toClose = () => {
+  dialog.value = false
+  form.value = {}
+}
+// provide
+provide('form', form)
+provide('rules', rules)
+provide('ruleFormRef', ruleFormRef)
+provide('submitForm', submitForm)
 </script>
 <style scoped lang="scss">
 .main {
@@ -202,6 +251,26 @@ const toMore = (type) => {
     .info_1 {
       padding: 30px 0;
     }
+    .info_4 {
+      padding: 0 50px 30px 50px;
+      background: #fff;
+      .title {
+        color: #000;
+        display: inline-block;
+        margin-right: 80px;
+        padding-bottom: 20px;
+        font-size: $global-font-size-30;
+        color: #000000;
+        border-bottom: 5px solid #378cff;
+        cursor: pointer;
+      }
+      .file {
+        margin: 20px 0 0 0;
+        .el-link {
+          font-size: $global-font-size-20;
+        }
+      }
+    }
     .info_2 {
       display: flex;
       border-radius: 5px;
@@ -241,6 +310,7 @@ const toMore = (type) => {
               font-size: $global-font-size-18;
             }
             .button {
+              cursor: default;
               margin-top: 20px;
               justify-content: center;
               display: flex;