guhongwei 2 years ago
parent
commit
cc123b459d

+ 2 - 0
components.d.ts

@@ -11,6 +11,7 @@ declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     CPage: typeof import('./src/components/common/c-page.vue')['default']
     CPopup: typeof import('./src/components/common/c-popup.vue')['default']
+    CUpload: typeof import('./src/components/common/c-upload.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     VanButton: typeof import('vant/es')['Button']
@@ -26,5 +27,6 @@ declare module '@vue/runtime-core' {
     VanRadioGroup: typeof import('vant/es')['RadioGroup']
     VanRow: typeof import('vant/es')['Row']
     VanSearch: typeof import('vant/es')['Search']
+    VanUploader: typeof import('vant/es')['Uploader']
   }
 }

+ 8 - 6
src/components/common/c-page.vue

@@ -1,25 +1,27 @@
 <template>
   <div id="c-page">
-    <van-pagination v-model="currentPage" :page-count="total" mode="simple" @change="toCPage" />
+    <van-pagination v-model="currentPage" :total-items="total" :items-per-page="limit" mode="simple" @change="toCPage" />
   </div>
 </template>
 
 <script setup lang="ts">
 import { toRefs } from 'vue';
 import type { Ref } from 'vue';
-import { ref, getCurrentInstance } from 'vue';
+// getCurrentInstance
+import { ref } from 'vue';
 // 基本设置
-const { proxy } = getCurrentInstance() as any;
+// const { proxy } = getCurrentInstance() as any;
 
 const props = defineProps({
-  total: { type: Number, default: 0 }
+  total: { type: Number, default: 0 },
+  limit: { type: Number, default: 10 }
 });
 const currentPage: Ref<any> = ref(1);
-let limit: number = proxy.$limit;
+const limit: Ref<any> = ref(10);
 
 const emit = defineEmits(['search']);
 const toCPage = (page) => {
-  emit('search', { skip: (page - 1) * limit, limit: limit });
+  emit('search', { skip: (page - 1) * limit.value, limit: limit.value });
 };
 
 const { total } = toRefs(props);

+ 63 - 0
src/components/common/c-upload.vue

@@ -0,0 +1,63 @@
+<template>
+  <div id="c-upload">
+    <van-uploader v-model="file" multiple :max-count="count" :accept="accept" :before-read="beforeRead" :after-read="afterRead">
+      <van-button type="primary" size="small">上传文件</van-button>
+    </van-uploader>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import { toRefs } from 'vue';
+import { onMounted } from 'vue';
+import { showToast } from 'vant';
+import axios from 'axios';
+
+const props = defineProps({
+  file: { type: Array, default: () => [] },
+  count: { type: Number, default: () => 1 },
+  accept: { type: String, default: () => '*' }, //image/png,image/jpeg
+  url: { type: String, default: () => '/files/basic/policyfile/upload' }
+});
+const { file } = toRefs(props);
+const { count } = toRefs(props);
+const { accept } = toRefs(props);
+const { url } = toRefs(props);
+
+// 接口
+// 请求
+onMounted(async () => {});
+// 文件前置
+const beforeRead = (file) => {
+  if (accept.value == '*') {
+    return true;
+  } else {
+    let list = accept.value.split(',');
+    let is_info = list.find((i) => i == file.type);
+    if (!is_info) {
+      showToast('文件格式不对,请重新上传');
+      return false;
+    }
+    return true;
+  }
+};
+// 文件后置
+const afterRead = async (e: { file: any }) => {
+  let formdata = new FormData();
+  formdata.append('file', e.file, e.file.name);
+  const res = await axios.request({
+    method: 'post',
+    url: url.value,
+    responseType: 'json',
+    data: formdata,
+    headers: { 'Content-Type': 'multipart/form-data' }
+  });
+  if (res.status === 200 && res.data.errcode == 0) {
+    const { id, name, uri } = res.data;
+    const obj = { id, name, uri, url: `${import.meta.env.VITE_APP_HOST}/${uri}` };
+    file.value.push(obj);
+    console.log(file.value);
+  }
+};
+</script>
+<style scoped lang="scss"></style>

+ 2 - 1
src/components/index.ts

@@ -10,9 +10,10 @@ import cFile from '@common/src/components/frame/c-file.vue';
 // 本项目
 import cPage from '@/components/common/c-page.vue';
 import cPopup from '@/components/common/c-popup.vue';
+import vUpload from '@/components/common/c-upload.vue';
 
 const components: {
   [propName: string]: Component;
-} = { cButton, cDialog, cSearch, cForm, cTable, cUpload, cEditor, cFile, cPage, cPopup };
+} = { cButton, cDialog, cSearch, cForm, cTable, cUpload, cEditor, cFile, cPage, cPopup, vUpload };
 
 export default components;

+ 15 - 0
src/router/module/admin.ts

