YY vor 2 Jahren
Ursprung
Commit
cdd56ec1e8

+ 161 - 0
index.vue

@@ -0,0 +1,161 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="search1" :form="searchForm" @onSubmit="toSearch" @toReset="toReset"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <cButton @toAdd="toAdd()"> </cButton>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <cTable :fields="fields" :opera="opera" :data="list" @query="search" :total="total" @edit="toEdit" @del="toDel" :select="false">
+            <template #dict_type="{ item, row }">
+              <template v-if="item.model === 'dict_type'">
+                <el-link size="mini" type="primary" @click="toType(row)">{{ getProps(row, item.model) }}</el-link>
+              </template>
+            </template>
+          </cTable>
+        </el-col>
+      </el-col>
+    </el-row>
+    <cDialog :dialog="dialog" @handleClose="toClose">
+      <template v-slot:info>
+        <cForm v-if="dialog.type == '1'" :span="24" :fields="formFields" :form="form" :rules="rules" @save="onSubmit">
+          <template #status>
+            <el-radio label="0">正常</el-radio>
+            <el-radio label="1">停用</el-radio>
+          </template>
+        </cForm>
+      </template>
+    </cDialog>
+  </div>
+</template>
+<script lang="ts" setup>
+import _ from 'lodash'
+import search1 from './parts/search-1.vue'
+import type { FormRules } from 'element-plus'
+import type { Ref } from 'vue'
+import { ref, onMounted, getCurrentInstance, reactive } from 'vue'
+import { ElMessage } from 'element-plus'
+import { useRouter } from 'vue-router'
+import { DictTypeStore } from '@common/src/stores/system/dictType' // 字典表
+import type { IQueryResult } from '@/util/types.util'
+const dictType = DictTypeStore()
+const router = useRouter()
+const { proxy } = getCurrentInstance() as any
+// 列表数据
+let list: Ref<any[]> = ref([])
+// 总数
+let total: Ref<number> = ref(0)
+let skip = 0
+let limit: number = proxy.$limit
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '字典名称', model: 'dict_name' },
+  { label: '字典类型', model: 'dict_type', custom: true },
+  { label: '状态', model: 'status', format: (i) => (i == '0' ? '正常' : '停用') },
+  { label: '备注', model: 'remark' }
+])
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '修改', method: 'edit' },
+  { label: '删除', method: 'del', confirm: true, type: 'danger' }
+])
+const dialog: Ref<{ type: string; show: boolean; title: string }> = ref({ type: '1', show: false, title: '信息管理' })
+let form: Ref<{}> = ref({})
+
+// 表单
+let formFields: Ref<any[]> = ref([
+  { label: '字典名称', model: 'dict_name' },
+  { label: '字典类型', model: 'dict_type' },
+  { label: '状态', model: 'status', type: 'radio' },
+  { label: '备注', model: 'remark', type: 'textarea' }
+])
+const rules = reactive<FormRules>({
+  dict_type: [{ required: true, message: '请输入字典类型', trigger: 'blur' }],
+  dict_label: [{ required: true, message: '请输入字典标签', trigger: 'blur' }],
+  dict_value: [{ required: true, message: '请输入字典键值', trigger: 'blur' }],
+  dict_sort: [{ required: true, message: '请输入显示排序', trigger: 'blur' }],
+  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
+})
+
+// 查询数据
+let searchForm: Ref<{}> = ref({})
+
+onMounted(async () => {
+  await search({ skip, limit })
+})
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  const { skip, limit } = e
+  const condition = _.cloneDeep(searchForm.value)
+  let info = { limit: limit, skip: skip, ...condition }
+  // let res: IQueryResult = await dictType.query(info)
+  // if (res.errcode == 0) {
+  //   list.value = res.data as any[]
+  //   total.value = res.total
+  // }
+}
+const toSearch = () => {
+  search({ skip, limit })
+}
+const toReset = () => {
+  searchForm.value = {}
+  search({ skip, limit })
+}
+// 新增
+const toAdd = () => {
+  dialog.value = { title: '信息管理', show: true, type: '1' }
+}
+// 修改
+const toEdit = async (data) => {
+  // let res: IQueryResult = await dictType.fetch(data._id)
+  // if (res.errcode == 0) {
+  //   form.value = res.data as {}
+  //   dialog.value = { title: '信息管理', show: true, type: '1' }
+  // }
+}
+// 提交
+const onSubmit = async (data) => {
+  // let res: IQueryResult
+  // if (data._id) res = await dictType.update(data)
+  // else res = await dictType.create(data)
+  // if (res.errcode == 0) {
+  //   ElMessage({ type: `success`, message: `维护信息成功` })
+  //   toClose()
+  // }
+}
+// 删除
+const toDel = async (data) => {
+  // let res: IQueryResult = await dictType.del(data._id)
+  // if (res.errcode == 0) {
+  //   ElMessage({ type: `success`, message: `刪除信息成功` })
+  //   search({ skip, limit })
+  // }
+}
+// 字典类型跳转
+const toType = (data) => {
+  router.push({ path: '/system/dict/detail', query: { id: data._id, dict_type: data.dict_type } })
+}
+// 弹框关闭
+const toClose = () => {
+  form.value = {}
+  searchForm.value = {}
+  dialog.value = { title: '信息管理', show: false, type: '1' }
+  search({ skip, limit })
+}
+const getProps = (data, prop) => {
+  return _.get(data, prop)
+}
+</script>
+<style lang="scss" scoped>
+.main {
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 2 - 0
src/main.ts

@@ -13,6 +13,8 @@ import locale from 'element-plus/lib/locale/lang/zh-cn'
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 // moment
 import moment from 'moment'
+// 图标
+import '@common/src/assets/icon/iconfont.css'
 
 const app = createApp(App)
 app.use(createPinia())

+ 39 - 3
src/router/index.ts

@@ -1,24 +1,60 @@
 import { createRouter, createWebHistory } from 'vue-router'
+import store from '@/stores/counter'
+import axios from 'axios'
+// 公共
+import common from './module/common'
+// 系统管理
+import system from './module/system'
+// 账号管理
+import account from './module/account'
+
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   routes: [
+    // 公共
+    ...common,
     {
       path: '/',
       redirect: '/homeIndex'
     },
     {
       path: '/homeIndex',
-      meta: { title: '基础研究动态管理平台', is_filter: true },
+      meta: { title: '中科在线(长春)', is_filter: true },
       component: () => import('@common/src/components/admin-frame/home.vue'),
       children: [
         {
           path: '/homeIndex',
-          meta: { title: '基础研究动态管理平台', is_filter: true },
+          meta: { title: '中科在线(长春)', is_filter: true },
           component: () => import('@/views/home/index.vue')
-        }
+        },
+        // 系统管理
+        ...system,
+        // 账号管理
+        ...account
       ]
     }
   ]
 })
