wenhongquan 1 year ago
parent
commit
04962f7612

+ 2 - 0
package.json

@@ -19,6 +19,7 @@
   "dependencies": {
     "@element-plus/icons-vue": "2.1.0",
     "@tato30/vue-pdf": "^1.10.0",
+    "@vant/auto-import-resolver": "^1.2.1",
     "@vueup/vue-quill": "1.2.0",
     "@vueuse/core": "9.5.0",
     "animate.css": "4.1.1",
@@ -38,6 +39,7 @@
     "path-to-regexp": "6.2.0",
     "pinia": "2.0.22",
     "screenfull": "6.0.0",
+    "vant": "^4.9.1",
     "vform3-builds": "3.0.8",
     "vue": "3.2.45",
     "vue-cropper": "1.0.3",

+ 11 - 4
src/permission.ts

@@ -10,18 +10,21 @@ import useSettingsStore from '@/store/modules/settings';
 import usePermissionStore from '@/store/modules/permission';
 
 NProgress.configure({ showSpinner: false });
-const whiteList = ['/login', '/register', '/social-callback'];
+const whiteList = ['/login', '/register', '/social-callback', '/h5/login'];
 
 router.beforeEach(async (to, from, next) => {
   NProgress.start();
   if (getToken()) {
     to.meta.title && useSettingsStore().setTitle(to.meta.title as string);
     /* has token*/
-    if (to.path === '/login') {
+    if (to.path === '/h5/login') {
+      next({ path: '/h5/project' });
+      NProgress.done();
+    } else if (to.path === '/login') {
       next({ path: '/' });
       NProgress.done();
     } else if (whiteList.indexOf(to.path) !== -1) {
-      next()
+      next();
     } else {
       if (useUserStore().roles.length === 0) {
         isRelogin.show = true;
@@ -52,7 +55,11 @@ router.beforeEach(async (to, from, next) => {
       // 在免登录白名单,直接进入
       next();
     } else {
-      next(`/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
+      if (to.path.indexOf('/h5') !== -1) {
+        next(`/h5/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
+      } else {
+        next(`/login?redirect=${to.fullPath}`); // 否则全部重定向到登录页
+      }
       NProgress.done();
     }
   }

+ 20 - 0
src/router/index.ts

@@ -62,6 +62,26 @@ export const constantRoutes: RouteOption[] = [
     component: () => import('@/views/error/401.vue'),
     hidden: true
   },
+
+  {
+    path: '/h5',
+    hidden: true,
+    redirect: '/h5/login',
+    children: [
+      {
+        path: '/h5/login',
+        component: () => import('@/views/h5/login/index.vue')
+      },
+      {
+        path: '/h5/project',
+        component: () => import('@/views/h5/project/index.vue')
+      },
+      {
+        path: '/h5/filelist',
+        component: () => import('@/views/h5/filelist/index.vue')
+      }
+    ]
+  },
   {
     path: '',
     component: Layout,

+ 166 - 0
src/views/h5/filelist/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="content">
+    <van-sticky :offset-top="0">
+      <van-nav-bar title="项目文件" left-text="返回" left-arrow @click-left="onClickLeft" @click-right="filterclick"> </van-nav-bar>
+    </van-sticky>
+    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
+      <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
+        <van-cell-group v-for="item in list" :key="item" inset style="margin-top: 10px">
+          <van-cell @click="previewfile(item)">
+            <div style="display: flex;justify-content: space-between;">
+              <div style="display: flex;">
+                <img style="width: 25px;height:25px" :src="gettypeicon(item.fileSuffix)" />
+                <div style="max-width: 50vw;white-space: nowrap;overflow: hidden;text-overflow: ellipsis; ">{{ item.originalName }}</div>
+              </div>
+              <div style="font-size: 10px;">
+                {{ item.createTime }}
+              </div>
+            </div>
+          </van-cell>
+        </van-cell-group>
+      </van-list>
+    </van-pull-refresh>
+
+    <el-dialog v-model="pdfviewshow" :title="`文件预览`" width="90vw">
+      <div style="position: relative;min-height:78vh">
+        <pdfview :src="currentfile.url"></pdfview>
+      </div>
+      <!-- <div><el-affix :offset="120" position="bottom"><el-button type="text" icon="DArrowRight"></el-button></el-affix></div>
+      </div> -->
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="pdfviewshow = false">关闭</el-button>
+
+          <el-button v-hasPermi="['filemanager.project.file.download']" type="primary" @click="downloadfile(currentfile)"> 下载 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script setup lang="ts">
+import {
+  listArchives,
+  addArchives,
+  updateArchives,
+  delArchives,
+  getArchive_files,
+  saveArchive_files
+} from "@/api/archives/index";
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_area, sys_project_status } = toRefs<any>(
+  proxy?.useDict("sys_area", "sys_project_status")
+);
+import { listByIds,delOss } from "@/api/system/oss";
+import _ from "lodash";
+const list = ref([]);
+const refreshing = ref(false);
+const loading = ref(false);
+const finished = ref(false);
+const router = useRouter();
+const route = useRoute();
+
+const currentfile = ref({ url: "" })
+const pdfviewshow = ref(false);
+
+const onClickLeft = () => {
+  router.replace({ path: '/h5/project' });
+}
+
+onMounted(() => {
+  if (route.query.id == undefined) {
+    router.replace({ path: '/h5/project' });
+  }
+})
+
+const onLoad = () => {
+  getArchive_files(route.query.id).then((res) => {
+    loading.value = false;
+     list.value = res.data
+     finished.value = true;
+  });
+};
+const onRefresh = () => {
+  // 清空列表数据
+  finished.value = false;
+  refreshing.value = false;
+
+  // 重新加载数据
+  // 将 loading 设置为 true,表示处于加载状态
+  loading.value = true;
+  onLoad();
+};
+
+const previewfile = (file) => {
+  currentfile.value = file;
+   listByIds(file.ossId).then((res) => {
+    currentfile.value.url = res.data[0].url;
+    pdfviewshow.value = true;
+  });
+}
+const downloadfile = (file) => {
+   proxy?.$download.oss(file.ossId)
+}
+
+
+import txticon from '@/assets/icons/svg/txt.svg'
+import picicon from '@/assets/icons/svg/pic.svg'
+import pdficon from '@/assets/icons/svg/pdf1.svg'
+import docicon from '@/assets/icons/svg/doc.svg'
+import xlsicon from '@/assets/icons/svg/xls.svg'
+import ppticon from '@/assets/icons/svg/ppt.svg'
+import mp4icon from '@/assets/icons/svg/mp4.svg'
+import cadicon from '@/assets/icons/svg/cad.svg'
+import unknownicon from '@/assets/icons/svg/unknown.svg'
+
+const gettypeicon = (type) => {
+  if (type.indexOf('png') != -1 || type.indexOf('jp') != -1) {
+    return picicon;
+  }
+  if (type.indexOf('ppt') != -1 ) {
+    return ppticon;
+  }
+   if (type.indexOf('xl') != -1 ) {
+    return xlsicon;
+   }
+   if (type.indexOf('doc') != -1 ) {
+    return docicon;
+   }
+  if (type.indexOf('txt') != -1 ) {
+    return txticon;
+  }
+  if (type.indexOf('ca') != -1 ) {
+    return cadicon;
+  }
+  if (type.indexOf('mp4') != -1 ) {
+    return mp4icon;
+  }
+  if (type.indexOf('pdf') != -1 ) {
+    return pdficon;
+  }
+  return unknownicon
+}
+</script>
+<style lang="scss" scoped>
+.content {
+  text-align: center;
+  position: relative;
+  min-height: 100vh;
+  background: #eff2f5;
+  .filtercss{
+
+
+  }
+}
+</style>
+<style lang="scss">
+.filtercss{
+   .el-drawer{
+    background: rgb(236, 235, 235);
+    .el-drawer__body{
+      padding:0
+    }
+   }
+
+  }
+</style>

+ 70 - 0
src/views/h5/login/index.vue

@@ -0,0 +1,70 @@
+<!-- eslint-disable @typescript-eslint/ban-ts-comment -->
+<template>
+  <div class="content">
+    <div style="margin-top: -15vh;"><van-image :src="logoimg" /></div>
+    <div style="font-size: 20px;font-weight: 600;margin-top:15px">文件管理系统</div>
+    <div style="margin-top: 40px;">
+      <div>
+        <van-cell-group inset>
+          <van-field v-model="loginForm.username" label="用户名" placeholder="请输入用户名" />
+        </van-cell-group>
+      </div>
+      <div style="margin-top: 10px;">
+        <van-cell-group inset>
+          <van-field v-model="loginForm.password" label="密码" type="password" placeholder="请输入密码" />
+        </van-cell-group>
+      </div>
+
+      <van-button style="margin-top: 40px;" type="primary" round size="large" @click="dologin">登录</van-button>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import logoimg from '@/assets/logo/logo.png';
+import { useUserStore } from '@/store/modules/user';
+import { LoginData, TenantVO } from '@/api/types';
+import { to } from 'await-to-js';
+
+const userStore = useUserStore();
+const router = useRouter();
+const loginForm = ref<LoginData>({
+  tenantId: '000000',
+  username: 'admin',
+  password: 'admin123',
+  rememberMe: false,
+  code: '',
+  uuid: ''
+} as LoginData);
+
+const redirect = ref(undefined);
+watch(() => router.currentRoute.value, (newRoute: any) => {
+  redirect.value = newRoute.query && newRoute.query.redirect;
+  if ((redirect.value ?? "").indexOf("h5") == -1) {
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    //@ts-ignore
+    redirect.value = "/h5/project";
+  }
+}, { immediate: true });
+
+
+
+const dologin = ()=>{
+  to(userStore.login(loginForm.value)).then(res => {
+      router.push({ path: redirect.value || '/h5/project' });
+  }).catch((e) => {
+    //  console.log(e)
+  })
+}
+</script>
+<style lang="scss" scoped>
+.content{
+  padding: 20px;
+  text-align: center;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  position: relative;
+  height: 100vh;
+  background: #eff2f5;
+}
+</style>

+ 185 - 0
src/views/h5/project/index.vue

@@ -0,0 +1,185 @@
+<template>
+  <div class="content">
+    <van-sticky :offset-top="0">
+      <van-nav-bar title="项目" @click-right="filterclick">
+        <template #right>
+          <van-icon name="filter-o" size="18" />
+        </template>
+      </van-nav-bar>
+    </van-sticky>
+    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
+      <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
+        <van-cell-group v-for="item in list" :key="item" inset style="margin-top: 10px">
+          <van-cell>
+            <div>
+              <el-descriptions border :column="2">
+                <el-descriptions-item label="电子编号" :span="2">
+                  {{ item.ecode }}
+                  <div style="position: absolute;right:5px;top:5px">
+                    <van-button size="mini" type="primary" plain hairline @click="filelook(item)">文件查看</van-button>
+                  </div>
+                </el-descriptions-item>
+                <el-descriptions-item label="丘权号" :span="2">
+                  {{ item.qiuquan }}
+                </el-descriptions-item>
+                <el-descriptions-item label="区域" :span="2">
+                  <dict-tag style="display: inline;" :options="sys_area" :value="item.area"
+                /></el-descriptions-item>
+                <el-descriptions-item label="创建时间" :span="2">
+                  {{ item.achievementDate }}
+                </el-descriptions-item>
+                <el-descriptions-item label="建设单位" :span="2">
+                  {{ item.buildUnit }}
+                </el-descriptions-item>
+                <el-descriptions-item label="地址" :span="2">
+                  {{ item.addr }}
+                </el-descriptions-item>
+                <el-descriptions-item label="备注" :span="2">
+                  {{ item.remark }}
+                </el-descriptions-item>
+              </el-descriptions>
+            </div>
+          </van-cell>
+        </van-cell-group>
+      </van-list>
+    </van-pull-refresh>
+    <el-drawer v-model="showfilter" title="筛选" :direction="'rtl'" size="70vw" modal-class="filtercss">
+      <van-cell-group inset>
+        <van-field v-model="areaname" is-link readonly label="区域" placeholder="点击选择区域" @click="showPicker = true" />
+        <van-popup v-model:show="showPicker" position="bottom">
+          <van-picker
+            :columns="sys_area.map((item) =>{ return { 'text':item.label,'value':item.value}})"
+            @confirm="onConfirm"
+            @cancel="showPicker = false"
+          />
+        </van-popup>
+        <van-field v-model="searchForm.qiuquan" label="丘权号" placeholder="丘权号" />
+        <van-field v-model="searchForm.buildUnit" label="建设单位" placeholder="建设单位" />
+        <van-field v-model="searchForm.saveAddr" label="存储位置" placeholder="存储位置" />
+        <van-field v-model="searchForm.remark" label="备注" placeholder="备注" />
+      </van-cell-group>
+      <div style="display: flex;gap:20px;padding:20px">
+        <van-button round block type="default" @click="reset"> 重置 </van-button>
+        <van-button round block type="primary" @click="onRefresh"> 搜索 </van-button>
+      </div>
+    </el-drawer>
+  </div>
+</template>
+<script setup lang="ts">
+import {
+  listArchives,
+  addArchives,
+  updateArchives,
+  delArchives,
+  getArchive_files,
+  saveArchive_files
+} from "@/api/archives/index";
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { sys_area, sys_project_status } = toRefs<any>(
+  proxy?.useDict("sys_area", "sys_project_status")
+);
+import _ from "lodash";
+const list = ref([]);
+const refreshing = ref(false);
+const loading = ref(false);
+const finished = ref(false);
+const router = useRouter();
+const filterclick = () => {
+  showfilter.value = true;
+};
+const showPicker = ref(false)
+const showfilter = ref(false)
+const searchForm = ref({
+  area: "",
+  qiuquan: "",
+  buildUnit: "",
+  addr: "",
+  saveAddr: "",
+  remark:""
+});
+
+const areaname = ref("");
+
+const filelook = (item) => {
+  router.push({
+    path: "/h5/filelist",
+    query: {
+      id: item.id,
+    },
+  });
+};
+
+const onConfirm = ({ selectedValues }) => {
+  searchForm.value.area = selectedValues[0];
+  showPicker.value = false
+  try {
+    areaname.value = sys_area.value.filter(i=>i.value==selectedValues[0])[0].label;
+  } catch (error) {
+
+  }
+}
+
+const reset = () => {
+  showfilter.value = false;
+  searchForm.value = {
+    area: "",
+    qiuquan: "",
+    buildUnit: "",
+    addr: "",
+    saveAddr: "",
+    remark:"",
+  };
+  pageNum.value = 1;
+  onLoad();
+};
+
+const pageNum = ref(1);
+const onLoad = () => {
+  showfilter.value = false;
+  if (pageNum.value == 1) {
+    list.value = [];
+  }
+  listArchives({ pageSize: 10, pageNum: pageNum.value++ ,...searchForm.value}).then((res) => {
+   list.value= list.value.concat(res.rows);
+    // 加载状态结束
+    loading.value = false;
+     if (list.value.length >= res.total) {
+      finished.value = true;
+    }
+  });
+};
+const onRefresh = () => {
+  // 清空列表数据
+  finished.value = false;
+  pageNum.value = 1;
+  refreshing.value = false;
+
+  // 重新加载数据
+  // 将 loading 设置为 true,表示处于加载状态
+  loading.value = true;
+  onLoad();
+};
+</script>
+<style lang="scss" scoped>
+.content {
+  text-align: center;
+  position: relative;
+  min-height: 100vh;
+  background: #eff2f5;
+  .filtercss{
+
+
+  }
+}
+</style>
+<style lang="scss">
+.filtercss{
+   .el-drawer{
+    background: rgb(236, 235, 235);
+    .el-drawer__body{
+      padding:0
+    }
+   }
+
+  }
+</style>

+ 3 - 1
vite/plugins/auto-import.ts

@@ -1,6 +1,7 @@
 import AutoImport from 'unplugin-auto-import/vite';
 import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
 import IconsResolver from 'unplugin-icons/resolver';
+import { VantResolver } from '@vant/auto-import-resolver';
 
 export default (path: any) => {
   return AutoImport({
@@ -16,7 +17,8 @@ export default (path: any) => {
       ElementPlusResolver(),
       IconsResolver({
         prefix: 'Icon'
-      })
+      }),
+      VantResolver()
     ],
     vueTemplate: true, // 是否在 vue 模板中自动导入
     dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'auto-imports.d.ts')

+ 3 - 1
vite/plugins/components.ts

@@ -1,6 +1,7 @@
 import Components from 'unplugin-vue-components/vite';
 import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
 import IconsResolver from 'unplugin-icons/resolver';
+import { VantResolver } from '@vant/auto-import-resolver';
 
 export default (path: any) => {
   return Components({
@@ -10,7 +11,8 @@ export default (path: any) => {
       // 自动注册图标组件
       IconsResolver({
         enabledCollections: ['ep']
-      })
+      }),
+      VantResolver()
     ],
     dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'components.d.ts')
   });