zs преди 8 месеца
родител
ревизия
81e572035c

BIN
public/images/cata1.png


BIN
public/images/cata2.png


BIN
public/images/cata3.png


BIN
public/images/service_bottom_bg.png


BIN
public/images/service_center_bg.png


BIN
public/images/service_top_bg.png


+ 5 - 1
src/store/api/util.js

@@ -6,5 +6,9 @@ export const UtilStore = defineStore('util', () => {
     const res = await axios.$post(`/util/toImport`, payload)
     return res
   }
-  return { toImport }
+  const toExport = async (payload) => {
+    const res = await axios.$post(`/util/toExport`, payload)
+    return res
+  }
+  return { toImport, toExport }
 })

+ 100 - 16
src/views/center/achievement.vue

@@ -6,7 +6,7 @@
           <div class="one_left">
             <div class="button" @click="toAdd">发布成果</div>
             <div class="button" @click="toTemplate">下载导出模板</div>
-            <div class="button" @click="toUExcel">上传Excel</div>
+            <el-upload class="button" :action="url" :show-file-list="false" :on-error="onError" :http-request="httpRequse" accept=".xlsx"> 选择excel模板文件 </el-upload>
             <div class="button" @click="toDownload">下载Excel</div>
           </div>
           <div class="one_right">
@@ -77,6 +77,19 @@
             </template>
           </custom-form>
         </el-col>
+        <el-col :span="24" class="dialog_thr" v-if="dialog.type == '3'">
+          <el-col :span="24" class="one">
+            <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
+          </el-col>
+          <el-col :span="24" class="two">
+            <el-checkbox-group v-model="checkedExport" @change="checkedExportChange">
+              <el-checkbox v-for="i in formFields" :label="i" :key="i.model">{{ i.label }}</el-checkbox>
+            </el-checkbox-group>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="mini" @click="toFile()">导出</el-button>
+          </el-col>
+        </el-col>
       </el-row>
     </el-dialog>
   </div>
@@ -95,6 +108,8 @@ import { DictDataStore } from '@/store/api/system/dictData'
 import { TagsStore } from '@/store/api/system/tags'
 import { SectorStore } from '@/store/api/platform/sector'
 import { RegionStore } from '@/store/api/system/region'
+import { UtilStore } from '@/store/api/util'
+const utilStore = UtilStore()
 const regionStore = RegionStore()
 const store = AchievementStore()
 const dictDataStore = DictDataStore()
@@ -127,25 +142,29 @@ const form = ref({ file: [] })
 const dialog = ref({ type: '1', show: false, title: '发布成果' })
 const formFields = ref([
   { label: '成果名称', model: 'name' },
-  { label: '标签', model: 'tags', custom: true },
+  { label: '标签', model: 'tags', custom: true, mark: 'tags' },
   { label: '所属产业', model: 'industry', type: 'select' },
   { label: '专利号', model: 'patent' },
   { label: '行业领域', model: 'field' },
-  { label: '属性', model: 'attribute', type: 'select' },
-  { label: '成熟度', model: 'mature', type: 'select' },
-  { label: '出让方式', model: 'sell', type: 'select' },
-  { label: '技术分类', model: 'technology', type: 'select' },
-  { label: '成果地区', model: 'area', custom: true },
+  { label: '属性', model: 'attribute', type: 'select', mark: 'dict', code: 'attribute' },
+  { label: '成熟度', model: 'mature', type: 'select', mark: 'dict', code: 'mature' },
+  { label: '出让方式', model: 'sell', type: 'select', mark: 'dict', code: 'sell' },
+  { label: '技术分类', model: 'technology', type: 'select', mark: 'dict', code: 'technology' },
+  { label: '成果地区', model: 'area', custom: true, mark: 'area' },
   { label: '发布时间', model: 'time', type: 'date' },
   { label: '价格(万元)', model: 'money' },
   { label: '项目来源', model: 'source' },
   { label: '联系人', model: 'person' },
   { label: '联系电话', model: 'tel' },
-  { label: '是否公开', model: 'is_use', type: 'radio' },
+  { label: '是否公开', model: 'is_use', type: 'radio', mark: 'dict', code: 'isUse' },
   { label: '简介', model: 'brief', type: 'textarea' },
-  { label: '附件', model: 'file', custom: true }
+  { label: '附件', model: 'file', custom: true, mark: 'file' }
 ])
 const rules = reactive({ name: [{ required: true, message: '请输入成果名称', trigger: 'blur' }] })