+router.beforeEach(async (to, from, next) => {
+  document.title = `${to.meta.title} `
+  //   const token = localStorage.getItem('token');
+  //   if (token) {
+  //     const res = await axios.request({
+  //       method: 'get',
+  //       url: '/jcyjdtglpt/v1/api/token/tokenView',
+  //       responseType: 'json',
+  //       headers: {
+  //         token: token
+  //       }
+  //     });
+  //     console.log(res.data);
+  //     if (res.data.errcode == '0') {
+  //       store.commit('setUser', res.data.data, { root: true });
+  //     }
+  next()
+  // } else {
+  //   window.alert('无登录信息,无法打开');
+  // }
+})
 
 export default router

+ 1 - 0
src/router/module/account.js

@@ -0,0 +1 @@
+export default []

+ 1 - 0
src/router/module/common.js

@@ -0,0 +1 @@
+export default [];

+ 7 - 0
src/router/module/system.js

@@ -0,0 +1,7 @@
+export default [
+  {
+    path: '/system/dictionary',
+    meta: { title: '字典表设置', is_filter: true },
+    component: () => import('@/views/system/dictionary/index.vue')
+  }
+]

+ 150 - 0
src/util/axios-wrapper.ts

@@ -0,0 +1,150 @@
+/* eslint-disable no-console */
+/* eslint-disable no-param-reassign */
+
+import _ from 'lodash';
+import Axios from 'axios';
+import { Util, Error } from 'naf-core';
+// import { Indicator } from 'mint-ui';
+import type { IOptionsType, IQueryType, IRequestResult } from './types.util';
+
+const { trimData, isNullOrUndefined } = Util;
+const { ErrorCode } = Error;
+
+let currentRequests = 0;
+
+// // 参数类型设置
+// type valueType = string | number | object | boolean | Array<any>;
+// type queryType = string | number | boolean;
+
+// export interface IQueryType {
+//   [props: string]: queryType;
+// }
+// export interface IOptionsType {
+//   [props: string]: valueType;
+// }
+
+// export interface IRequestResult {
+//   errcode: string | number;
+//   errmsg: string | number;
+//   details?: string;
+//   [props: string]: any;
+// }
+
+export class AxiosWrapper {
+  constructor({ baseUrl = import.meta.env.VITE_REQUEST_BASE, unwrap = true } = {}) {
+    this.baseUrl = baseUrl;
+    this.unwrap = unwrap;
+  }
+  baseUrl: string;
+  unwrap: boolean;
+
+  // 替换uri中的参数变量
+  static merge(uri: string, query: IQueryType) {
+    if (!uri.includes(':')) {
+      return uri;
+    }
+    const keys = [];
+    const regexp = /\/:([a-z0-9_]+)/gi;
+    let res;
+    // eslint-disable-next-line no-cond-assign
+    while ((res = regexp.exec(uri)) != null) {
+      keys.push(res[1]);
+    }
+    keys.forEach((key) => {
+      const val = _.get(query, key);
+      if (!isNullOrUndefined(val)) {
+        uri = uri.replace(`:${key}`, `${val}`);
+      }
+    });
+    return uri;
+  }
+
+  $get(uri: string, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, undefined, query, options);
+  }
+
+  $post(uri: string, data: object = {}, query?: IQueryType, options?: IOptionsType) {
+    return this.$request(uri, data, query, options);
+  }
+  $delete(uri: string, data: object = {}, query?: IQueryType, options: IOptionsType = {}) {
+    options = { ...options, method: 'delete' };
+    return this.$request(uri, data, query, options);
+  }
+  async $request(uri: string, data?: object, query?: IQueryType, options?: IOptionsType) {
+    if (query && _.isObject(query)) {
+      const keys = Object.keys(query);
+      for (const key of keys) {
+        const val = _.get(query, key);
+        if (val === '') {
+          delete query[key];
+        }
+      }
+    }
+    if (_.isObject(query) && _.isObject(options)) {
+      options = { ...options, params: query, method: 'get' };
+    } else if (_.isObject(query) && !query.params) {
+      options = { params: query };
+    } else if (_.isObject(query) && query.params) {
+      options = query;
+    }
+    if (!options) options = {};
+    if (options.params) options.params = trimData(options.params, null, null);
+    const params = _.get(options, 'params');
+    const url = AxiosWrapper.merge(uri, params as IQueryType);
+    currentRequests += 1;
+    // Indicator.open({
+    //   spinnerType: 'fading-circle',
+    // });
+    try {
+      let returnData: any;
+      const axios = Axios.create({
+        baseURL: this.baseUrl,
+      });
+      // if (util.token && util.token !== null) axios.defaults.headers.common.Authorization = util.token;
+      const token = localStorage.getItem('token');
+      const apiToken = sessionStorage.getItem('apiToken');
+      if (token) axios.defaults.headers.common['token'] = token;
+      if (apiToken) axios.defaults.headers.common['api-token'] = apiToken;
+      const res = await axios.request({
+        method: isNullOrUndefined(data) ? 'get' : 'post',
+        url,
+        data,
+        responseType: 'json',
+        ...options,
+      });
+      const returnRes: IRequestResult = res.data;
+      const { errcode, errmsg, details } = returnRes;
+      if (errcode) {
+        console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`);
+        return returnRes;
+      }
+      // unwrap data
+      if (this.unwrap) {
+        returnData = returnRes;
+      }
+      // 处理apiToken
+      const { apiToken: at, ...others } = returnData;
+      if (at) sessionStorage.setItem('apiToken', at);
+      return others;
+    } catch (err: any) {
+      let errmsg = '接口请求失败,请稍后重试';
+      if (err.response) {
+        const { status } = err.response;
+        if (status === 401) errmsg = '用户认证失败,请重新登录';
+        if (status === 403) errmsg = '当前用户不允许执行该操作';
+      }
+      console.error(
+        `[AxiosWrapper] 接口请求失败: ${err.config && err.config.url} - 
+        ${err.message}`
+      );
+      return { errcode: ErrorCode.SERVICE_FAULT, errmsg, details: err.message };
+    } finally {
+      /* eslint-disable */
+      currentRequests -= 1;
+      if (currentRequests <= 0) {
+        currentRequests = 0;
+        // Indicator.close();
+      }
+    }
+  }
+}

+ 29 - 0
src/util/types.util.ts

@@ -0,0 +1,29 @@
+// 参数类型设置
+type valueType = string | number | Object | boolean | Array<any>;
+type queryType = string | number | boolean;
+
+export interface IQueryType {
+  [props: string]: queryType;
+}
+export interface IOptionsType {
+  [props: string]: valueType;
+}
+
+export interface IRequestResult {
+  errcode: string | number;
+  errmsg: string | number;
+  details?: string;
+  [props: string]: any;
+}
+export interface IQueryResult {
+  errcode?: string | number;
+  errmsg?: string | number;
+  data: valueType;
+  total: number;
+}
+
+export interface IQueryParams {
+  skip?: number;
+  limit?: number;
+  [props: string]: any;
+}

+ 172 - 0
src/views/system/dictionary/detail.vue

@@ -0,0 +1,172 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <c-search :is_title="false" :is_back="true" @toBack="toBack"> </c-search>
+        </el-col>
+        <el-col :span="24" class="two">
+          <component :is="search1" :form="searchForm" @onSubmit="toSearch" @toReset="toReset" @changeType="changeType"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <cButton @toAdd="toAdd()"> </cButton>
+        </el-col>
+        <el-col :span="24" class="fou">
+          <cTable :fields="fields" :opera="opera" :data="list" @query="search" :total="total" @edit="toEdit" @del="toDel" :select="false"> </cTable>
+        </el-col>
+      </el-col>
+    </el-row>
+    <cDialog :dialog="dialog" @handleClose="toClose">
+      <template v-slot:info>
+        <cForm v-if="dialog.type == '1'" :span="24" :fields="formFields" :form="form" :rules="rules" @save="onSubmit">
+          <template #status>
+            <el-radio label="0">正常</el-radio>
+            <el-radio label="1">停用</el-radio>
+          </template>
+          <template #is_default>
+            <el-radio label="0">非默认</el-radio>
+            <el-radio label="1">默认</el-radio>
+          </template>
+        </cForm>
+      </template>
+    </cDialog>
+  </div>
+</template>
+<script lang="ts" setup>
+import _ from 'lodash'
+import search1 from './parts_two/search-1.vue'
+import type { FormRules } from 'element-plus'
+import type { Ref } from 'vue'
+import { ref, onMounted, getCurrentInstance, reactive } from 'vue'
+import { ElMessage } from 'element-plus'
+import { useRoute } from 'vue-router'
+import { DictDataStore } from '@common/src/stores/system/dictData' // 字典表
+import type { IQueryResult } from '@/util/types.util'
+const dictData = DictDataStore()
+const route = useRoute()
+const { proxy } = getCurrentInstance() as any
+// 列表数据
+let list: Ref<any[]> = ref([])
+// 总数
+let total: Ref<number> = ref(0)
+let skip = 0
+let limit: number = proxy.$limit
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '字典标签', model: 'dict_label' },
+  { label: '字典键值', model: 'dict_value' },
+  { label: '字典排序', model: 'dict_sort' },
+  { label: '状态', model: 'status', format: (i) => (i == '0' ? '正常' : '停用') }
+])
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '修改', method: 'edit' },
+  { label: '删除', method: 'del', confirm: true, type: 'danger' }
+])
+const dialog: Ref<{ type: string; show: boolean; title: string }> = ref({ type: '1', show: false, title: '信息管理' })
+let form: Ref<any> = ref({})
+
+// 表单
+let formFields: Ref<any[]> = ref([
+  { label: '字典类型', model: 'dict_type' },
+  { label: '字典标签', model: 'dict_label' },
+  { label: '字典键值', model: 'dict_value' },
+  { label: '显示排序', model: 'dict_sort', type: 'number' },
+  { label: '是否默认', model: 'is_default', type: 'radio' },
+  { label: '状态', model: 'status', type: 'radio' }
+])
+const rules = reactive<FormRules>({
+  dict_name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
+  dict_type: [{ required: true, message: '请输入字典类型', trigger: 'blur' }],
+  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
+})
+
+// 查询数据
+let searchForm: Ref<any> = ref({})
+let dict_type: Ref<any> = ref('')
+
+onMounted(async () => {
+  await searchOther()
+  await search({ skip, limit })
+})
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  const { skip, limit } = e
+  const condition = _.cloneDeep(searchForm.value)
+  let info = { limit: limit, skip: skip, ...condition }
+  let res: IQueryResult = await dictData.query(info)
+  if (res.errcode == 0) {
+    list.value = res.data as any[]
+    total.value = res.total
+  }
+}
+const toSearch = () => {
+  search({ skip, limit })
+}
+const searchOther = () => {
+  if (route.query.dict_type) dict_type.value = route.query.dict_type
+  form.value.dict_type = dict_type.value
+  searchForm.value.dict_type = dict_type.value
+  console.log(searchForm.value)
+}
+const toReset = () => {
+  searchForm.value = { dict_type: route.query.dict_type }
+  search({ skip, limit })
+}
+// 新增
+const toAdd = () => {
+  dialog.value = { title: '信息管理', show: true, type: '1' }
+}
+// 修改
+const toEdit = async (data) => {
+  let res: IQueryResult = await dictData.fetch(data._id)
+  if (res.errcode == 0) {
+    form.value = res.data as {}
+    dialog.value = { title: '信息管理', show: true, type: '1' }
+  }
+}
+// 提交
+const onSubmit = async (data) => {
+  let res: IQueryResult
+  if (data._id) res = await dictData.update(data)
+  else res = await dictData.create(data)
+  if (res.errcode == 0) {
+    ElMessage({ type: `success`, message: `维护信息成功` })
+    toClose()
+  }
+}
+// 删除
+const toDel = async (data) => {
+  let res: IQueryResult = await dictData.del(data._id)
+  if (res.errcode == 0) {
+    ElMessage({ type: `success`, message: `刪除信息成功` })
+    search({ skip, limit })
+  }
+}
+// 选择字典名称
+const changeType = (value) => {
+  dict_type.value = value
+  form.value.dict_type = value
+}
+// 返回
+const toBack = () => {
+  window.history.go(-1)
+}
+// 弹框关闭
+const toClose = () => {
+  form.value = {}
+  searchForm.value = { dict_type: dict_type.value }
+  dialog.value = { title: '信息管理', show: false, type: '1' }
+  search({ skip, limit })
+}
+</script>
+<style lang="scss" scoped>
+.main {
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 161 - 0
src/views/system/dictionary/index.vue

@@ -0,0 +1,161 @@
+<template>
+  <div id="index">
+    <el-row>
+      <el-col :span="24" class="main animate__animated animate__backInRight">
+        <el-col :span="24" class="one">
+          <component :is="search1" :form="searchForm" @onSubmit="toSearch" @toReset="toReset"></component>
+        </el-col>
+        <el-col :span="24" class="two">
+          <cButton @toAdd="toAdd()"> </cButton>
+        </el-col>
+        <el-col :span="24" class="thr">
+          <cTable :fields="fields" :opera="opera" :data="list" @query="search" :total="total" @edit="toEdit" @del="toDel" :select="false">
+            <template #dict_type="{ item, row }">
+              <template v-if="item.model === 'dict_type'">
+                <el-link size="mini" type="primary" @click="toType(row)">{{ getProps(row, item.model) }}</el-link>
+              </template>
+            </template>
+          </cTable>
+        </el-col>
+      </el-col>
+    </el-row>
+    <cDialog :dialog="dialog" @handleClose="toClose">
+      <template v-slot:info>
+        <cForm v-if="dialog.type == '1'" :span="24" :fields="formFields" :form="form" :rules="rules" @save="onSubmit">
+          <template #status>
+            <el-radio label="0">正常</el-radio>
+            <el-radio label="1">停用</el-radio>
+          </template>
+        </cForm>
+      </template>
+    </cDialog>
+  </div>
+</template>
+<script lang="ts" setup>
+import _ from 'lodash'
+import search1 from './parts/search-1.vue'
+import type { FormRules } from 'element-plus'
+import type { Ref } from 'vue'
+import { ref, onMounted, getCurrentInstance, reactive } from 'vue'
+import { ElMessage } from 'element-plus'
+import { useRouter } from 'vue-router'
+import { DictTypeStore } from '@common/src/stores/system/dictType' // 字典表
+import type { IQueryResult } from '@/util/types.util'
+const dictType = DictTypeStore()
+const router = useRouter()
+const { proxy } = getCurrentInstance() as any
+// 列表数据
+let list: Ref<any[]> = ref([])
+// 总数
+let total: Ref<number> = ref(0)
+let skip = 0
+let limit: number = proxy.$limit
+// 列表
+let fields: Ref<any[]> = ref([
+  { label: '字典名称', model: 'dict_name' },
+  { label: '字典类型', model: 'dict_type', custom: true },
+  { label: '状态', model: 'status', format: (i) => (i == '0' ? '正常' : '停用') },
+  { label: '备注', model: 'remark' }
+])
+// 操作
+let opera: Ref<any[]> = ref([
+  { label: '修改', method: 'edit' },
+  { label: '删除', method: 'del', confirm: true, type: 'danger' }
+])
+const dialog: Ref<{ type: string; show: boolean; title: string }> = ref({ type: '1', show: false, title: '信息管理' })
+let form: Ref<{}> = ref({})
+
+// 表单
+let formFields: Ref<any[]> = ref([
+  { label: '字典名称', model: 'dict_name' },
+  { label: '字典类型', model: 'dict_type' },
+  { label: '状态', model: 'status', type: 'radio' },
+  { label: '备注', model: 'remark', type: 'textarea' }
+])
+const rules = reactive<FormRules>({
+  dict_type: [{ required: true, message: '请输入字典类型', trigger: 'blur' }],
+  dict_label: [{ required: true, message: '请输入字典标签', trigger: 'blur' }],
+  dict_value: [{ required: true, message: '请输入字典键值', trigger: 'blur' }],
+  dict_sort: [{ required: true, message: '请输入显示排序', trigger: 'blur' }],
+  status: [{ required: true, message: '请选择状态', trigger: 'change' }]
+})
+
+// 查询数据
+let searchForm: Ref<{}> = ref({})
+
+onMounted(async () => {
+  await search({ skip, limit })
+})
+// 查询
+const search = async (e: { skip: number; limit: number }) => {
+  const { skip, limit } = e
+  const condition = _.cloneDeep(searchForm.value)
+  let info = { limit: limit, skip: skip, ...condition }
+  let res: IQueryResult = await dictType.query(info)
+  if (res.errcode == 0) {
+    list.value = res.data as any[]
+    total.value = res.total
+  }
+}
+const toSearch = () => {
+  search({ skip, limit })
+}
+const toReset = () => {
+  searchForm.value = {}
+  search({ skip, limit })
+}
+// 新增
+const toAdd = () => {
+  dialog.value = { title: '信息管理', show: true, type: '1' }
+}
+// 修改
+const toEdit = async (data) => {
+  let res: IQueryResult = await dictType.fetch(data._id)
+  if (res.errcode == 0) {
+    form.value = res.data as {}
+    dialog.value = { title: '信息管理', show: true, type: '1' }
+  }
+}
+// 提交
+const onSubmit = async (data) => {
+  let res: IQueryResult
+  if (data._id) res = await dictType.update(data)
+  else res = await dictType.create(data)
+  if (res.errcode == 0) {
+    ElMessage({ type: `success`, message: `维护信息成功` })
+    toClose()
+  }
+}
+// 删除
+const toDel = async (data) => {
+  let res: IQueryResult = await dictType.del(data._id)
+  if (res.errcode == 0) {
+    ElMessage({ type: `success`, message: `刪除信息成功` })
+    search({ skip, limit })
+  }
+}
+// 字典类型跳转
+const toType = (data) => {
+  router.push({ path: '/system/dict/detail', query: { id: data._id, dict_type: data.dict_type } })
+}
+// 弹框关闭
+const toClose = () => {
+  form.value = {}
+  searchForm.value = {}
+  dialog.value = { title: '信息管理', show: false, type: '1' }
+  search({ skip, limit })
+}
+const getProps = (data, prop) => {
+  return _.get(data, prop)
+}
+</script>
+<style lang="scss" scoped>
+.main {
+  .one {
+    margin: 0 0 10px 0;
+  }
+  .two {
+    margin: 0 0 10px 0;
+  }
+}
+</style>

+ 64 - 0
src/views/system/dictionary/parts/search-1.vue

@@ -0,0 +1,64 @@
+<template>
+  <div id="search-1">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-form :model="form" ref="refForm" label-width="100px">
+          <el-col :span="24" class="form">
+            <el-col :span="6">
+              <el-form-item label="字典名称" prop="dict_name">
+                <el-input v-model="form.dict_name" placeholder="请输入字典名称"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="字典类型" prop="dict_type">
+                <el-input v-model="form.dict_type" placeholder="请输入字典类型"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="状态" prop="status">
+                <el-select v-model="form.status" clearable filterable placeholder="请选择状态" style="width: 100%">
+                  <el-option label="正常" value="0"></el-option>
+                  <el-option label="停用" value="1"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" :icon="Search" @click="onSubmit()">搜索</el-button>
+            <el-button :icon="Refresh" @click="toReset()">重置</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+<script setup lang="ts">
+import { Search, Refresh } from '@element-plus/icons-vue'
+import { toRefs } from 'vue'
+const props = defineProps({
+  form: { type: Object, default: () => {} }
+})
+const { form } = toRefs(props)
+const emit = defineEmits(['toReset', 'onSubmit'])
+const onSubmit = () => {
+  emit('onSubmit')
+}
+// 重置
+const toReset = () => {
+  form.value = {}
+  emit('toReset')
+}
+</script>
+
+<style lang="scss" scoped>
+.main {
+  .form {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+  }
+  .btn {
+    text-align: right;
+  }
+}
+</style>

+ 85 - 0
src/views/system/dictionary/parts_two/search-1.vue

@@ -0,0 +1,85 @@
+<template>
+  <div id="search-1">
+    <el-row>
+      <el-col :span="24" class="main">
+        <el-form :model="form" ref="refForm" label-width="100px">
+          <el-col :span="24" class="form">
+            <el-col :span="6">
+              <el-form-item label="字典名称" prop="dict_type">
+                <el-select v-model="form.dict_type" filterable placeholder="请选择状态" style="width: 100%" @change="changeType">
+                  <el-option v-for="(item, index) in dict_typeList" :key="index" :label="item.dict_name" :value="item.dict_type"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="字典标签" prop="dict_label">
+                <el-input v-model="form.dict_label" placeholder="请输入字典标签"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="状态" prop="status">
+                <el-select v-model="form.status" clearable filterable placeholder="请选择状态" style="width: 100%">
+                  <el-option label="正常" value="0"></el-option>
+                  <el-option label="停用" value="1"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-col>
+          <el-col :span="24" class="btn">
+            <el-button type="primary" :icon="Search" @click="onSubmit()">搜索</el-button>
+            <el-button :icon="Refresh" @click="toReset()">重置</el-button>
+          </el-col>
+        </el-form>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { Search, Refresh } from '@element-plus/icons-vue'
+import { toRefs, onMounted, ref } from 'vue'
+import type { Ref } from 'vue'
+import { DictTypeStore } from '@common/src/stores/users/sysdicttype' // 字典表
+import type { IQueryResult } from '@/util/types.util'
+const sysdicttype = DictTypeStore()
+const props = defineProps({
+  form: { type: Object, default: () => {} }
+})
+const { form } = toRefs(props)
+let dict_typeList: Ref<any[]> = ref([])
+onMounted(async () => {
+  console.log(form.value)
+
+  await searchOther()
+})
+// 查询
+const searchOther = async () => {
+  let res: IQueryResult = await sysdicttype.query()
+  if (res.errcode == 0) dict_typeList.value = res.data as any[]
+}
+const emit = defineEmits(['toReset', 'onSubmit', 'changeType'])
+const changeType = (value) => {
+  emit('changeType', value)
+}
+const onSubmit = () => {
+  emit('onSubmit')
+}
+// 重置
+const toReset = () => {
+  form.value = {}
+  emit('toReset')
+}
+</script>
+
+<style lang="scss" scoped>
+.main {
+  .form {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+  }
+  .btn {
+    text-align: right;
+  }
+}
+</style>

+ 14 - 9
vite.config.ts

@@ -1,10 +1,10 @@
-import { fileURLToPath, URL } from 'node:url';
-import { defineConfig, loadEnv } from 'vite';
-import vue from '@vitejs/plugin-vue';
-const path = require('path');
-const common = path.resolve(__dirname, '../common');
+import { fileURLToPath, URL } from 'node:url'
+import { defineConfig, loadEnv } from 'vite'
+import vue from '@vitejs/plugin-vue'
+const path = require('path')
+const common = path.resolve(__dirname, '../common')
 export default defineConfig(({ mode }) => {
-  const env = loadEnv(mode, __dirname);
+  const env = loadEnv(mode, __dirname)
   return {
     // 静态路径
     base: env.VITE_BASE_URL,
@@ -17,7 +17,12 @@ export default defineConfig(({ mode }) => {
       port: 8003,
       proxy: {
         '/files': {
-          target: 'http://basic.waityou24.cn'
+          target: 'http://broadcast.kqyjy.com'
+        },
+        '/zkzx/v2/v1/api': {
+          target: 'http://192.168.1.113:12001',
+          changeOrigin: true,
+          ws: false
         }
       },
       fs: { strict: false }
@@ -28,5 +33,5 @@ export default defineConfig(({ mode }) => {
         '@common': common
       }
     }
-  };
-});
+  }
+})