zs 1 year ago
parent
commit
fcc13132f6

+ 2 - 0
.env.development

@@ -6,3 +6,5 @@ VITE_APP_PORT = 3000
 
 # 代理前缀
 VITE_APP_BASE_API = '/ts/frame/api'
+
+VITE_APP_HOST = "http://192.168.1.197"

+ 1 - 0
.env.production

@@ -7,3 +7,4 @@ VITE_APP_PORT = 3000
 # 代理前缀
 VITE_APP_BASE_API = '/prod-api'
 
+VITE_APP_HOST = "https://broadcast.waityou24.cn"

+ 1 - 1
package-lock.json

@@ -10,9 +10,9 @@
       "dependencies": {
         "@element-plus/icons-vue": "^2.3.1",
         "@vueuse/core": "^10.7.2",
+        "@vueuse/integrations": "^10.9.0",
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "5.1.10",
-        "@vueuse/integrations": "^10.9.0",
         "axios": "^1.6.7",
         "element-plus": "^2.5.6",
         "lodash-es": "^4.17.21",

+ 8 - 22
src/components/WangEditor/index.vue

@@ -8,9 +8,11 @@
 </template>
 
 <script setup>
-import Axios from 'axios'
 import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
-const $checkRes = inject('$checkRes')
+
+// API 引用
+import { uploadFileApi } from '@/utils/file'
+
 const props = defineProps({
   modelValue: {
     type: [String],
@@ -32,27 +34,11 @@ const editorConfig = ref({
     uploadImage: {
       // 自定义图片上传
       async customUpload(file, insertFn) {
-        const formData = new FormData()
-        formData.append('file', file)
-        const axios = Axios.create({
-          baseURL: 'http://192.168.1.197'
+        uploadFileApi(file).then((response) => {
+          const { errcode, uri } = response.data
+          const url = `${import.meta.env.VITE_APP_HOST}${uri}`
+          if (errcode === 0) insertFn(url)
         })
-        const res = await axios.request({
-          url: '/files',
-          method: 'post',
-          data: formData,
-          headers: {
-            'Content-Type': 'multipart/form-data'
-          }
-        })
-        if ($checkRes(res, true)) {
-          console.log(res)
-        }
-
-        // uploadFileApi(file).then((response) => {
-        //   const url = response.data.url
-        //   insertFn(url)
-        // })
       }
     }
   }

+ 1 - 1
src/components/custom/custom-table.vue

@@ -16,7 +16,7 @@
             <slot v-bind="{ row }">
               <template v-for="f in opera">
                 <template v-if="display(f, row)">
-                  <el-link :key="f.method" :type="f.type || 'primary'" size="small" :underline="false" class="link" v-opera="f.method" @click="handleOpera(f, row, $index)">
+                  <el-link :key="f.method" :type="f.type || 'primary'" size="small" :underline="false" class="link" v-method="f.method" @click="handleOpera(f, row, $index)">
                     {{ f.label }}
                   </el-link>
                 </template>

+ 13 - 2
src/lang/package/zh-cn/menus.js

@@ -9,7 +9,18 @@ export default {
   system_dict_data: '字典数据',
   user_admin: '管理员用户',
   user_user: '平台用户',
-  platform: '平台管理',
+  user_unit: '科研机构',
+  user_company: '企业用户',
+  user_expert: '专家用户',
+  platform: '信息管理',
   platform_policy: '政策法规',
-  platform_news: '新闻资讯'
+  platform_news: '新闻资讯',
+  platform_demand: '供需管理',
+  platform_match: '赛事管理',
+  platform_achievement: '成果管理',
+  demand_supply: '供给信息管理',
+  demand_demand: '需求信息管理',
+  match: '赛事管理',
+  achievement: '成果管理',
+  password: '修改密码'
 }

+ 15 - 0
src/lang/package/zh-cn/pages.js

@@ -82,5 +82,20 @@ export default {
     content: '内容',
     is_use: '是否启用',
     titleMessage: '请输入标题'
+  },
+  demand: {
+    addDialogTitle: '新增需求',
+    upDialogTitle: '修改需求',
+    name: '需求名称',
+    field: '行业领域',
+    urgent: '需求紧急度',
+    method: '合作方式',
+    time: '有效期',
+    money: '价格',
+    province: '省',
+    city: '市',
+    brief: '简介',
+    is_use: '是否启用',
+    titleMessage: '请输入需求名称'
   }
 }

+ 13 - 3
src/layout/parts/sidebar/items.vue

@@ -3,7 +3,7 @@
     <template v-if="item.type === '0'">
       <el-sub-menu :index="item._id" :key="item._id">
         <template #title>
-          <i :class="['iconfont', item.icon]"></i>
+          <component class="icon" :is="item.icon"></component>
           <span>{{ $t(item.i18n_code) }}</span>
         </template>
         <menu-item :items="item.children"></menu-item>
@@ -11,7 +11,7 @@
     </template>
     <template v-else-if="item.type === '1'">
       <el-menu-item :index="item.path" :key="item.path">
-        <i :class="['iconfont', item.icon]"></i>
+        <component class="icon" :is="item.icon"></component>
         <span>{{ $t(item.i18n_code) }}</span>
       </el-menu-item>
     </template>
@@ -27,4 +27,14 @@ export default {
 }
 </script>
 
-<style scoped></style>
+<style scoped lang="scss">
+.icon {
+  display: inline-block;
+  width: 1em;
+  height: 1em;
+  overflow: hidden;
+  vertical-align: -0.15em;
+  outline: none;
+  margin-right: 5px;
+}
+</style>

+ 40 - 0
src/store/api/platform/demand.js

@@ -0,0 +1,40 @@
+import { defineStore } from 'pinia'
+import { AxiosWrapper } from '@/utils/axios-wrapper'
+import { get } from 'lodash-es'
+const url = '/demand'
+const axios = new AxiosWrapper()
+
+export const DemandStore = defineStore('demand', () => {
+  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
+  }
+})

+ 26 - 0
src/utils/file.js

@@ -0,0 +1,26 @@
+import Axios from 'axios'
+/**
+ * 上传文件
+ *
+ * @param file
+ */
+export async function uploadFileApi(file) {
+  const formData = new FormData()
+  formData.append('file', file)
+  const axios = Axios.create({
+    baseURL: '/files',
+    withCredentials: true
+  })
+  const token = localStorage.getItem('token')
+  const apiToken = localStorage.getItem('apiToken')
+  if (token) axios.defaults.headers.common['token'] = token
+  if (apiToken) axios.defaults.headers.common['api-token'] = apiToken
+  return await axios.request({
+    url: '/web/template/upload',
+    method: 'post',
+    data: formData,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
+}

+ 20 - 0
src/views/acccount/updatepd/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 修改密码 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>

+ 20 - 0
src/views/achievement/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 成果管理 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>

+ 20 - 0
src/views/match/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 赛事管理 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>

+ 20 - 0
src/views/platform/demand/demand/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 需求信息管理 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>

+ 131 - 0
src/views/platform/demand/supply/index.vue

@@ -0,0 +1,131 @@
+<template>
+  <div class="main animate__animated animate__backInRight" v-loading="loading">
+    <custom-search-bar :fields="fields.filter((f) => f.isSearch)" v-model="searchForm" @search="search" @reset="toReset"></custom-search-bar>
+    <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </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" :rules="rules" @save="toSave">
+            <template #is_use>
+              <el-radio v-for="i in isUseList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
+            </template>
+          </custom-form>
+        </el-col>
+      </el-row>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { cloneDeep, get } from 'lodash-es'
+const $checkRes = inject('$checkRes')
+const { t } = useI18n()
+// 接口
+import { DemandStore } from '@/store/api/platform/demand'
+import { DictDataStore } from '@/store/api/system/dictData'
+const store = DemandStore()
+const dictDataStore = DictDataStore()
+const data = ref([])
+const searchForm = ref({})
+const fields = [
+  { label: t('pages.demand.name'), model: 'name', isSearch: true },
+  { label: t('pages.demand.field'), model: 'field', isSearch: true },
+  { label: t('pages.demand.urgent'), model: 'urgent', isSearch: true },
+  { label: t('pages.demand.method'), model: 'method' },
+  { label: t('pages.demand.money'), model: 'money' },
+  { label: t('pages.demand.is_use'), model: 'is_use', custom: true, format: (i) => getDict(i) }
+]
+const opera = [
+  { label: t('common.update'), method: 'edit' },
+  { label: t('common.delete'), method: 'delete', confirm: true, type: 'danger' }
+]
+const buttonFields = [{ label: t('common.add'), method: 'add' }]
+let skip = 0
+let limit = inject('limit')
+const total = ref(20)
+const isUseList = ref([])
+// 加载中
+const loading = ref(false)
+const formFields = ref([
+  { label: t('pages.demand.name'), model: 'name' },
+  { label: t('pages.demand.field'), model: 'field' },
+  { label: t('pages.demand.urgent'), model: 'urgent' },
+  { label: t('pages.demand.method'), model: 'method' },
+  { label: t('pages.demand.money'), model: 'money' },
+  { label: t('pages.demand.province'), model: 'money' },
+  { label: t('pages.demand.time'), model: 'time', type: 'daterange' },
+  { label: t('pages.demand.is_use'), model: 'is_use', type: 'radio' },
+  { label: t('pages.demand.brief'), model: 'brief', type: 'textarea' }
+])
+const rules = reactive({ name: [{ required: true, message: t('pages.demand.titleMessage'), trigger: 'blur' }] })
+const dialog = ref({ type: '1', show: false, title: t('pages.demand.addDialogTitle') })
+const form = ref({})
+// 请求
+onMounted(async () => {
+  loading.value = true
+  await searchOther()
+  await search({ skip, limit })
+  loading.value = false
+})
+
+const searchOther = async () => {
+  const result = await dictDataStore.query({ code: 'isUse', is_use: '0' })
+  if ($checkRes(result)) isUseList.value = result.data
+}
+const search = async (query = { skip: 0, limit }) => {
+  const info = { skip: query.skip, limit: query.limit, ...searchForm.value, type: '0' }
+  const res = await store.query(info)
+  if (res.errcode == '0') {
+    data.value = res.data
+    total.value = res.total
+  }
+}
+// 字典数据转换
+const getDict = (data) => {
+  const res = isUseList.value.find((f) => f.value == data)
+  return get(res, 'label')
+}
+// 添加
+const toAdd = () => {
+  form.value = { type: '0' }
+  dialog.value = { type: '1', show: true, title: t('pages.demand.addDialogTitle') }
+}
+// 修改
+const toEdit = (data) => {
+  form.value = data
+  dialog.value = { type: '1', show: true, title: t('pages.demand.upDialogTitle') }
+}
+// 删除
+const toDelete = async (data) => {
+  const res = await store.del(data._id)
+  if ($checkRes(res, true)) {
+    search({ skip: 0, limit })
+  }
+}
+const toSave = async () => {
+  const data = cloneDeep(form.value)
+  let res
+  if (get(data, '_id')) res = await store.update(data)
+  else res = await store.create(data)
+  if ($checkRes(res, true)) {
+    search({ skip: 0, limit })
+    toClose()
+  }
+}
+// 重置
+const toReset = async () => {
+  searchForm.value = {}
+  await search({ skip, limit })
+}
+const toClose = () => {
+  form.value = {}
+  dialog.value = { show: false }
+}
+</script>
+<style scoped lang="scss"></style>

+ 7 - 2
src/views/platform/news/index.vue

@@ -2,7 +2,12 @@
   <div class="main animate__animated animate__backInRight" v-loading="loading">
     <custom-search-bar :fields="fields.filter((f) => f.isSearch)" v-model="searchForm" @search="search" @reset="toReset"></custom-search-bar>
     <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
-    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete"></custom-table>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </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'">
@@ -40,7 +45,7 @@ const fields = [
   { label: t('pages.news.person'), model: 'person', isSearch: true },
   { label: t('pages.news.time'), model: 'time', type: 'date', isSearch: true },
   { label: t('pages.news.number'), model: 'number' },
-  { label: t('pages.news.is_use'), model: 'is_use', format: (i) => getDict(i) }
+  { label: t('pages.news.is_use'), model: 'is_use', custom: true, format: (i) => getDict(i) }
 ]
 const opera = [
   { label: t('common.update'), method: 'edit' },

+ 7 - 2
src/views/platform/policy/index.vue

@@ -2,7 +2,12 @@
   <div class="main animate__animated animate__backInRight" v-loading="loading">
     <custom-search-bar :fields="fields.filter((f) => f.isSearch)" v-model="searchForm" @search="search" @reset="toReset"></custom-search-bar>
     <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
-    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete"></custom-table>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </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'">
@@ -40,7 +45,7 @@ const fields = [
   { label: t('pages.news.person'), model: 'person', isSearch: true },
   { label: t('pages.news.time'), model: 'time', type: 'date', isSearch: true },
   { label: t('pages.news.number'), model: 'number' },
-  { label: t('pages.news.is_use'), model: 'is_use', format: (i) => getDict(i) }
+  { label: t('pages.news.is_use'), model: 'is_use', custom: true, format: (i) => getDict(i) }
 ]
 const opera = [
   { label: t('common.update'), method: 'edit' },

+ 7 - 2
src/views/system/dict/index.vue

@@ -2,7 +2,12 @@
   <div class="main animate__animated animate__backInRight" v-loading="loading">
     <custom-search-bar :fields="fields.filter((f) => f.isSearch)" v-model="searchForm" @search="search" @reset="toReset"></custom-search-bar>
     <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
-    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @dict="toDict" @edit="toEdit" @delete="toDelete"></custom-table>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @dict="toDict" @edit="toEdit" @delete="toDelete">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </template>
+    </custom-table>
     <el-dialog v-model="dialog.show" :title="dialog.title" :destroy-on-close="false" @close="toClose" :top="dialog.top">
       <el-row>
         <el-col :span="24" v-if="dialog.type == '1'">
@@ -35,7 +40,7 @@ const searchForm = ref({})
 const fields = [
   { label: t('pages.dict.title'), model: 'title', isSearch: true },
   { label: t('pages.dict.code'), model: 'code', isSearch: true },
-  { label: t('pages.dict.is_use'), model: 'is_use', format: (i) => getDict(i) },
+  { label: t('pages.dict.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true },
   { label: t('pages.dict.remark'), model: 'remark' }
 ]
 const opera = [

+ 7 - 2
src/views/system/dictData/index.vue

@@ -2,7 +2,12 @@
   <div class="main animate__animated animate__backInRight" v-loading="loading">
     <custom-search-bar :fields="fields.filter((f) => f.isSearch)" v-model="searchForm" @search="search" @reset="toReset"></custom-search-bar>
     <custom-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
-    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete"></custom-table>
+    <custom-table :data="data" :fields="fields" @query="search" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </template>
+    </custom-table>
     <el-dialog v-model="dialog" :title="$t('pages.dictData.dialogTitle')" :destroy-on-close="false" @close="toClose" width="30%">
       <custom-form v-model="form" :fields="formFields" :rules="rules" @save="toSave">
         <template #is_use>
@@ -26,7 +31,7 @@ const fields = [
   { label: t('pages.dictData.label'), model: 'label', isSearch: true },
   { label: t('pages.dictData.value'), model: 'value' },
   { label: t('pages.dictData.sort'), model: 'sort' },
-  { label: t('pages.dictData.is_use'), model: 'is_use', format: (i) => getDict(i) }
+  { label: t('pages.dict.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true }
 ]
 const opera = [
   { label: t('common.update'), method: 'edit' },

+ 11 - 4
src/views/system/menus/index.vue

@@ -19,9 +19,11 @@ import menuTable from './parts/menu-table.vue'
 import menuInfo from './parts/menu-info.vue'
 import { cloneDeep, get, omit } from 'lodash-es'
 import { MenusStore } from '@/store/api/system/menus'
+import { DictDataStore } from '@/store/api/system/dictData'
 import { useI18n } from 'vue-i18n'
 const { t } = useI18n
 const store = MenusStore()
+const dictDataStore = DictDataStore()
 const $checkRes = inject('$checkRes')
 const dialog = ref(false)
 const list = ref([])
@@ -31,11 +33,15 @@ const typeList = [
   { label: '菜单', value: '1' },
   { label: '子页面', value: '2' }
 ]
-
-onMounted(() => {
-  search()
+const iconList = ref([])
+onMounted(async () => {
+  await searchOther()
+  await search()
 })
-
+const searchOther = async () => {
+  const result = await dictDataStore.query({ code: 'icon', is_use: '0' })
+  if ($checkRes(result)) iconList.value = result.data
+}
 // #region 接口函数
 const search = async () => {
   const res = await store.query()
@@ -97,6 +103,7 @@ provide('toUpdate', toUpdate)
 provide('toAddNext', toAddNext)
 provide('toDelete', toDelete)
 provide('toSave', toSave)
+provide('iconList', iconList)
 </script>
 
 <style scoped></style>

+ 4 - 1
src/views/system/menus/parts/menu-table.vue

@@ -16,7 +16,10 @@
         <template #default="{ row }">{{ getType(row) }} </template>
       </el-table-column>
       <el-table-column align="center" :label="$t('pages.menus.is_use')" prop="is_use" width="80">
-        <template #default="{ row }">{{ getStatus(row) }} </template>
+        <template #default="{ row }">
+          <el-tag v-if="row.is_use === '0'" type="success"> {{ getStatus(row) }} </el-tag>
+          <el-tag v-else type="info"> {{ getStatus(row) }} </el-tag>
+        </template>
       </el-table-column>
       <el-table-column align="center" :label="$t('pages.menus.remark')" prop="remark" width="100"> </el-table-column>
       <el-table-column align="center" :label="$t('common.opera')">

+ 18 - 5
src/views/system/menus/parts/parts/info.vue

@@ -39,10 +39,12 @@
     </el-form-item>
     <el-form-item :label="$t('pages.menus.icon')">
       <el-select v-model="form.icon" clearable filterable :placeholder="$t('pages.menus.iconPh')">
-        <!-- <el-option v-for="item in iconList" :key="item.dict_label" :label="item.dict_label" :value="item.dict_label">
-          <span style="float: left" :class="['iconfont', item.dict_label]"></span>
-          <span style="float: right; color: #8492a6; font-size: 13px">{{ item.dict_label }}</span>
-        </el-option> -->
+        <el-option v-for="item in iconList" :key="item.label" :label="item.label" :value="item.label">
+          <div>
+            <component class="icon" :is="item.label"></component>
+            <span style="font-size: 12px">{{ item.label }}</span>
+          </div>
+        </el-option>
       </el-select>
     </el-form-item>
     <el-form-item :label="$t('pages.menus.is_use')">
@@ -62,6 +64,7 @@ import { cloneDeep } from 'lodash-es'
 const menuTree = inject('menuTree')
 const typeList = inject('typeList')
 const form = inject('form')
+const iconList = inject('iconList')
 const is_dev = import.meta.env.MODE === 'development'
 
 // #region 整理数组
@@ -85,4 +88,14 @@ const getAllChild = (children) => {
 }
 // #endregion
 </script>
-<style scoped></style>
+<style scoped lang="scss">
+.icon {
+  display: inline-block;
+  width: 1em;
+  height: 1em;
+  overflow: hidden;
+  vertical-align: -0.15em;
+  outline: none;
+  margin-right: 5px;
+}
+</style>

+ 4 - 1
src/views/system/role/parts/table.vue

@@ -3,7 +3,10 @@
     <el-table-column align="center" :label="$t('pages.role.name')" prop="name"></el-table-column>
     <el-table-column align="center" :label="$t('pages.role.code')" prop="code"></el-table-column>
     <el-table-column align="center" :label="$t('pages.role.is_use')" prop="is_use">
-      <template #default="{ row }">{{ getStatus(row) }} </template>
+      <template #default="{ row }">
+        <el-tag v-if="row.is_use === '0'" type="success"> {{ getStatus(row) }} </el-tag>
+        <el-tag v-else type="info"> {{ getStatus(row) }} </el-tag>
+      </template>
     </el-table-column>
     <el-table-column align="center" :label="$t('common.opera')">
       <template #default="{ row }">

+ 7 - 2
src/views/user/admin/index.vue

@@ -2,7 +2,12 @@
   <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-button-bar :fields="buttonFields" @add="toAdd"></custom-button-bar>
-    <custom-table :data="data" :fields="fields" @search="search" :total="total" :opera="opera" @edit="toEdit" @changeUse="toChangeUse" @delete="toDelete" @rp="toResetPwd"></custom-table>
+    <custom-table :data="data" :fields="fields" @search="search" :total="total" :opera="opera" @edit="toEdit" @changeUse="toChangeUse" @delete="toDelete" @rp="toResetPwd">
+      <template #is_use="{ row }">
+        <el-tag v-if="row.is_use == '0'" type="success">启用</el-tag>
+        <el-tag v-else type="info">禁用</el-tag>
+      </template>
+    </custom-table>
     <el-dialog v-model="dialog" :title="$t('pages.menus.dialogTitle')" :destroy-on-close="false" @close="toClose">
       <custom-form v-model="form" :fields="formFields" @save="toSave">
         <template #is_use>
@@ -45,7 +50,7 @@ const fields = [
   { label: t('pages.admin.nick_name'), model: 'nick_name' },
   { label: t('pages.admin.role'), model: 'role', format: (i) => getRole(i) },
   { label: t('pages.admin.is_super'), model: 'is_super', format: (i) => (i === '0' ? t('common.yes') : t('common.no')) },
-  { label: t('pages.admin.is_use'), model: 'is_use', format: (i) => getDict(i) }
+  { label: t('pages.admin.is_use'), model: 'is_use', format: (i) => getDict(i), custom: true }
 ]
 const opera = [
   { label: t('common.update'), method: 'edit', display: (i) => i.is_super !== '0' },

+ 20 - 0
src/views/user/company/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 企业 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>

+ 20 - 0
src/views/user/expert/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 专家 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>

+ 20 - 0
src/views/user/unit/index.vue

@@ -0,0 +1,20 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
+        <el-col :span="24" class="one"> 科研机构 </el-col>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+// 加载中
+const loading = ref(false)
+// 请求
+onMounted(async () => {
+  loading.value = true
+  loading.value = false
+})
+</script>
+<style scoped lang="scss"></style>