Forráskód Böngészése

OA H5工程搭建并实现OA H5首页

songxy 1 éve
szülő
commit
7e722ea7a9

+ 24 - 0
client_h5/.gitignore

@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 18 - 0
client_h5/README.md

@@ -0,0 +1,18 @@
+# Vue 3 + TypeScript + Vite
+
+This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
+
+## Recommended IDE Setup
+
+- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
+
+## Type Support For `.vue` Imports in TS
+
+TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
+
+If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
+
+1. Disable the built-in TypeScript Extension
+   1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
+   2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
+2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.

+ 13 - 0
client_h5/index.html

@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1">
+    <title>Vite + Vue + TS</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.ts"></script>
+  </body>
+</html>

+ 23 - 0
client_h5/package.json

@@ -0,0 +1,23 @@
+{
+  "name": "client_h5",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "vue-tsc && vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "vue": "^3.4.19",
+    "vue-router": "^4.2.5"
+  },
+  "devDependencies": {
+    "@types/node": "^20.11.20",
+    "@vitejs/plugin-vue": "^5.0.4",
+    "sass": "^1.71.1",
+    "typescript": "^5.2.2",
+    "vite": "^5.1.4",
+    "vue-tsc": "^1.8.27"
+  }
+}

+ 1 - 0
client_h5/public/vite.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

+ 11 - 0
client_h5/src/App.vue

@@ -0,0 +1,11 @@
+<script setup lang="ts">
+</script>
+
+<template>
+  <div>
+    <RouterView />
+  </div>
+</template>
+
+<style scoped>
+</style>

BIN
client_h5/src/assets/images/bjzx_icon.png


BIN
client_h5/src/assets/images/ccsq_icon.png


BIN
client_h5/src/assets/images/jksq_icon.png


BIN
client_h5/src/assets/images/kqsmt_icon.png


BIN
client_h5/src/assets/images/nav_bg.png


BIN
client_h5/src/assets/images/qjsq_icon.png


BIN
client_h5/src/assets/images/rztx_icon.png


BIN
client_h5/src/assets/images/tzgg_icon.png


BIN
client_h5/src/assets/images/user_log.jpg


BIN
client_h5/src/assets/images/wdkq_icon.png


BIN
client_h5/src/assets/images/wdrz_icon.png


BIN
client_h5/src/assets/images/wdxx_icon.png


BIN
client_h5/src/assets/images/wdzc_icon.png


BIN
client_h5/src/assets/images/xxzx_icon.png


+ 13 - 0
client_h5/src/main.ts

@@ -0,0 +1,13 @@
+import { createApp } from 'vue'
+import setupRouter from './router'
+import './style.css'
+import App from './App.vue'
+
+
+const setupAll = () => {
+  const app = createApp(App)
+  setupRouter(app)
+  return app;
+}
+
+setupAll().mount('#app')

+ 158 - 0
client_h5/src/pages/home/index.scss

