zs преди 1 година
родител
ревизия
a9279c9f9f

+ 40 - 0
src/store/api/user/association.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/association'
+const axios = new AxiosWrapper()
+
+export const AssociationStore = defineStore('association', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/company.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/company'
+const axios = new AxiosWrapper()
+
+export const CompanyStore = defineStore('company', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/competition.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/competition'
+const axios = new AxiosWrapper()
+
+export const CompetitionStore = defineStore('competition', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/expert.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/expert'
+const axios = new AxiosWrapper()
+
+export const ExpertStore = defineStore('expert', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/incubator.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/incubator'
+const axios = new AxiosWrapper()
+
+export const IncubatorStore = defineStore('incubator', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/investment.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/investment'
+const axios = new AxiosWrapper()
+
+export const InvestmentStore = defineStore('investment', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/state.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/state'
+const axios = new AxiosWrapper()
+
+export const StateStore = defineStore('state', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 40 - 0
src/store/api/user/unit.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/unit'
+const axios = new AxiosWrapper()
+
+export const UnitStore = defineStore('unit', () => {
+  const query = async ({ skip = 0, limit = undefined, ...info } = {}) => {
+    let cond = {}
+    if (skip) cond.skip = skip
+    if (limit) cond.limit = limit
+    cond = { ...cond, ...info }
+    const res = await axios.$get(`${url}`, cond)
+    return res
+  }
+  const fetch = async (payload) => {
+    const res = await axios.$get(`${url}/${payload}`)
+    return res
+  }
+  const create = async (payload) => {
+    const res = await axios.$post(`${url}`, payload)
+    return res
+  }
+  const update = async (payload) => {
+    const id = get(payload, 'id', get(payload, '_id'))
+    const res = await axios.$post(`${url}/${id}`, payload)
+    return res
+  }
+  const del = async (payload) => {
+    const res = await axios.$delete(`${url}/${payload}`)
+    return res
+  }
+  return {
+    query,
+    fetch,
+    create,
+    update,
+    del
+  }
+})

+ 215 - 45
src/views/user/user/index.vue

@@ -1,23 +1,69 @@
 <template>
   <div class="main animate__animated animate__backInRight">
-    <custom-search-bar v-model="searchForm" :fields="fields.filter((f) => f.filter)" @search="search" @reset="toReset"></custom-search-bar>
-    <custom-table :data="data" :fields="fields" @search="search" :total="total" :opera="opera" @exam="toExam" @view="toView" @delete="toDelete"> </custom-table>
-    <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose">
+    <custom-search-bar
+      v-model="searchForm"
+      :fields="fields.filter((f) => f.filter)"
+      @search="search"
+      @reset="toReset"
+    ></custom-search-bar>
+    <custom-table
+      :data="data"
+      :fields="fields"
+      @search="search"
+      :total="total"
+      :opera="opera"
+      @view="toView"
+      @exam="toExam"
+      @delete="toDelete"
+    >
+      <template #role="{ row }">
+        <div class="tags">
+          <el-tag v-for="(item, index) in row.role" :key="index" type="primary">{{
+            getRole(item)
+          }}</el-tag>
+        </div>
+      </template>
+    </custom-table>
+    <el-dialog
+      v-model="dialog.show"
+      :title="dialog.title"
+      :destroy-on-close="false"
+      @close="toClose"
+    >
       <el-row>
         <el-col :span="24" v-if="dialog.type == '1'">
-          <custom-form v-model="form" :fields="formFields" :useSave="false">
-            <template #gender>
-              <el-option v-for="i in genderList" :key="i._id" :label="i.label" :value="i.value"></el-option>
-            </template>
-            <template #role>
-              {{ getRole(form.role) }}
-            </template>
-          </custom-form>
+          <el-tabs v-model="type" type="card" @tab-change="toChang">
+            <el-tab-pane
+              v-for="(item, index) in role"
+              :key="index"
+              :label="getRole(item)"
+              :name="item"
+            ></el-tab-pane>
+          </el-tabs>
+          <user v-if="type == 'User'"></user>
+          <expert v-if="type == 'Expert'"></expert>
+          <company v-if="type == 'Company'"></company>
+          <incubator v-if="type == 'Incubator'"></incubator>
+          <competition v-if="type == 'Competition'"></competition>
+          <investment v-if="type == 'Investment'"></investment>
+          <association v-if="type == 'Association'"></association>
+          <state v-if="type == 'State'"></state>
+          <unit v-if="type == 'Unit'"></unit>
         </el-col>
         <el-col :span="24" v-if="dialog.type == '2'">
-          <custom-form v-model="examForm" :fields="examFormFields" :rules="examRules" @save="toExamSave">
+          <custom-form
+            v-model="examForm"
+            :fields="examFormFields"
+            :rules="examRules"
+            @save="toExamSave"
+          >
             <template #status>
-              <el-option v-for="i in statusList" :key="i._id" :label="i.label" :value="i.value"></el-option>
+              <el-option
+                v-for="i in statusList"
+                :key="i._id"
+                :label="i.label"
+                :value="i.value"
+              ></el-option>
             </template>
           </custom-form>
         </el-col>
@@ -27,6 +73,18 @@
 </template>
 
 <script setup>
+// 组件
+import user from './parts/user.vue'
+import association from './parts/association.vue'
+import company from './parts/company.vue'
+import competition from './parts/competition.vue'
+import expert from './parts/expert.vue'
+import incubator from './parts/incubator.vue'
+import state from './parts/state.vue'
+import unit from './parts/unit.vue'
+import investment from './parts/investment.vue'
+// API 引用
+import { getCity } from '@/utils/city'
 import { UserStore } from '@/store/api/user/user'
 import { RoleStore } from '@/store/api/system/role'
 import { DictDataStore } from '@/store/api/system/dictData'
@@ -35,12 +93,31 @@ const $checkRes = inject('$checkRes')
 const store = UserStore()
 const dictDataStore = DictDataStore()
 const roleStore = RoleStore()
+// 接口
+import { UnitStore } from '@/store/api/user/unit'
+const unitStore = UnitStore()
+import { ExpertStore } from '@/store/api/user/expert'
+const expertStore = ExpertStore()
+import { AssociationStore } from '@/store/api/user/association'
+const associationStore = AssociationStore()
+import { CompanyStore } from '@/store/api/user/company'
+const companyStore = CompanyStore()
+import { CompetitionStore } from '@/store/api/user/competition'
+const competitionStore = CompetitionStore()
+import { IncubatorStore } from '@/store/api/user/incubator'
+const incubatorStore = IncubatorStore()
+import { InvestmentStore } from '@/store/api/user/investment'
+const investmentStore = InvestmentStore()
+import { StateStore } from '@/store/api/user/state'
+const stateStore = StateStore()
 const { t } = useI18n()
 const loading = ref(false)
 let skip = 0
 let limit = inject('limit')
 const data = ref([])
 const total = ref(0)
+const type = ref('User')
+const role = ref([])
 onMounted(async () => {
   loading.value = true
   await searchOther()
@@ -51,20 +128,23 @@ const fields = [
   { label: t('pages.user.account'), model: 'account', filter: true },
   { label: t('pages.user.nick_name'), model: 'nick_name' },
   { label: t('pages.user.phone'), model: 'phone' },
-  { label: t('pages.user.role'), model: 'role', format: (i) => getRole(i) },
+  { label: t('pages.user.role'), model: 'role', custom: true },
   { label: t('pages.user.status'), model: 'status', format: (i) => getDict(i) }
 ]
 const opera = [
   { label: t('common.view'), method: 'view' },
-  { label: t('common.exam'), method: 'exam', type: 'warning', display: (i) => i.status === '0' },
-  { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger', display: (i) => i.status === '-1' }
+  { label: t('common.exam'), method: 'exam', type: 'warning' },
+  {
+    label: t('common.delete'),
+    method: 'delete',
+    confirm: true,
+    type: 'danger',
+    display: (i) => i.status === '-1'
+  }
 ]
 const searchForm = ref({})
 const dialog = ref({ type: '1', show: false, title: t('pages.user.dialogTitle') })
-// 审核
-const examFormFields = [{ label: t('pages.user.status'), model: 'status', type: 'select' }]
-const examRules = reactive({ status: [{ required: true, message: t('common.statusMessage'), trigger: 'blur' }] })
-const examForm = ref({})
+// 查询
 const search = async (query = { skip: 0, limit }) => {
   const info = { skip: query.skip, limit: query.limit, ...searchForm.value }
   const res = await store.query(info)
@@ -73,9 +153,28 @@ const search = async (query = { skip: 0, limit }) => {
     total.value = res.total
   }
 }
+// 表单验证
+const ruleFormRef = ref()
+const form = ref({})
+// 审核
+const examFormFields = [{ label: t('pages.user.status'), model: 'status', type: 'select' }]
+const examRules = reactive({
+  status: [{ required: true, message: t('common.statusMessage'), trigger: 'blur' }]
+})
+const examForm = ref({})
+// 字典表
 const statusList = ref([])
 const roleList = ref([])
 const genderList = ref([])
+const fieldList = ref([])
+const educationList = ref([])
+const cityList = ref([])
+const isUseList = ref([])
+const patternList = ref([])
+const scaleList = ref([])
+const IndustryList = ref([])
+const cardTypeList = ref([])
+const contributionList = ref([])
 const searchOther = async () => {
   let result
   // 状态
@@ -87,6 +186,35 @@ const searchOther = async () => {
   // 角色
   result = await roleStore.query({ is_use: '0' })
   if ($checkRes(result)) roleList.value = result.data
+  // 专家领域
+  result = await dictDataStore.query({ code: 'field', is_use: '0' })
+  if ($checkRes(result)) fieldList.value = result.data
+  // 企业类型
+  result = await dictDataStore.query({ code: 'companyType', is_use: '0' })
+  if ($checkRes(result)) patternList.value = result.data
+  // 企业规模
+  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 dictDataStore.query({ code: 'education', is_use: '0' })
+  if ($checkRes(result)) educationList.value = result.data
+  // 证件类型
+  result = await dictDataStore.query({ code: 'cardType', is_use: '0' })
+  if ($checkRes(result)) cardTypeList.value = result.data
+  // 出资方式
+  result = await dictDataStore.query({ code: 'contribution', is_use: '0' })
+  if ($checkRes(result)) contributionList.value = result.data
+  // 是否使用
+  result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
+  if ($checkRes(result)) isUseList.value = result.data
+  // 城市
+  getCity().then((response) => (cityList.value = response.address))
+  // 角色
+  result = await roleStore.query({ is_use: '0' })
+  if ($checkRes(result)) roleList.value = result.data
 }
 
 const toDelete = async (data) => {
@@ -95,20 +223,48 @@ const toDelete = async (data) => {
     search({ skip: 0, limit })
   }
 }
-const form = ref({})
-const formFields = ref([])
-const formFieldsForUpdate = [
-  { label: t('pages.user.account'), model: 'account' },
-  { label: t('pages.user.nick_name'), model: 'nick_name' },
-  { label: t('pages.user.gender'), model: 'gender', type: 'select' },
-  { label: t('pages.user.phone'), model: 'phone' },
-  { label: t('pages.user.role'), model: 'role', custom: true }
-]
-const toView = (data) => {
-  formFields.value = cloneDeep(formFieldsForUpdate)
+const getRole = (data) => {
+  const res = roleList.value.find((f) => f.code === data)
+  return get(res, 'name')
+}
+const getDict = (data) => {
+  const res = statusList.value.find((f) => f.value == data)
+  return get(res, 'label')
+}
+// 查看
+const toView = async (data) => {
   form.value = data
+  role.value = get(data, 'role')
   dialog.value = { type: '1', show: true, title: t('pages.user.dialogTitle') }
 }
+// 标签改变
+const toChang = async (name) => {
+  let result
+  if (name == 'User') {
+    result = await store.fetch(form.value.user)
+    if ($checkRes(result)) form.value = result.data
+  } else {
+    if (name == 'Expert') {
+      result = await expertStore.query({ user: form.value._id })
+    } else if (name == 'Company') {
+      result = await companyStore.query({ user: form.value._id })
+    } else if (name == 'Unit') {
+      result = await unitStore.query({ user: form.value._id })
+    } else if (name == 'Association') {
+      result = await associationStore.query({ user: form.value._id })
+    } else if (name == 'Competition') {
+      result = await competitionStore.query({ user: form.value._id })
+    } else if (name == 'Incubator') {
+      result = await incubatorStore.query({ user: form.value._id })
+    } else if (name == 'Investment') {
+      result = await investmentStore.query({ user: form.value._id })
+    } else if (name == 'State') {
+      result = await stateStore.query({ user: form.value._id })
+    }
+    if ($checkRes(result)) form.value = result.data[0] || {}
+  }
+}
+
 // 审核
 const toExam = (data) => {
   examForm.value = data
@@ -123,21 +279,10 @@ const toExamSave = async () => {
     toClose()
   }
 }
-const getRole = (data) => {
-  const list = []
-  for (const val of data) {
-    const res = roleList.value.find((f) => f.code === val)
-    list.push(get(res, 'name'))
-  }
-  return list.join(',')
-}
-const getDict = (data) => {
-  const res = statusList.value.find((f) => f.value == data)
-  return get(res, 'label')
-}
 const toClose = () => {
-  examForm.value = {}
   form.value = {}
+  type.value = 'User'
+  role.value = []
   dialog.value = { show: false }
 }
 // 重置
@@ -145,5 +290,30 @@ const toReset = async () => {
   searchForm.value = {}
   await search({ skip, limit })
 }
+// provide
+provide('cloneDeep', cloneDeep)
+provide('ruleFormRef ', ruleFormRef)
+provide('form', form)
+// 字典
+provide('statusList', statusList)
+provide('genderList', genderList)
+provide('fieldList', fieldList)
+provide('educationList', educationList)
+provide('cityList', cityList)
+provide('isUseList', isUseList)
+provide('patternList', patternList)
+provide('scaleList', scaleList)
+provide('IndustryList', IndustryList)
+provide('cardTypeList', cardTypeList)
+provide('contributionList', contributionList)
+// 方法
+provide('getRole', getRole)
 </script>
-<style scoped></style>
+<style scoped lang="scss">
+.tags {
+  display: flex;
+  justify-content: center;
+  grid-gap: 0.5rem;
+  gap: 0.5rem;
+}
+</style>

+ 68 - 0
src/views/user/user/parts/association.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      label-width="90px"
+      class="form"
+      label-position="left"
+      disabled
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="商协会名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入商协会名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="负责人姓名" prop="person">
+            <el-input v-model="form.person" placeholder="请输入负责人姓名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="负责人电话" prop="person_phone">
+            <el-input v-model="form.person_phone" placeholder="请输入负责人电话" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否公开" prop="is_show">
+            <el-radio-group v-model="form.is_show">
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="地址" prop="address">
+          <el-input
+            v-model="form.address"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入地址"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const isUseList = inject('isUseList')
+</script>
+<style scoped lang="scss"></style>

+ 165 - 0
src/views/user/user/parts/company.vue

@@ -0,0 +1,165 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      :rules="rules"
+      label-width="100px"
+      class="form"
+      label-position="left"
+    >
+      <el-row>
+        <el-form-item label="企业Logo" prop="logo">
+          <custom-upload
+            model="logo"
+            :list="form.logo"
+            :limit="1"
+            url="/files/web/template/company/upload"
+            @change="onFUpload"
+            listType="picture-card"
+          ></custom-upload>
+        </el-form-item>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="企业名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入企业名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="企业类型" prop="pattern">
+            <el-select clearable v-model="form.pattern" placeholder="请选择企业类型">
+              <el-option
+                v-for="(item, index) in patternList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="企业规模" prop="scale">
+            <el-select clearable v-model="form.scale" placeholder="请选择企业规模">
+              <el-option
+                v-for="item in scaleList"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="统一信用代码" prop="code">
+            <el-input v-model="form.code" placeholder="请输入统一信用代码" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="所属行业" prop="type">
+            <el-select clearable v-model="form.type" placeholder="请选择所属行业">
+              <el-option
+                v-for="(item, index) in IndustryList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="所在地区" prop="region">
+            <el-cascader
+              v-model="form.area"
+              :props="{ value: 'label', label: 'label' }"
+              :options="cityList"
+              clearable
+              placeholder="请选择所在地区"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="法定代表人" prop="representative">
+            <el-input v-model="form.representative" placeholder="请输入法定代表人名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="电子邮箱" prop="email">
+            <el-input v-model="form.email" type="email" placeholder="请输入电子邮箱" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="员工人数" prop="person">
+            <el-input v-model="form.person" placeholder="请输入员工人数" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="注册资本" prop="register">
+            <el-input v-model="form.register" placeholder="请输入注册资本(万元)" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="成立时间" prop="create_time">
+            <el-date-picker
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              v-model="form.create_time"
+              type="date"
+              placeholder="请选择成立时间"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="企业地址" prop="address">
+            <el-input v-model="form.address" placeholder="请输入企业地址" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="是否公开" prop="is_show">
+          <el-radio-group v-model="form.is_show">
+            <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const patternList = inject('patternList')
+const scaleList = inject('scaleList')
+const IndustryList = inject('IndustryList')
+const cityList = inject('cityList')
+const isUseList = inject('isUseList')
+// 上传图片
+const onFUpload = (e) => {
+  const { model, value } = e
+  form.value[model] = value
+}
+</script>
+<style scoped lang="scss"></style>

+ 68 - 0
src/views/user/user/parts/competition.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      label-width="90px"
+      class="form"
+      label-position="left"
+      disabled
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="负责人姓名" prop="person">
+            <el-input v-model="form.person" placeholder="请输入负责人姓名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="负责人电话" prop="person_phone">
+            <el-input v-model="form.person_phone" placeholder="请输入负责人电话" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否公开" prop="is_show">
+            <el-radio-group v-model="form.is_show">
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="地址" prop="address">
+          <el-input
+            v-model="form.address"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入地址"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const isUseList = inject('isUseList')
+</script>
+<style scoped lang="scss"></style>

+ 124 - 0
src/views/user/user/parts/expert.vue

@@ -0,0 +1,124 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      label-width="80px"
+      class="form"
+      label-position="left"
+      disabled
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="专家姓名" prop="name">
+            <el-input v-model="form.name" placeholder="请输入专家姓名" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="出生年月" prop="birth">
+            <el-date-picker
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              v-model="form.birth"
+              type="date"
+              placeholder="请选择出生年月"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="证件类型" prop="cardType">
+            <el-select clearable v-model="form.cardType" placeholder="请选择证件类型">
+              <el-option
+                v-for="(item, index) in cardTypeList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="证件号码" prop="card">
+            <el-input v-model="form.card" placeholder="请输入证件号码" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="擅长领域" prop="field">
+            <el-select clearable v-model="form.field" placeholder="请选择擅长领域">
+              <el-option
+                v-for="(item, index) in fieldList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="研究方向" prop="direction">
+            <el-input v-model="form.direction" placeholder="请输入研究方向" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="最高学历" prop="education">
+            <el-select clearable v-model="form.education" placeholder="请选择最高学历">
+              <el-option
+                v-for="(item, index) in educationList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="所在地区" prop="region">
+            <el-cascader
+              v-model="form.area"
+              :props="{ value: 'label', label: 'label' }"
+              :options="cityList"
+              clearable
+              placeholder="请选择所在地区"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="是否公开" prop="is_show">
+          <el-radio-group v-model="form.is_show">
+            <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const fieldList = inject('fieldList')
+const educationList = inject('educationList')
+const cityList = inject('cityList')
+const isUseList = inject('isUseList')
+const cardTypeList = inject('cardTypeList')
+</script>
+<style scoped lang="scss"></style>

+ 68 - 0
src/views/user/user/parts/incubator.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      label-width="90px"
+      class="form"
+      label-position="left"
+      disabled
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="孵化器名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入孵化器名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="负责人姓名" prop="person">
+            <el-input v-model="form.person" placeholder="请输入负责人姓名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="负责人电话" prop="person_phone">
+            <el-input v-model="form.person_phone" placeholder="请输入负责人电话" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否公开" prop="is_show">
+            <el-radio-group v-model="form.is_show">
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="地址" prop="address">
+          <el-input
+            v-model="form.address"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入地址"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const isUseList = inject('isUseList')
+</script>
+<style scoped lang="scss"></style>

+ 97 - 0
src/views/user/user/parts/investment.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      label-width="80px"
+      class="form"
+      label-position="left"
+      disabled
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="姓名" prop="name">
+            <el-input v-model="form.name" placeholder="请输入姓名" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="出资额" prop="money">
+            <el-input v-model="form.money" placeholder="请输入出资额(万元)" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="证件类型" prop="cardType">
+            <el-select clearable v-model="form.cardType" placeholder="请选择证件类型">
+              <el-option
+                v-for="(item, index) in cardTypeList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="证件号码" prop="card">
+            <el-input v-model="form.card" placeholder="请输入证件号码" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="出资方式" prop="type">
+            <el-select clearable v-model="form.type" placeholder="请选择出资方式">
+              <el-option
+                v-for="(item, index) in contributionList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否公开" prop="is_show">
+            <el-radio-group v-model="form.is_show">
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="地址" prop="address">
+          <el-input
+            v-model="form.address"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入地址"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const cardTypeList = inject('cardTypeList')
+const isUseList = inject('isUseList')
+const contributionList = inject('contributionList')
+
+</script>
+<style scoped lang="scss"></style>

+ 82 - 0
src/views/user/user/parts/state.vue

@@ -0,0 +1,82 @@
+<template>
+  <div class="index">
+    <el-form
+      ref="ruleFormRef"
+      :model="form"
+      label-width="90px"
+      class="form"
+      label-position="left"
+      disabled
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="负责人姓名" prop="person">
+            <el-input v-model="form.person" placeholder="请输入负责人姓名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="负责人电话" prop="person_phone">
+            <el-input v-model="form.person_phone" placeholder="请输入负责人电话" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="部门类型" prop="type">
+            <el-select clearable v-model="form.type" placeholder="请选择部门类型">
+              <el-option
+                v-for="(item, index) in typeList"
+                :key="index"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="是否公开" prop="is_show">
+            <el-radio-group v-model="form.is_show">
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="地址" prop="address">
+          <el-input
+            v-model="form.address"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入地址"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 表单
+const form = inject('form')
+// 字典表
+const isUseList = inject('isUseList')
+</script>
+<style scoped lang="scss"></style>

+ 60 - 0
src/views/user/user/parts/unit.vue

@@ -0,0 +1,60 @@
+<template>
+  <div class="index">
+    <el-form ref="ruleFormRef" :model="form" label-width="90px" class="form" label-position="left">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="名称" prop="name">
+            <el-input v-model="form.name" placeholder="请输入名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="负责人姓名" prop="person">
+            <el-input v-model="form.person" placeholder="请输入负责人姓名" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="负责人电话" prop="person_phone">
+            <el-input v-model="form.person_phone" placeholder="请输入负责人电话" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="是否公开" prop="is_show">
+            <el-radio-group v-model="form.is_show">
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{
+                i.label
+              }}</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-col :span="24">
+        <el-form-item label="地址" prop="address">
+          <el-input
+            v-model="form.address"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入地址"
+          />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="简介" prop="brief">
+          <el-input
+            v-model="form.brief"
+            :autosize="{ minRows: 2, maxRows: 4 }"
+            type="textarea"
+            placeholder="请输入简介"
+          />
+        </el-form-item>
+      </el-col>
+    </el-form>
+  </div>
+</template>
+<script setup>
+// 字典表
+const isUseList = inject('isUseList')
+const form = ref({})
+</script>
+<style scoped lang="scss"></style>

+ 45 - 0
src/views/user/user/parts/user.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="index">
+    <custom-form v-model="form" :fields="formFields" :useSave="false">
+      <template #role>
+        <div class="tags">
+          <el-tag v-for="(item, index) in form.role" :key="index" type="primary">{{
+            getRole(item)
+          }}</el-tag>
+        </div>
+      </template>
+      <template #gender>
+        <el-option
+          disabled
+          v-for="i in genderList"
+          :key="i._id"
+          :label="i.label"
+          :value="i.value"
+        ></el-option>
+      </template>
+    </custom-form>
+  </div>
+</template>
+<script setup>
+// 基础
+const { t } = useI18n()
+const form = inject('form')
+const getRole = inject('getRole')
+const formFields = ref([
+  { label: t('pages.user.account'), model: 'account', options: { readonly: true } },
+  { label: t('pages.user.nick_name'), model: 'nick_name', options: { readonly: true } },
+  { label: t('pages.user.gender'), model: 'gender', type: 'select' },
+  { label: t('pages.user.phone'), model: 'phone', options: { readonly: true } },
+  { label: t('pages.user.role'), model: 'role', custom: true }
+])
+// 字典表
+const genderList = inject('genderList')
+</script>
+<style scoped lang="scss">
+.tags {
+  display: flex;
+  justify-content: center;
+  grid-gap: 0.5rem;
+  gap: 0.5rem;
+}
+</style>