+// 导出文件
+const checkAll = ref(false)
+const checkedExport = ref([])
+const isIndeterminate = ref(true)
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -273,21 +292,69 @@ const toExam = async (row) => {
     })
     .catch(() => {})
 }
+const toClose = () => {
+  checkedExport.value = []
+  checkAll.value = false
+  form.value = { time: [] }
+  dialog.value = { show: false }
+}
+// 全选
+const handleCheckAllChange = (val) => {
+  checkedExport.value = val ? formFields.value : []
+  isIndeterminate.value = false
+}
+// 选择
+const checkedExportChange = (value) => {
+  let checkedCount = value.length
+  checkAll.value = checkedCount === formFields.value.length
+  isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
+}
 // 下载导出模板
 const toTemplate = () => {
-  console.log('下载导出模板')
+  window.open('/cxyyWeb/导入模板.xlsx')
 }
 // 上传Excel
-const toUExcel = () => {
-  console.log('上传Excel')
+const httpRequse = async (param) => {
+  const msgbox = ElMessage({ message: '正在导入中,请稍后...', center: true, duration: 0 })
+  try {
+    let fileObj = param.file
+    let fd = new FormData()
+    fd.append('file', fileObj, fileObj.name)
+    const res = await utilStore.toImport(fd)
+    // let list
+    console.log(res)
+    // if (res.status !== 200) {
+    //   list = [{ key: '请求发生错误' }]
+    // } else if (res.data.errcode !== 0) {
+    //   list = [{ key: '请求发生错误', num: res.data.errmsg }]
+    // } else {
+    //   list = res.data.data
+    // }
+    // console.log(list)
+  } catch (error) {
+    console.error(error)
+  } finally {
+    msgbox.close()
+  }
 }
 // 下载Excel
 const toDownload = () => {
-  console.log('下载Excel')
+  dialog.value = { type: '3', show: true, title: '下载Excel' }
 }
-const toClose = () => {
-  form.value = { file: [] }
-  dialog.value = { show: false }
+
+// 导出Excel
+const toFile = async () => {
+  if (checkedExport.value.length > 0) {
+    const reqData = { table: 'achievement', config: checkedExport.value, user: user.value.id }
+    const res = await utilStore.toExport(reqData)
+    if ($checkRes(res, true)) {
+      ElMessage({ type: `success`, message: `导出成功` })
+      window.open(res.data)
+    }
+    toClose()
+  } else {
+    ElMessage({ type: `warning`, message: `请选择导出信息字段` })
+  }
 }
 // 分页
 const changePage = (page = currentPage.value) => {
@@ -328,4 +395,21 @@ const sizeChange = (limits) => {
     margin: 20px 0 0 0;
   }
 }
+.dialog_thr {
+  padding: 20px;
+
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+    :deep(.el-checkbox) {
+      padding: 0 0 20px 0;
+    }
+  }
+  .btn {
+    text-align: center;
+    margin: 20px 0 0 0;
+  }
+}
 </style>

+ 70 - 9
src/views/center/demand.vue

@@ -94,6 +94,19 @@
             </div>
           </el-col>
         </transition>
+        <el-col :span="24" class="dialog_thr" v-if="dialog.type == '3'">
+          <el-col :span="24" class="one">
+            <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
+          </el-col>
+          <el-col :span="24" class="two">
+            <el-checkbox-group v-model="checkedExport" @change="checkedExportChange">
+              <el-checkbox v-for="i in formFields" :label="i" :key="i.model">{{ i.label }}</el-checkbox>
+            </el-checkbox-group>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="mini" @click="toFile()">导出</el-button>
+          </el-col>
+        </el-col>
       </el-row>
     </el-dialog>
   </div>
@@ -114,13 +127,13 @@ import { TagsStore } from '@/store/api/system/tags'
 import { SectorStore } from '@/store/api/platform/sector'
 import { RegionStore } from '@/store/api/system/region'
 import { UtilStore } from '@/store/api/util'
+const utilStore = UtilStore()
 const regionStore = RegionStore()
 const store = DemandStore()
 const dictDataStore = DictDataStore()
 const tagsStore = TagsStore()
 const sectorStore = SectorStore()
 const supplyStore = SupplyStore()
-const utilStore = UtilStore()
 // 加载中
 const loading = ref(false)
 const isLoading = ref(false)
@@ -161,11 +174,11 @@ const form = ref({ time: [] })
 const dialog = ref({ type: '1', show: false, title: '发布需求' })
 const formFields = ref([
   { label: '需求名称', model: 'name' },
-  { label: '标签', model: 'tags', custom: true },
+  { label: '标签', model: 'tags', custom: true, mark: 'tags' },
   { label: '所属产业', model: 'industry', type: 'select' },
   { label: '行业领域', model: 'field' },
-  { label: '需求紧急度', model: 'urgent', type: 'select' },
-  { label: '合作方式', model: 'method', type: 'select' },
+  { label: '需求紧急度', model: 'urgent', type: 'select', mark: 'dict', code: 'urgent' },
+  { label: '合作方式', model: 'method', type: 'select', mark: 'dict', code: 'method' },
   { label: '价格(万元)', model: 'money' },
   { label: '所属企业', model: 'company' },
   { label: '企业简况', model: 'company_brief', type: 'textarea' },
@@ -175,12 +188,16 @@ const formFields = ref([
   { label: '月份', model: 'month', type: 'month' },
   { label: '技术需求名称', model: 'tec_name' },
   { label: '待解决问题', model: 'question', type: 'textarea' },
-  { label: '需求地区', model: 'area', custom: true },
-  { label: '发布时间', model: 'time', type: 'daterange' },
-  { label: '是否公开', model: 'is_use', type: 'radio' },
+  { label: '需求地区', model: 'area', custom: true, mark: 'area' },
+  { label: '发布时间', model: 'time', type: 'daterange', mark: 'time' },
+  { label: '是否公开', model: 'is_use', type: 'radio', mark: 'dict', code: 'isUse' },
   { label: '简介', model: 'brief', type: 'textarea' }
 ])
 const rules = reactive({ name: [{ required: true, message: '请输入需求名称', trigger: 'blur' }] })
+// 导出文件
+const checkAll = ref(false)
+const checkedExport = ref([])
+const isIndeterminate = ref(true)
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -332,10 +349,23 @@ const toView = (item) => {
   router.push({ path: '/supply/detail', query: { id: item.id || item._id } })
 }
 const toClose = () => {
+  checkedExport.value = []
+  checkAll.value = false
   form.value = { time: [] }
   width.value = '50%'
   dialog.value = { show: false }
 }
+// 全选
+const handleCheckAllChange = (val) => {
+  checkedExport.value = val ? formFields.value : []
+  isIndeterminate.value = false
+}
+// 选择
+const checkedExportChange = (value) => {
+  let checkedCount = value.length
+  checkAll.value = checkedCount === formFields.value.length
+  isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
+}
 // 下载导出模板
 const toTemplate = () => {
   window.open('/cxyyWeb/导入模板.xlsx')
@@ -346,7 +376,6 @@ const httpRequse = async (param) => {
   try {
     let fileObj = param.file
     let fd = new FormData()
-    console.log(fileObj.name)
     fd.append('file', fileObj, fileObj.name)
     const res = await utilStore.toImport(fd)
     // let list
@@ -367,7 +396,22 @@ const httpRequse = async (param) => {
 }
 // 下载Excel
 const toDownload = () => {
-  console.log('下载Excel')
+  dialog.value = { type: '3', show: true, title: '下载Excel' }
+}
+
+// 导出Excel
+const toFile = async () => {
+  if (checkedExport.value.length > 0) {
+    const reqData = { table: 'demand', config: checkedExport.value, user: user.value.id }
+    const res = await utilStore.toExport(reqData)
+    if ($checkRes(res, true)) {
+      ElMessage({ type: `success`, message: `导出成功` })
+      window.open(res.data)
+    }
+    toClose()
+  } else {
+    ElMessage({ type: `warning`, message: `请选择导出信息字段` })
+  }
 }
 // 分页
 const changePage = (page = currentPage.value) => {
@@ -493,4 +537,21 @@ const sizeChange = (limits) => {
     }
   }
 }
+.dialog_thr {
+  padding: 20px;
+
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+    :deep(.el-checkbox) {
+      padding: 0 0 20px 0;
+    }
+  }
+  .btn {
+    text-align: center;
+    margin: 20px 0 0 0;
+  }
+}
 </style>

+ 101 - 17
src/views/center/project.vue

@@ -6,7 +6,7 @@
           <div class="one_left">
             <div class="button" @click="toAdd">发布项目</div>
             <div class="button" @click="toTemplate">下载导出模板</div>
-            <div class="button" @click="toUExcel">上传Excel</div>
+            <el-upload class="button" :action="url" :show-file-list="false" :on-error="onError" :http-request="httpRequse" accept=".xlsx"> 选择excel模板文件 </el-upload>
             <div class="button" @click="toDownload">下载Excel</div>
           </div>
           <div class="one_right">
@@ -102,6 +102,19 @@
             </div>
           </el-col>
         </transition>
+        <el-col :span="24" class="dialog_thr" v-if="dialog.type == '3'">
+          <el-col :span="24" class="one">
+            <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
+          </el-col>
+          <el-col :span="24" class="two">
+            <el-checkbox-group v-model="checkedExport" @change="checkedExportChange">
+              <el-checkbox v-for="i in formFields" :label="i" :key="i.model">{{ i.label }}</el-checkbox>
+            </el-checkbox-group>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="mini" @click="toFile()">导出</el-button>
+          </el-col>
+        </el-col>
       </el-row>
     </el-dialog>
   </div>
@@ -121,6 +134,8 @@ import { DictDataStore } from '@/store/api/system/dictData'
 import { TagsStore } from '@/store/api/system/tags'
 import { SectorStore } from '@/store/api/platform/sector'
 import { RegionStore } from '@/store/api/system/region'
+import { UtilStore } from '@/store/api/util'
+const utilStore = UtilStore()
 const regionStore = RegionStore()
 const store = ProjectStore()
 const dictDataStore = DictDataStore()
@@ -168,24 +183,28 @@ const form = ref({ file: [] })
 const dialog = ref({ type: '1', show: false, title: '发布项目' })
 const formFields = ref([
   { label: '项目名称', model: 'name' },
-  { label: '标签', model: 'tags', custom: true },
+  { label: '标签', model: 'tags', custom: true, mark: 'tags' },
   { label: '所属产业', model: 'industry', type: 'select' },
-  { label: '行业分类', model: 'type', type: 'select' },
-  { label: '成熟度', model: 'maturity', type: 'select' },
-  { label: '技术类型', model: 'skill', type: 'select' },
-  { label: '行业领域', model: 'field', type: 'select' },
-  { label: '合作类型', model: 'cooperate', type: 'select' },
-  { label: '项目地区', model: 'area', custom: true },
+  { label: '行业分类', model: 'type', type: 'select', code: 'industry' },
+  { label: '成熟度', model: 'maturity', type: 'select', mark: 'dict', code: 'projectMaturity' },
+  { label: '技术类型', model: 'skill', type: 'select', mark: 'dict', code: 'technology' },
+  { label: '行业领域', model: 'field', type: 'select', mark: 'dict', code: 'field' },
+  { label: '合作类型', model: 'cooperate', type: 'select', mark: 'dict', code: 'projectType' },
+  { label: '项目地区', model: 'area', custom: true, mark: 'area' },
   { label: '发布时间', model: 'time', type: 'date' },
   { label: '项目主体', model: 'main' },
   { label: '项目进展', model: 'progress' },
   { label: '跟踪支持单位', model: 'track_unit' },
   { label: '项目来源', model: 'source' },
-  { label: '是否启用', model: 'is_use', type: 'radio' },
+  { label: '是否启用', model: 'is_use', type: 'radio', mark: 'dict', code: 'isUse' },
   { label: '简介', model: 'brief', type: 'textarea' },
   { label: '附件', model: 'file', custom: true }
 ])
 const rules = reactive({ name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }] })
+// 导出文件
+const checkAll = ref(false)
+const checkedExport = ref([])
+const isIndeterminate = ref(true)
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -337,22 +356,70 @@ const getArea = (data) => {
   if (data) return data.join('-')
   else return '暂无地区'
 }
+const toClose = () => {
+  checkedExport.value = []
+  checkAll.value = false
+  form.value = { time: [] }
+  width.value = '50%'
+  dialog.value = { show: false }
+}
+// 全选
+const handleCheckAllChange = (val) => {
+  checkedExport.value = val ? formFields.value : []
+  isIndeterminate.value = false
+}
+// 选择
+const checkedExportChange = (value) => {
+  let checkedCount = value.length
+  checkAll.value = checkedCount === formFields.value.length
+  isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
+}
 // 下载导出模板
 const toTemplate = () => {
-  console.log('下载导出模板')
+  window.open('/cxyyWeb/导入模板.xlsx')
 }
 // 上传Excel
-const toUExcel = () => {
-  console.log('上传Excel')
+const httpRequse = async (param) => {
+  const msgbox = ElMessage({ message: '正在导入中,请稍后...', center: true, duration: 0 })
+  try {
+    let fileObj = param.file
+    let fd = new FormData()
+    fd.append('file', fileObj, fileObj.name)
+    const res = await utilStore.toImport(fd)
+    // let list
+    console.log(res)
+    // if (res.status !== 200) {
+    //   list = [{ key: '请求发生错误' }]
+    // } else if (res.data.errcode !== 0) {
+    //   list = [{ key: '请求发生错误', num: res.data.errmsg }]
+    // } else {
+    //   list = res.data.data
+    // }
+    // console.log(list)
+  } catch (error) {
+    console.error(error)
+  } finally {
+    msgbox.close()
+  }
 }
 // 下载Excel
 const toDownload = () => {
-  console.log('下载Excel')
+  dialog.value = { type: '3', show: true, title: '下载Excel' }
 }
-const toClose = () => {
-  form.value = { file: [] }
-  width.value = '50%'
-  dialog.value = { show: false }
+
+// 导出Excel
+const toFile = async () => {
+  if (checkedExport.value.length > 0) {
+    const reqData = { table: 'project', config: checkedExport.value, user: user.value.id }
+    const res = await utilStore.toExport(reqData)
+    if ($checkRes(res, true)) {
+      ElMessage({ type: `success`, message: `导出成功` })
+      window.open(res.data)
+    }
+    toClose()
+  } else {
+    ElMessage({ type: `warning`, message: `请选择导出信息字段` })
+  }
 }
 // 分页
 const changePage = (page = currentPage.value) => {
@@ -478,4 +545,21 @@ const sizeChange = (limits) => {
     }
   }
 }
+.dialog_thr {
+  padding: 20px;
+
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+    :deep(.el-checkbox) {
+      padding: 0 0 20px 0;
+    }
+  }
+  .btn {
+    text-align: center;
+    margin: 20px 0 0 0;
+  }
+}
 </style>

+ 100 - 16
src/views/center/supply.vue

@@ -6,7 +6,7 @@
           <div class="one_left">
             <div class="button" @click="toAdd">发布供给</div>
             <div class="button" @click="toTemplate">下载导出模板</div>
-            <div class="button" @click="toUExcel">上传Excel</div>
+            <el-upload class="button" :action="url" :show-file-list="false" :on-error="onError" :http-request="httpRequse" accept=".xlsx"> 选择excel模板文件 </el-upload>
             <div class="button" @click="toDownload">下载Excel</div>
           </div>
           <div class="one_right">
@@ -94,6 +94,19 @@
             </div>
           </el-col>
         </transition>
+        <el-col :span="24" class="dialog_thr" v-if="dialog.type == '3'">
+          <el-col :span="24" class="one">
+            <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
+          </el-col>
+          <el-col :span="24" class="two">
+            <el-checkbox-group v-model="checkedExport" @change="checkedExportChange">
+              <el-checkbox v-for="i in formFields" :label="i" :key="i.model">{{ i.label }}</el-checkbox>
+            </el-checkbox-group>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" size="mini" @click="toFile()">导出</el-button>
+          </el-col>
+        </el-col>
       </el-row>
     </el-dialog>
   </div>
@@ -113,6 +126,8 @@ import { DictDataStore } from '@/store/api/system/dictData'
 import { TagsStore } from '@/store/api/system/tags'
 import { SectorStore } from '@/store/api/platform/sector'
 import { RegionStore } from '@/store/api/system/region'
+import { UtilStore } from '@/store/api/util'
+const utilStore = UtilStore()
 const regionStore = RegionStore()
 const store = SupplyStore()
 const dictDataStore = DictDataStore()
@@ -159,19 +174,23 @@ const form = ref({ time: [] })
 const dialog = ref({ type: '1', show: false, title: '发布供给' })
 const formFields = ref([
   { label: '供给名称', model: 'name' },
-  { label: '标签', model: 'tags', custom: true },
+  { label: '标签', model: 'tags', custom: true, mark: 'tags' },
   { label: '所属产业', model: 'industry', type: 'select' },
   { label: '行业领域', model: 'field' },
-  { label: '供给紧急度', model: 'urgent', type: 'select' },
-  { label: '合作方式', model: 'method', type: 'select' },
+  { label: '供给紧急度', model: 'urgent', type: 'select', mark: 'dict', code: 'urgent' },
+  { label: '合作方式', model: 'method', type: 'select', mark: 'dict', code: 'method' },
   { label: '价格(万元)', model: 'money' },
   { label: '项目来源', model: 'source' },
-  { label: '供给地区', model: 'area', custom: true },
-  { label: '发布时间', model: 'time', type: 'daterange' },
-  { label: '是否公开', model: 'is_use', type: 'radio' },
+  { label: '供给地区', model: 'area', custom: true, mark: 'area' },
+  { label: '发布时间', model: 'time', type: 'daterange', mark: 'time' },
+  { label: '是否公开', model: 'is_use', type: 'radio', mark: 'dict', code: 'isUse' },
   { label: '简介', model: 'brief', type: 'textarea' }
 ])
 const rules = reactive({ name: [{ required: true, message: '请输入供给名称', trigger: 'blur' }] })
+// 导出文件
+const checkAll = ref(false)
+const checkedExport = ref([])
+const isIndeterminate = ref(true)
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -320,29 +339,77 @@ const searchDemand = async () => {
 }
 // 查看详情
 const toView = (item) => {
-  router.push({ path: '/demand/detail', query: { id: item.id || item._id } })
+  router.push({ path: '/supply/detail', query: { id: item.id || item._id } })
 }
 // 地区
 const getArea = (data) => {
   if (data) return data.join('-')
   else return '暂无地区'
 }
+const toClose = () => {
+  checkedExport.value = []
+  checkAll.value = false
+  form.value = { time: [] }
+  width.value = '50%'
+  dialog.value = { show: false }
+}
+// 全选
+const handleCheckAllChange = (val) => {
+  checkedExport.value = val ? formFields.value : []
+  isIndeterminate.value = false
+}
+// 选择
+const checkedExportChange = (value) => {
+  let checkedCount = value.length
+  checkAll.value = checkedCount === formFields.value.length
+  isIndeterminate.value = checkedCount > 0 && checkedCount < formFields.value.length
+}
 // 下载导出模板
 const toTemplate = () => {
-  console.log('下载导出模板')
+  window.open('/cxyyWeb/导入模板.xlsx')
 }
 // 上传Excel
-const toUExcel = () => {
-  console.log('上传Excel')
+const httpRequse = async (param) => {
+  const msgbox = ElMessage({ message: '正在导入中,请稍后...', center: true, duration: 0 })
+  try {
+    let fileObj = param.file
+    let fd = new FormData()
+    fd.append('file', fileObj, fileObj.name)
+    const res = await utilStore.toImport(fd)
+    // let list
+    console.log(res)
+    // if (res.status !== 200) {
+    //   list = [{ key: '请求发生错误' }]
+    // } else if (res.data.errcode !== 0) {
+    //   list = [{ key: '请求发生错误', num: res.data.errmsg }]
+    // } else {
+    //   list = res.data.data
+    // }
+    // console.log(list)
+  } catch (error) {
+    console.error(error)
+  } finally {
+    msgbox.close()
+  }
 }
 // 下载Excel
 const toDownload = () => {
-  console.log('下载Excel')
+  dialog.value = { type: '3', show: true, title: '下载Excel' }
 }
-const toClose = () => {
-  form.value = { time: [] }
-  width.value = '50%'
-  dialog.value = { show: false }
+
+// 导出Excel
+const toFile = async () => {
+  if (checkedExport.value.length > 0) {
+    const reqData = { table: 'supply', config: checkedExport.value, user: user.value.id }
+    const res = await utilStore.toExport(reqData)
+    if ($checkRes(res, true)) {
+      ElMessage({ type: `success`, message: `导出成功` })
+      window.open(res.data)
+    }
+    toClose()
+  } else {
+    ElMessage({ type: `warning`, message: `请选择导出信息字段` })
+  }
 }
 // 分页
 const changePage = (page = currentPage.value) => {
@@ -468,4 +535,21 @@ const sizeChange = (limits) => {
     }
   }
 }
+.dialog_thr {
+  padding: 20px;
+
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+    :deep(.el-checkbox) {
+      padding: 0 0 20px 0;
+    }
+  }
+  .btn {
+    text-align: center;
+    margin: 20px 0 0 0;
+  }
+}
 </style>

+ 14 - 18
src/views/detail/matchDetail.vue

@@ -250,25 +250,21 @@ const getUrl = (item, type) => {
 }
 // 报名
 const submitForm = async (formEl) => {
-  if (user.value.id) {
-    if (!formEl) return
-    await formEl.validate(async (valid, fields) => {
-      if (valid) {
-        const data = cloneDeep(form.value)
-        const other = {
-          match: info.value.id,
-          user: user.value.id,
-          time: moment().format('YYYY-MM-DD')
-        }
-        let res = await signStore.create({ ...data, ...other })
-        if ($checkRes(res, true)) toClose()
-      } else {
-        console.log('error submit!', fields)
+  if (!formEl) return
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      const data = cloneDeep(form.value)
+      const other = {
+        match: info.value.id,
+        time: moment().format('YYYY-MM-DD')
       }
-    })
-  } else {
-    ElMessage.error('用户未登录无法报名活动!')
-  }
+      if (user.value.id) other.user = user.value.id
+      let res = await signStore.create({ ...data, ...other })
+      if ($checkRes(res, true)) toClose()
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
 }
 const toCollect = async () => {
   if (user.value.id) {

+ 145 - 50
src/views/thirteen/index.vue

@@ -5,15 +5,27 @@
     </el-col>
     <el-col :span="24" class="two">
       <div class="w_1300 flex">
-        <el-col :span="8" class="two_1" v-for="(item, index) in list" :key="index" @click="toView(item)">
-          <div class="top">
-            <el-image class="image" :src="getUrl(item.file)" fit="fill" />
-            <div class="text">
-              <h5 class="title" style="padding-top: 0px">{{ item.name || '暂无标题' }}</h5>
+        <div class="flexList" @mouseover="handleMouseOver(index)" v-for="(item, index) in list" :key="index">
+          <div class="two_1" :class="['list' + index]" v-if="is_show != index">
+            <h5 class="title">{{ item.name || '暂无标题' }}</h5>
+            <div class="brief textOne">{{ item.brief || '暂无简介' }}</div>
+          </div>
+          <div class="two_2" :class="['image' + index]" v-else>
+            <div class="other_1">
+              <div class="title">{{ item.name || '暂无标题' }}</div>
+              <div class="more" @click="toView(item)">查看更多>></div>
+            </div>
+            <div class="other_2 textMore">
+              {{ item.brief || '暂无简介' }}
+            </div>
+            <div class="other_3">
+              <div class="other_list" v-for="(tag, indexs) in item.list" :key="indexs">
+                <el-image class="image" :src="getUrl(tag.file)" fit="fill" />
+                <div class="title">{{ tag.name || '暂无标题' }}</div>
+              </div>
             </div>
           </div>
-          <div class="bottom textMore">{{ item.brief || '暂无' }}</div>
-        </el-col>
+        </div>
       </div>
     </el-col>
   </custom-layout>
@@ -24,9 +36,9 @@
 import news from '/images/news.png'
 // 接口
 import { JournalStore } from '@/store/api/platform/journal'
-import { DictDataStore } from '@/store/api/system/dictData'
+import { NotesStore } from '@/store/api/platform/notes'
 const store = JournalStore()
-const dictDataStore = DictDataStore()
+const notesStore = NotesStore()
 // 路由
 const router = useRouter()
 // 加载中
@@ -35,6 +47,7 @@ const list = ref([])
 let skip = 0
 let limit = 8
 const total = ref(0)
+const is_show = ref(0)
 // 请求
 onMounted(async () => {
   loading.value = true
@@ -47,6 +60,12 @@ const search = async (query = { skip, limit }) => {
   const info = { skip: query.skip, limit: query.limit, status: '1', is_use: '0' }
   const res = await store.query(info)
   if (res.errcode == '0') {
+    const data = { skip: 0, limit: 3, status: '1', is_use: '0' }
+    for (const val of res.data) {
+      data.journal = val.id
+      const arr = await notesStore.query(data)
+      if (arr.errcode == '0') val.list = arr.data
+    }
     list.value = res.data
     total.value = res.total
   }
@@ -58,6 +77,9 @@ const toView = async (item) => {
 const getUrl = (item) => {
   if (item && item.length > 0) return `${import.meta.env.VITE_APP_HOST}${item[0].uri}`
 }
+const handleMouseOver = (index) => {
+  is_show.value = index
+}
 </script>
 <style scoped lang="scss">
 .main {
@@ -73,52 +95,125 @@ const getUrl = (item) => {
     .flex {
       display: flex;
       justify-content: space-around;
-    }
-    .two_1 {
-      margin: 0 5px 0 0;
-      .top {
-        position: relative;
-        .image {
-          width: 100%;
-          height: 300px;
-        }
-        .text {
-          position: absolute;
-          left: 0;
-          bottom: 5px;
-          width: 100%;
-          padding: 0 8px;
-          background-color: rgba(0, 0, 0, 0.6);
-          background-image: none;
-          background-repeat: repeat;
-          background-position: 0 0;
-          background: -moz-linear-gradient(top, none, none);
-          background: -o-linear-gradient(top, none, none);
-          background: linear-gradient(top, none, none);
-          background: -webkit-gradient(linear, left top, left bottom, from(none), to(none));
-          box-sizing: border-box;
+      .flexList {
+        .two_1 {
+          margin: 0 5px 0 0;
+          width: 200px;
+          height: 480px;
+          text-align: center;
+          background-size: cover;
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+          align-items: center;
           .title {
-            margin: 0;
-            padding: 0;
+            margin-top: 58px;
             font-size: $global-font-size-18;
-            color: #fff;
+            color: #121834;
             text-align: center;
-            font-weight: normal;
-            font-style: normal;
-            text-decoration: none;
-            font-family: Tahoma;
-            line-height: 34px;
-            white-space: nowrap;
-            text-overflow: ellipsis;
-            -webkit-text-overflow: ellipsis;
-            -moz-text-overflow: ellipsis;
-            overflow: hidden;
+            line-height: 28px;
+            font-weight: 600;
+            margin: 0 0 10px 0;
+          }
+          .brief {
+            width: 80%;
+            padding: 10px 0 0 0;
+            margin: 0 10px;
+            font-family: PingFangSC-Regular;
+            font-size: $global-font-size-14;
+            color: #121834;
+            line-height: 19px;
+            font-weight: 400;
+            border-top: 0.5px dashed #909090;
           }
         }
-      }
-      .bottom {
-        margin: 10px 0;
-        font-size: $global-font-size-20;
+        .two_2 {
+          width: 850px;
+          height: 480px;
+          color: #fff;
+          border-radius: 2px;
+          padding: 0 40px 20px;
+          animation: box1 0.4s ease;
+          background-repeat: no-repeat;
+          .other_1 {
+            display: flex;
+            justify-content: space-between;
+            margin-bottom: 8px;
+            padding: 40px 0 20px 0;
+            cursor: pointer;
+            .title {
+              font-size: 26px;
+              color: #fff;
+              text-align: left;
+              line-height: 26px;
+              font-weight: 600;
+            }
+            .more {
+              font-family: PingFangSC-Medium;
+              font-size: $global-font-size-14;
+              color: #fff;
+              line-height: 21px;
+              font-weight: 500;
+              cursor: pointer;
+            }
+          }
+          .other_2 {
+            font-size: $global-font-size-14;
+            color: #fff;
+            line-height: 19px;
+            font-weight: 200;
+          }
+          .other_3 {
+            margin: 40px 0 0 0;
+            display: flex;
+            justify-content: space-between;
+            .other_list {
+              cursor: pointer;
+              width: 200px;
+              .image {
+                width: 100%;
+                height: 250px;
+              }
+              .title {
+                margin: 10px 0 0 0;
+                font-size: $global-font-size-18;
+                color: #fff;
+                text-align: center;
+                line-height: 26px;
+                font-weight: 500;
+              }
+            }
+          }
+        }
+        @keyframes box1 {
+          0% {
+            opacity: 0.8;
+            transform: scale(0.8);
+          }
+          100% {
+            opacity: 1;
+            transform: scale(1);
+          }
+        }
+
+        .list0 {
+          background: url(/images/cata1.png) no-repeat center;
+        }
+        .list1 {
+          background: url(/images/cata2.png) no-repeat center;
+        }
+        .list2 {
+          background: url(/images/cata3.png) no-repeat center;
+        }
+        .image0 {
+          background: url(/images/service_top_bg.png) no-repeat center;
+        }
+        .image1 {
+          background: url(/images/service_center_bg.png) center;
+        }
+        .image2 {
+          background: url(/images/service_bottom_bg.png) no-repeat center;
+        }
       }
     }
   }