@@ -0,0 +1,158 @@
+.home_box {
+  $card_radius: 8px;
+  height: 100%;
+  background-color: #F3F3F3;
+  >div {
+    &.header {
+      >.nav {
+        background: url("@/assets/images/nav_bg.png") no-repeat;
+        background-size: 100% 100%;
+        height: 16vh;
+        padding: 5vh 0px;
+        text-align: center;
+        >.login_info {
+          display: inline-block;
+          >img {
+            display: block;
+            width: 15vw;
+            height: 15vw;
+            border-radius: 50%;
+            border: 2px solid #fff;
+          }
+          >span {
+            display: block;
+            color: #fff;
+            margin-top: 8px;
+          }
+        }
+      }
+      >ul {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        >li {
+          flex: 1;
+          text-align: center;
+          position: relative;
+          >.corner {
+            right: 10px !important;
+          }
+          >img {
+            display: block;
+            margin: auto;
+          }
+          >p {
+            margin: 5px 0px;
+          }
+          >.corner {
+            display: block;
+          }
+        }
+      }
+    }
+    &.content {
+      padding: 20px;
+      >.card {
+        >ul {
+          display: grid;
+          grid-template-columns: repeat(2, 1fr);
+          >li {
+            background: #FFFFFF;
+            box-shadow: 0px 4px 20px 0px #EAEDF2;
+            border-radius: $card_radius;
+            padding: 25px 20px;
+            position: relative;
+            >img {
+              display: block;
+              position: absolute;
+              right: 8px;
+              bottom: 8px;
+              z-index: 9999999;
+            }
+            &::before {
+              display: block;
+              content: "";
+              position: absolute;
+              left: 0px;
+              right: 0px;
+              top: 0px;
+              margin: auto;
+              height: 50%;
+              background: linear-gradient( 180deg, #ECF2FF 0%, rgba(244,249,255,0) 100%);
+              border-radius: $card_radius;
+            }
+            &::after {
+              display: block;
+              content: "";
+              position: absolute;
+              width: 70px;
+              height: 12px;
+              bottom: 0px;
+              right: 0px;
+              border-bottom-right-radius: $card_radius;
+              background: linear-gradient( 270deg, #C5D8FF 0%, rgba(197,216,255,0) 100%);
+            }
+            &:nth-child(2),&:nth-child(4) {
+              margin-left: 10px;
+            }
+            &:nth-child(3),&:nth-child(4) {
+              margin-top: 10px;
+            }
+          }
+        }
+      }
+      >.item {
+        >ul {
+          display: grid;
+          grid-template-columns: repeat(4, 1fr);
+          >li {
+            flex: 1;
+            text-align: center;
+            position: relative;
+            background: rgba(255,255,255,0.5);
+            border-radius: 12px 12px 12px 12px;
+            padding: 15px 10px;
+            >img {
+              display: block;
+              margin: auto;
+              background: #FFFFFF;
+              box-shadow: 0px 4px 20px 0px #EAEDF2;
+              border-radius: $card_radius + 2;
+              padding: 10px;
+            }
+            >.title {
+              display: block;
+              margin-top: 5px;
+              font-size: 15px;
+            }
+            >p {
+              margin: 5px 0px;
+            }
+            >.corner {
+              display: block;
+            }
+          }
+        }
+      }
+    }
+  }
+  .corner {
+    position: absolute;
+    display: block;
+    width: 22px;
+    height: 16px;
+    line-height: 16px;
+    font-size: 13px;
+    background-color: #F23C3C;
+    color: #fff;
+    border-radius: 7px;
+    text-align: center;
+    right: 5px;
+    top: 5px;
+  }
+  .card_title {
+    font-size: 17px;
+    font-weight: bold;
+    color: #2A2E33;
+  }
+}

+ 116 - 0
client_h5/src/pages/home/index.vue

@@ -0,0 +1,116 @@
+<script setup lang="ts">
+import { ref } from 'vue'
+import { getAssetsURI } from '@/utils/common';
+
+const userName = ref<String>('测试用户')
+
+interface MenuItem {
+  title: string
+  corner?: number
+  icon: string
+}
+const navMenus: MenuItem[] = [
+  {
+    title: '办件中心',
+    corner: 0,
+    icon: '../assets/images/bjzx_icon.png'
+  },{
+    title: '日志填写',
+    corner: 0,
+    icon: '../assets/images/rztx_icon.png'
+  },{
+    title: '我的日志',
+    corner: 0,
+    icon: '../assets/images/wdrz_icon.png'
+  },{
+    title: '我的消息',
+    corner: 0,
+    icon: '../assets/images/wdxx_icon.png'
+  }
+]
+
+const processMenus: MenuItem[] = [
+  {
+    title: '请假申请',
+    corner: 0,
+    icon: '../assets/images/qjsq_icon.png'
+  },{
+    title: '出差申请',
+    corner: 0,
+    icon: '../assets/images/ccsq_icon.png'
+  },{
+    title: '考情说明条',
+    corner: 0,
+    icon: '../assets/images/kqsmt_icon.png'
+  },{
+    title: '借款申请',
+    corner: 0,
+    icon: '../assets/images/jksq_icon.png'
+  }
+]
+
+const personMenus: MenuItem[] = [
+  {
+    title: '我的考勤',
+    corner: 0,
+    icon: '../assets/images/wdkq_icon.png'
+  },{
+    title: '我的资产',
+    corner: 0,
+    icon: '../assets/images/wdzc_icon.png'
+  },{
+    title: '学习中心',
+    corner: 0,
+    icon: '../assets/images/xxzx_icon.png'
+  },{
+    title: '通知公告',
+    corner: 0,
+    icon: '../assets/images/tzgg_icon.png'
+  }
+]
+</script>
+
+<template>
+  <div class="home_box">
+    <div class="header">
+      <div class="nav">
+        <div class="login_info">
+          <img src="@/assets/images/user_log.jpg">
+          <span>{{ userName }}</span>
+        </div>
+      </div>
+      <ul>
+        <li v-for="(item,index) in navMenus" :key="index">
+          <img :src="getAssetsURI(item['icon'])" />
+          <p class="title">{{ item['title'] }}</p>
+          <span class="corner">{{ item['corner'] }}</span>
+        </li>
+      </ul>
+    </div>
+    <div class="content">
+      <div class="card">
+        <p class="card_title">常用流程</p>
+        <ul>
+          <li v-for="(item,index) in processMenus" :key="index">
+            <span class="title">{{ item['title'] }}</span>
+            <img :src="getAssetsURI(item['icon'])" />
+          </li>
+        </ul>
+      </div>
+      <div class="item">
+        <p class="card_title">个人中心</p>
+        <ul>
+          <li v-for="(item,index) in personMenus" :key="index">
+            <img :src="getAssetsURI(item['icon'])" />
+            <span class="title">{{ item['title'] }}</span>
+            <span class="corner">{{ item['corner'] }}</span>
+          </li>
+        </ul>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+@import './index.scss';
+</style>

+ 17 - 0
client_h5/src/router/index.ts

@@ -0,0 +1,17 @@
+import type {App} from 'vue';
+import type { RouteRecordRaw } from 'vue-router'
+import { createRouter, createWebHistory } from 'vue-router'
+import routes from './routes'
+
+const router = createRouter({
+  history: createWebHistory(),
+  strict: true,
+  routes: routes as RouteRecordRaw[],
+  scrollBehavior: () => ({ left: 0, top: 0 })
+})
+
+const setupRouter = (app: App<Element>): void => {
+  app.use(router)
+}
+
+export default setupRouter;

+ 19 - 0
client_h5/src/router/routes.ts

@@ -0,0 +1,19 @@
+import type { RouteRecordRaw } from 'vue-router'
+
+const routes:RouteRecordRaw[] = [
+  {
+    path: "/",
+    redirect: 'home',
+    children: [
+      {
+        path: 'home',
+        name: 'Homoe',
+        meta: {
+          title: '首页'
+        },
+        component:  () => import('@/pages/home/index.vue'),
+      }
+    ] as RouteRecordRaw[]
+  }
+] as RouteRecordRaw[]
+export default routes;

+ 8 - 0
client_h5/src/style.css

@@ -0,0 +1,8 @@
+html,body {
+  margin: 0px;
+}
+ul,li {
+  margin: 0px;
+  padding: 0px;
+  list-style: none;
+}

+ 6 - 0
client_h5/src/utils/common.ts

@@ -0,0 +1,6 @@
+/**
+ * 动态加载图片
+ * **/
+export const getAssetsURI = (uri: string): string => {
+  return new URL(uri, import.meta.url).href;
+}

+ 1 - 0
client_h5/src/vite-env.d.ts

@@ -0,0 +1 @@
+/// <reference types="vite/client" />

+ 29 - 0
client_h5/tsconfig.json

@@ -0,0 +1,29 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "useDefineForClassFields": true,
+    "module": "ESNext",
+    "lib": ["ES2020", "DOM", "DOM.Iterable"],
+    "skipLibCheck": true,
+
+    /* Bundler mode */
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "preserve",
+
+    /* Linting */
+    "strict": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "baseUrl": "./",
+    "paths": {
+      "@/*": ["src/*"]
+    },
+    "noFallthroughCasesInSwitch": true
+  },
+  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
+  "references": [{ "path": "./tsconfig.node.json" }],
+}

+ 11 - 0
client_h5/tsconfig.node.json

@@ -0,0 +1,11 @@
+{
+  "compilerOptions": {
+    "composite": true,
+    "skipLibCheck": true,
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowSyntheticDefaultImports": true,
+    "strict": true
+  },
+  "include": ["vite.config.ts"]
+}

+ 25 - 0
client_h5/vite.config.ts

@@ -0,0 +1,25 @@
+import { resolve } from 'path'
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+const root = process.cwd()
+function pathResolve(dir: string) {
+  return resolve(root, '.', dir)
+}
+// https://vitejs.dev/config/
+export default defineConfig({
+  resolve: {
+    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.scss', '.css'],
+    alias: [
+      {
+        find: 'vue-i18n',
+        replacement: 'vue-i18n/dist/vue-i18n.cjs.js'
+      },
+      {
+        find: /\@\//,
+        replacement: `${pathResolve('src')}/`
+      }
+    ]
+  },
+  plugins: [vue()],
+})