@@ -4,5 +4,20 @@ export default [
     path: '/laboratory/info',
     meta: { title: '实验室管理-信息列表' },
     component: () => import('@/views/laboratory/info/index.vue')
+  },
+  {
+    path: '/laboratory/info/detail',
+    meta: { title: '详细信息' },
+    component: () => import('@/views/laboratory/info/detail.vue')
+  },
+  {
+    path: '/policyfile',
+    meta: { title: '政策文件' },
+    component: () => import('@/views/policyfile/index.vue')
+  },
+  {
+    path: '/policyfile/detail',
+    meta: { title: '信息管理' },
+    component: () => import('@/views/policyfile/detail.vue')
   }
 ];

+ 48 - 0
src/views/laboratory/info/detail.vue

@@ -0,0 +1,48 @@
+<template>
+  <div id="detail">
+    <van-row>
+      <van-col span="24" class="main animate__animated animate__backInRight">
+        <van-col span="24" class="one">{{ basicInfo }}</van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+// 接口
+import { BasicStore } from '@common/src/stores/basic/basic';
+import type { IQueryResult } from '@/util/types.util';
+const basicAxios = BasicStore();
+
+// 路由
+const route = useRoute();
+
+// 实验室id
+const basic_id: Ref<any> = ref('');
+// 实验室详细信息
+const basicInfo: Ref<any> = ref({});
+
+// 请求
+onMounted(async () => {
+  basic_id.value = route.query.id;
+  await search();
+});
+const search = async () => {
+  if (basic_id.value) {
+    let res: IQueryResult = await basicAxios.fetch(basic_id.value);
+    if (res.errcode == '0') {
+      basicInfo.value = res.data;
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.main {
+  height: 100vh;
+  overflow: hidden;
+}
+</style>

+ 1 - 5
src/views/laboratory/info/index.vue

@@ -32,11 +32,7 @@
           </van-col>
         </van-col>
         <van-col span="24" class="thr">
-          <cPage :total="total" @search="search">
-            <template v-slot:info>
-              <van-col span="24">第一部分</van-col>
-            </template>
-          </cPage>
+          <cPage :total="total" :limit="limit" @search="search"> </cPage>
         </van-col>
       </van-col>
     </van-row>

+ 97 - 0
src/views/policyfile/detail.vue

@@ -0,0 +1,97 @@
+<template>
+  <div id="detail">
+    <van-row>
+      <van-col span="24" class="main animate__animated animate__backInRight">
+        <van-col span="24" class="one">
+          <van-form @submit="toSave" label-width="2em">
+            <van-cell-group>
+              <van-field
+                v-model="form.title"
+                name="title"
+                type="textarea"
+                rows="1"
+                autosize
+                label="标题"
+                placeholder="请输入文件标题"
+                :rules="[{ required: true, message: '请输入文件标题' }]"
+              />
+              <van-field name="file" label="文件">
+                <template #input>
+                  <vUpload :file="form.file"></vUpload>
+                </template>
+              </van-field>
+            </van-cell-group>
+            <div class="btn">
+              <van-button type="primary" size="small" native-type="submit"> 提交保存 </van-button>
+            </div>
+          </van-form>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import type { Ref } from 'vue';
+// reactive, ref, onMounted
+import { onMounted, ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { showToast } from 'vant';
+// 接口
+import { PolicyfileStore } from '@common/src/stores/basic/policyfile';
+import type { IQueryResult } from '@/util/types.util';
+const polAxios = PolicyfileStore();
+
+// 路由
+const route = useRoute();
+
+const id: Ref<any> = ref('');
+// 表单
+const form: Ref<any> = ref({});
+
+// 请求
+onMounted(async () => {
+  id.value = route.query.id;
+  await search();
+});
+const search = async () => {
+  if (id.value) {
+    let res: IQueryResult = await polAxios.fetch(id.value);
+    if (res.errcode == '0') {
+      form.value = res.data;
+    }
+  }
+};
+// 保存
+const toSave = async (e) => {
+  let res: IQueryResult;
+  if (id.value) res = await polAxios.update({ ...e, _id: id.value });
+  else res = await polAxios.create(e);
+  if (res.errcode == '0') {
+    showToast({ message: '信息删除成功', type: 'success', duration: 500 });
+    toBack();
+  } else {
+    showToast({ message: `${res.errmsg}`, type: 'fail', duration: 500 });
+  }
+};
+// 上传前置
+// const beforeRead = (e) => {
+//   console.log('1');
+//   console.log(e);
+// };
+// 返回;
+const toBack = () => {
+  window.history.go(-1);
+};
+</script>
+<style scoped lang="scss">
+.main {
+  .one {
+    .btn {
+      text-align: center;
+      margin: 10px 0;
+    }
+  }
+}
+</style>

+ 175 - 0
src/views/policyfile/index.vue

@@ -0,0 +1,175 @@
+<template>
+  <div id="index">
+    <van-row>
+      <van-col span="24" class="main animate__animated animate__backInRight">
+        <van-col span="24" class="one">
+          <van-col span="20" class="one_1">
+            <van-field v-model="searchForm.name" placeholder="请输入文件标题" @blur="toInput" />
+          </van-col>
+          <van-col span="4" class="one_2">
+            <van-button size="small" @click="toAdd" :disabled="!is_show">新增</van-button>
+          </van-col>
+        </van-col>
+        <van-col span="24" class="two">
+          <van-col span="24" class="list" v-for="i in list" :key="i._id">
+            <van-col span="24" class="name">{{ i.title }}</van-col>
+            <van-col span="24" class="other">
+              <van-col span="24" class="other_1">
+                <span>文件:</span>
+                <span v-for="r in i.file" :key="r.url" @click="toDownload(r)">{{ r.name }};</span>
+              </van-col>
+            </van-col>
+            <van-col span="24" class="btn">
+              <van-button type="primary" size="small" @click="toEdit(i)">信息编辑</van-button>
+              <van-button type="danger" size="small" @click="toDel(i)">信息删除</van-button>
+            </van-col>
+          </van-col>
+        </van-col>
+        <van-col span="24" class="thr">
+          <cPage :total="total" :limit="limit" @search="search"> </cPage>
+        </van-col>
+      </van-col>
+    </van-row>
+  </div>
+</template>
+
+<script setup lang="ts">
+// 基础
+import _ from 'lodash';
+import type { Ref } from 'vue';
+import { onMounted, ref, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+import { showConfirmDialog, showToast } from 'vant';
+// 接口
+import { PolicyfileStore } from '@common/src/stores/basic/policyfile';
+import type { IQueryResult } from '@/util/types.util';
+import store from '@/stores/counter';
+const polAxios = PolicyfileStore();
+
+// 基本设置
+const { proxy } = getCurrentInstance() as any;
+
+// 路由
+const router = useRouter();
+
+// 是否显示
+const is_show: Ref<any> = ref(false);
+
+const list: Ref<any> = ref([]);
+const total: Ref<any> = ref(0);
+const skip = 0;
+const limit: number = proxy.$limit;
+// 查询
+const searchForm: Ref<any> = ref({});
+
+// 请求
+onMounted(async () => {
+  await searchUser();
+  await search({ skip, limit });
+});
+const searchUser = () => {
+  let user = store.state.user as any;
+  if (user.role_type == '0' || user.role_type == '1') {
+    is_show.value = true;
+  }
+};
+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 polAxios.query(info);
+  if (res.errcode == 0) {
+    list.value = res.data as [];
+    total.value = res.total;
+  }
+};
+// 名称查询
+const toInput = () => {
+  search({ skip, limit });
+};
+// 新增
+const toAdd = () => {
+  router.push({ path: '/policyfile/detail' });
+};
+// 信息修改
+const toEdit = (e) => {
+  router.push({ path: '/policyfile/detail', query: { id: e._id } });
+};
+// 信息删除
+const toDel = async (e) => {
+  showConfirmDialog({
+    title: '提示',
+    message: '您确认删除该数据?',
+    width: '100%'
+  })
+    .then(async () => {
+      let res: IQueryResult = await polAxios.del(e._id);
+      if (res.errcode == '0') {
+        showToast({ message: '信息删除成功', type: 'success', duration: 500 });
+        search({ skip, limit });
+      } else {
+        showToast({ message: `${res.errmsg}`, type: 'fail', duration: 500 });
+      }
+    })
+    .catch(() => {});
+};
+// 查看文件
+const toDownload = (e) => {
+  window.location.href = `${e.url}`;
+};
+</script>
+<style scoped lang="scss">
+.main {
+  height: 100vh;
+  overflow: hidden;
+  .one {
+    display: flex;
+    padding: 10px;
+    height: 9vh;
+    .one_1 {
+      .van-cell {
+        padding: 5px;
+        border: 1px solid #f1f1f1;
+      }
+    }
+    .one_2 {
+      .van-button {
+        width: 100%;
+        height: 5.4vh;
+      }
+    }
+  }
+  .two {
+    height: 85vh;
+    overflow-y: auto;
+    padding: 0 10px;
+    .list {
+      border: 1px solid #f1f1f1;
+      margin: 0 0 10px 0;
+      padding: 10px;
+      border-radius: 5px;
+      .name {
+        font-size: 16px;
+        font-weight: bold;
+        margin: 0 0 5px 0;
+      }
+      .other {
+        margin: 0 0 5px 0;
+        .other_1 {
+          font-size: 14px;
+        }
+      }
+      .btn {
+        text-align: center;
+        .van-button {
+          margin: 0 10px;
+        }
+      }
+    }
+  }
+  .thr {
+    height: 6vh;
+    overflow: hidden;
+  }
+}
+</style>