소스 검색

init:按照原型先写逻辑

aamin 1 년 전
커밋
267621c5e2
66개의 변경된 파일13632개의 추가작업 그리고 0개의 파일을 삭제
  1. 0 0
      .eslintignore
  2. 15 0
      .eslintrc.cjs
  3. 30 0
      .gitignore
  4. 8 0
      .prettierrc.json
  5. 8 0
      .vscode/extensions.json
  6. 46 0
      README.md
  7. 19 0
      components.d.ts
  8. 1 0
      env.d.ts
  9. 22 0
      eslintrc.js
  10. 25 0
      index.html
  11. 7949 0
      package-lock.json
  12. 52 0
      package.json
  13. BIN
      public/favicon.ico
  14. 13 0
      public/staticData/data.js
  15. 94 0
      src/App.vue
  16. 5 0
      src/api/api/activeBooking/index.ts
  17. 4 0
      src/api/api/artwork/index.ts
  18. 5 0
      src/api/api/dynamic/index.ts
  19. 5 0
      src/api/api/exhibition/index.ts
  20. 6 0
      src/api/api/summarize/index.ts
  21. 4 0
      src/api/api/treasure/index.ts
  22. 4 0
      src/api/api/volunteerHome/index.ts
  23. 1 0
      src/api/record.ts
  24. 74 0
      src/api/request.ts
  25. 16 0
      src/assets/base.css
  26. BIN
      src/assets/images/back.png
  27. BIN
      src/assets/images/income.png
  28. BIN
      src/assets/images/left.png
  29. BIN
      src/assets/images/pause.png
  30. BIN
      src/assets/images/play.png
  31. BIN
      src/assets/images/right.png
  32. BIN
      src/assets/images/sceneBack.png
  33. 1 0
      src/assets/logo.svg
  34. 1 0
      src/assets/main.css
  35. 71 0
      src/auto-import.d.ts
  36. 15 0
      src/base.css
  37. 7 0
      src/images.d.ts
  38. 27 0
      src/main.ts
  39. 110 0
      src/router/index.ts
  40. 15 0
      src/stores/index.ts
  41. 9 0
      src/types/api/dynamic.d.ts
  42. 7 0
      src/types/declaration.d.ts
  43. 4 0
      src/types/index.d.ts
  44. 36 0
      src/utils/browser.ts
  45. 10 0
      src/utils/https.ts
  46. 100 0
      src/utils/pass.ts
  47. 174 0
      src/views/EnterNingguo/artwork.vue
  48. 129 0
      src/views/EnterNingguo/dynamic-detail.vue
  49. 213 0
      src/views/EnterNingguo/dynamic.vue
  50. 68 0
      src/views/EnterNingguo/summarize.vue
  51. 151 0
      src/views/ExhibitionService/active-detail.vue
  52. 106 0
      src/views/ExhibitionService/active-info.vue
  53. 154 0
      src/views/ExhibitionService/activeBooking.vue
  54. 18 0
      src/views/ExhibitionService/bookedList.vue
  55. 162 0
      src/views/SmartTour/exhibition-detail.vue
  56. 218 0
      src/views/SmartTour/exhibition.vue
  57. 261 0
      src/views/SmartTour/treasure-detail.vue
  58. 203 0
      src/views/SmartTour/treasure.vue
  59. 105 0
      src/views/VolunteerHome/apply.vue
  60. 146 0
      src/views/VolunteerHome/detail.vue
  61. 156 0
      src/views/VolunteerHome/home.vue
  62. 13 0
      tsconfig.app.json
  63. 30 0
      tsconfig.json
  64. 17 0
      tsconfig.node.json
  65. 44 0
      vite.config.ts
  66. 2445 0
      yarn.lock

+ 0 - 0
.eslintignore


+ 15 - 0
.eslintrc.cjs

@@ -0,0 +1,15 @@
+/* eslint-env node */
+require('@rushstack/eslint-patch/modern-module-resolution')
+
+module.exports = {
+  root: true,
+  'extends': [
+    'plugin:vue/vue3-essential',
+    'eslint:recommended',
+    '@vue/eslint-config-typescript',
+    '@vue/eslint-config-prettier/skip-formatting'
+  ],
+  parserOptions: {
+    ecmaVersion: 'latest'
+  }
+}

+ 30 - 0
.gitignore

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

+ 8 - 0
.prettierrc.json

@@ -0,0 +1,8 @@
+{
+  "$schema": "https://json.schemastore.org/prettierrc",
+  "semi": false,
+  "tabWidth": 2,
+  "singleQuote": true,
+  "printWidth": 100,
+  "trailingComma": "none"
+}

+ 8 - 0
.vscode/extensions.json

@@ -0,0 +1,8 @@
+{
+  "recommendations": [
+    "Vue.volar",
+    "Vue.vscode-typescript-vue-plugin",
+    "dbaeumer.vscode-eslint",
+    "esbenp.prettier-vscode"
+  ]
+}

+ 46 - 0
README.md

@@ -0,0 +1,46 @@
+# zhengquan
+
+This template should help get you started developing with Vue 3 in Vite.
+
+## Recommended IDE Setup
+
+[VSCode](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.
+
+## Customize configuration
+
+See [Vite Configuration Reference](https://vitejs.dev/config/).
+
+## Project Setup
+
+```sh
+npm install
+```
+
+### Compile and Hot-Reload for Development
+
+```sh
+npm run dev
+```
+
+### Type-Check, Compile and Minify for Production
+
+```sh
+npm run build
+```
+
+### Lint with [ESLint](https://eslint.org/)
+
+```sh
+npm run lint
+```

+ 19 - 0
components.d.ts

@@ -0,0 +1,19 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+export {}
+
+declare module 'vue' {
+  export interface GlobalComponents {
+    RouterLink: typeof import('vue-router')['RouterLink']
+    RouterView: typeof import('vue-router')['RouterView']
+    VanField: typeof import('vant/es')['Field']
+    VanSearch: typeof import('vant/es')['Search']
+    VanSwipe: typeof import('vant/es')['Swipe']
+    VanSwipeItem: typeof import('vant/es')['SwipeItem']
+    VanTab: typeof import('vant/es')['Tab']
+    VanTabs: typeof import('vant/es')['Tabs']
+  }
+}

+ 1 - 0
env.d.ts

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

+ 22 - 0
eslintrc.js

@@ -0,0 +1,22 @@
+module.exports = {
+  root: true, // 此项是用来告诉eslint找当前配置文件不能往父级查找
+  env: { // 预定义的全局变量,这里是浏览器环境
+    amd: true,
+    es6: true,
+    commonjs: true,
+    node: true,
+    jquery: true,
+    browser: true
+  },
+  extends: [
+    'plugin:vue/essential',
+    '@vue/standard'
+  ],
+  parserOptions: {
+    sourceType: 'module',
+    parser: 'babel-eslint' // 解析器,默认使用 Espree
+  },
+  rules: {
+    'vue/multi-word-component-names': 'off'
+  }
+}

+ 25 - 0
index.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <link rel="icon" href="/favicon.ico">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <meta name="apple-mobile-web-app-capable" content="yes">
+  <meta name="viewport"
+    content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
+
+  <!-- 本地开发 -->
+  <script src="/staticData/data.js"></script>
+  <!-- 打包配置 -->
+  <!-- <script src="./staticData/data.js"></script> -->
+
+  <title>宁国市博物馆</title>
+</head>
+
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+
+</html>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 7949 - 0
package-lock.json


+ 52 - 0
package.json

@@ -0,0 +1,52 @@
+{
+  "name": "zhengquan",
+  "version": "0.0.0",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "run-p type-check \"build-only {@}\" --",
+    "preview": "vite preview",
+    "build-only": "vite build",
+    "type-check": "vue-tsc --build --force",
+    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
+    "format": "prettier --write src/"
+  },
+  "dependencies": {
+    "@types/node": "^20.5.0",
+    "axios": "^1.6.2",
+    "easyscroller": "^1.0.1",
+    "element-plus": "^2.5.5",
+    "js-base64": "^3.7.5",
+    "pinia": "^2.1.7",
+    "swiper": "^10.3.1",
+    "v-viewer": "^3.0.11",
+    "vant": "^4.8.10",
+    "vue": "^3.3.11",
+    "vue-router": "^4.2.5"
+  },
+  "devDependencies": {
+    "@rushstack/eslint-patch": "^1.3.3",
+    "@tsconfig/node18": "^18.2.2",
+    "@types/node": "^18.19.3",
+    "@vant/auto-import-resolver": "^1.1.0",
+    "@vitejs/plugin-vue": "^4.5.2",
+    "@vue/eslint-config-prettier": "^8.0.0",
+    "@vue/eslint-config-typescript": "^12.0.0",
+    "@vue/tsconfig": "^0.5.0",
+    "eslint": "^8.49.0",
+    "eslint-plugin-vue": "^9.17.0",
+    "less": "^4.2.0",
+    "npm-run-all2": "^6.1.1",
+    "prettier": "^3.0.3",
+    "typescript": "~5.3.0",
+    "unplugin-auto-import": "^0.17.5",
+    "unplugin-vue-components": "^0.26.0",
+    "vite": "^5.0.10",
+    "vue-tsc": "^1.8.25"
+  },
+  "rules": {
+    "no-unused-vars": 0,
+    "vue/multi-word-component-names": "off"
+  }
+}

BIN
public/favicon.ico


+ 13 - 0
public/staticData/data.js

@@ -0,0 +1,13 @@
+let baseUrlRes = ''
+
+if (window.location.href.includes('http://')) {
+  // 本地环境
+  baseUrlRes = 'http://127.0.0.1:8081/staticData/'
+} else {
+  // 正式环境
+  baseUrlRes = '../staticData'
+}
+
+const dataAll = {
+
+}

+ 94 - 0
src/App.vue

@@ -0,0 +1,94 @@
+<script setup lang="ts">
+import { useStore } from "./stores/index";
+const store = useStore();
+
+const time = ref();
+
+
+onBeforeMount(() => {
+  // @ts-ignore
+  store.dataAll = dataAll;
+  // 移动端
+  window.addEventListener(
+    "resize",
+    () => {
+      //@ts-ignore
+      clearTimeout(time.current);
+      //@ts-ignore
+      time.current = window.setTimeout(() => {
+        // 根元素
+        const dom: HTMLDivElement | null = document.querySelector("#app");
+        if (dom && document.documentElement.clientWidth < 480) {
+          dom.style.height = document.documentElement.clientHeight + "px";
+        }
+      }, 100);
+    },
+    true
+  );
+
+  // const baseAPIUrl = ref('')
+  // // const baseAPIUrl = ref('http://192.168.20.61:8063')
+  // // const baseAPIUrl = ref('https://sit-cnzhengquan.4dage.com')
+
+  // // 统计访问量
+  // if (localStorage.getItem('refreshTime')) {
+  //   var nowDate = Math.floor(Date.now() / 1000);
+  //   // @ts-ignore
+  //   var storedTimestamp = parseInt(localStorage.getItem('refreshTime'), 10);
+  //   console.log('时间差',Math.floor((nowDate - storedTimestamp)))
+  //   if (Math.floor((nowDate - storedTimestamp) / 60) > 60) {
+  //     // 发送请求并且更新本地缓存
+
+  //     axios.get(`${baseAPIUrl.value}/api/show/addVisit?id=10&type=visit`).then(() => {
+  //       // @ts-ignore
+  //       localStorage.setItem('refreshTime', nowDate);
+  //     })
+  //   }
+  // } else {
+  //   axios.get(`${baseAPIUrl.value}/api/show/addVisit?id=10&type=visit`).then(() => {
+  //     // @ts-ignore
+  //     localStorage.setItem('refreshTime', Math.floor(Date.now() / 1000));
+  //   })
+
+  // }
+})
+</script>
+
+<template>
+  <router-view />
+</template>
+
+<style scoped>
+@font-face {
+  font-family: 'REEJI-DuoguanGB-free-Flash';
+  src: url('./assets/fonts/REEJI-DuoguanGB-free-Flash.ttf');
+}
+
+@font-face {
+  font-family: 'SourceHanSansCN-Bold';
+  src: url('./assets/fonts/SourceHanSansCN-Bold.otf');
+}
+
+@font-face {
+  font-family: 'SourceHanSansCN-Medium';
+  src: url('./assets/fonts/SourceHanSansCN-Medium.otf');
+}
+
+@font-face {
+  font-family: 'SourceHanSerifCN-Heavy';
+  src: url('./assets/fonts/SourceHanSerifCN-Heavy.otf');
+}
+
+
+
+#app {
+  width: 100%;
+  height: 100%;
+}
+
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+</style>

+ 5 - 0
src/api/api/activeBooking/index.ts

@@ -0,0 +1,5 @@
+import axiosInstance from '@/api/request'
+export const ActiveBookingApi = {
+  getActiveList:() => axiosInstance.get(''),
+  getDetailById: (id: number) => axiosInstance.get(`${id}`)
+}

+ 4 - 0
src/api/api/artwork/index.ts

@@ -0,0 +1,4 @@
+import axiosInstance from '@/api/request'
+export const ArtworkApi = {
+  getSearchByKeyword: (data: any) => axiosInstance.get('', data)
+}

+ 5 - 0
src/api/api/dynamic/index.ts

@@ -0,0 +1,5 @@
+import axiosInstance from '@/api/request'
+export const DynamicApi = {
+  getDynamicList:() => axiosInstance.get(''),
+  getDetailById: (id: number) => axiosInstance.get(`${id}`)
+}

+ 5 - 0
src/api/api/exhibition/index.ts

@@ -0,0 +1,5 @@
+import axiosInstance from '@/api/request'
+export const ExhibitionApi = {
+  getExhibitionList: () => axiosInstance.get(''),
+  getDetailById: (id: number) => axiosInstance.get(`${id}`,)
+}

+ 6 - 0
src/api/api/summarize/index.ts

@@ -0,0 +1,6 @@
+import axiosInstance from '@/api/request'
+export const SummarizeApi = {
+  // 获得概述内容
+  // getSummerize: () => request('/wxShow/config/getAppreciate', 'GET', {})
+  getSummerize: () => axiosInstance.get('/wxShow/config/getAppreciate'),
+}

+ 4 - 0
src/api/api/treasure/index.ts

@@ -0,0 +1,4 @@
+import axiosInstance from '@/api/request'
+export const TreasureApi = {
+  getTreasureList: () => axiosInstance.get(''),
+}

+ 4 - 0
src/api/api/volunteerHome/index.ts

@@ -0,0 +1,4 @@
+import axiosInstance from '@/api/request'
+export const VolunteerApi = {
+  getVolunteerList: () => axiosInstance.get(''),
+}

+ 1 - 0
src/api/record.ts

@@ -0,0 +1 @@
+export const baseIMGUrl ='https://houseoss.4dkankan.com/project/bjfljtl/img'

+ 74 - 0
src/api/request.ts

@@ -0,0 +1,74 @@
+import axios from 'axios';
+
+
+//设置基地址
+// export const baseUrl = "https://wxfalangchang.4dage.com/api";
+// export const baseIMGUrl = "https://wxfalangchang.4dage.com";
+export const baseUrl = "";
+export const baseIMGUrl = "";
+
+
+const instance = axios.create({
+  baseURL: baseUrl, // 使用环境变量设置API的基础URL
+  timeout: 5000, // 可选,设置请求超时时间
+  headers: {
+    'Content-Type': 'application/json',
+  },
+});
+
+// 请求拦截器
+instance.interceptors.request.use(
+  async (config) => {
+    // 在这里执行请求发送前的预处理操作
+
+    // 示例:添加全局请求头(如API版本、认证令牌等)(需要登录)
+    // const commonStore = useCommonStore(); // 假设有一个名为commonStore的Pinia store来管理全局状态
+    // const { accessToken } = storeToRefs(commonStore); // 从store中获取accessToken
+
+    // if (accessToken.value) {
+    //   config.headers.Authorization = `Bearer ${accessToken.value}`;
+    // }
+
+    // 可以在此处添加其他通用请求逻辑,如:
+    // - 统一处理请求参数序列化
+    // - 显示全局加载指示器
+    // - ...
+
+    return config;
+  },
+  (error) => {
+    // 对请求错误进行处理,如:
+    // - 清除过期的认证信息
+    // - 提示用户网络问题
+    // - ...
+
+    return Promise.reject(error);
+  },
+);
+
+instance.interceptors.response.use(
+  (response) => {
+    // 对正常响应进行处理,如:
+    // - 解析并标准化返回数据结构
+    // - 隐藏全局加载指示器
+    // - 更新全局状态(如刷新用户信息、更新接口调用次数等)
+
+    return response.data; // 返回响应数据
+  },
+  (error) => {
+   // 对HTTP错误进行处理,如:
+   // - 根据状态码显示相应的错误提示
+   // - 处理token过期,触发重新登录流程
+   // - 将错误信息标准化以便在组件中统一处理
+
+   if (error.response.status === 401) {
+     // 处理未授权情况,如清除token并跳转到登录页面
+   }
+
+   return Promise.reject(error); // 将错误对象传递给后续的catch语句
+  },
+);
+
+
+
+export default instance;

+ 16 - 0
src/assets/base.css

@@ -0,0 +1,16 @@
+#app {
+  margin: 0;
+  width: 100vw;
+  height: 100vh;
+  /* overflow: hidden; */
+}
+body {
+  margin: 0;
+  padding: 0;
+  display: block;
+}
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}

BIN
src/assets/images/back.png


BIN
src/assets/images/income.png


BIN
src/assets/images/left.png


BIN
src/assets/images/pause.png


BIN
src/assets/images/play.png


BIN
src/assets/images/right.png


BIN
src/assets/images/sceneBack.png


+ 1 - 0
src/assets/logo.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

+ 1 - 0
src/assets/main.css

@@ -0,0 +1 @@
+@import './base.css';

+ 71 - 0
src/auto-import.d.ts

@@ -0,0 +1,71 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// noinspection JSUnusedGlobalSymbols
+// Generated by unplugin-auto-import
+export {}
+declare global {
+  const EffectScope: typeof import('vue')['EffectScope']
+  const computed: typeof import('vue')['computed']
+  const createApp: typeof import('vue')['createApp']
+  const customRef: typeof import('vue')['customRef']
+  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
+  const defineComponent: typeof import('vue')['defineComponent']
+  const effectScope: typeof import('vue')['effectScope']
+  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
+  const getCurrentScope: typeof import('vue')['getCurrentScope']
+  const h: typeof import('vue')['h']
+  const inject: typeof import('vue')['inject']
+  const isProxy: typeof import('vue')['isProxy']
+  const isReactive: typeof import('vue')['isReactive']
+  const isReadonly: typeof import('vue')['isReadonly']
+  const isRef: typeof import('vue')['isRef']
+  const markRaw: typeof import('vue')['markRaw']
+  const nextTick: typeof import('vue')['nextTick']
+  const onActivated: typeof import('vue')['onActivated']
+  const onBeforeMount: typeof import('vue')['onBeforeMount']
+  const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
+  const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
+  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
+  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
+  const onDeactivated: typeof import('vue')['onDeactivated']
+  const onErrorCaptured: typeof import('vue')['onErrorCaptured']
+  const onMounted: typeof import('vue')['onMounted']
+  const onRenderTracked: typeof import('vue')['onRenderTracked']
+  const onRenderTriggered: typeof import('vue')['onRenderTriggered']
+  const onScopeDispose: typeof import('vue')['onScopeDispose']
+  const onServerPrefetch: typeof import('vue')['onServerPrefetch']
+  const onUnmounted: typeof import('vue')['onUnmounted']
+  const onUpdated: typeof import('vue')['onUpdated']
+  const provide: typeof import('vue')['provide']
+  const reactive: typeof import('vue')['reactive']
+  const readonly: typeof import('vue')['readonly']
+  const ref: typeof import('vue')['ref']
+  const resolveComponent: typeof import('vue')['resolveComponent']
+  const shallowReactive: typeof import('vue')['shallowReactive']
+  const shallowReadonly: typeof import('vue')['shallowReadonly']
+  const shallowRef: typeof import('vue')['shallowRef']
+  const toRaw: typeof import('vue')['toRaw']
+  const toRef: typeof import('vue')['toRef']
+  const toRefs: typeof import('vue')['toRefs']
+  const toValue: typeof import('vue')['toValue']
+  const triggerRef: typeof import('vue')['triggerRef']
+  const unref: typeof import('vue')['unref']
+  const useAttrs: typeof import('vue')['useAttrs']
+  const useCssModule: typeof import('vue')['useCssModule']
+  const useCssVars: typeof import('vue')['useCssVars']
+  const useLink: typeof import('vue-router')['useLink']
+  const useRoute: typeof import('vue-router')['useRoute']
+  const useRouter: typeof import('vue-router')['useRouter']
+  const useSlots: typeof import('vue')['useSlots']
+  const watch: typeof import('vue')['watch']
+  const watchEffect: typeof import('vue')['watchEffect']
+  const watchPostEffect: typeof import('vue')['watchPostEffect']
+  const watchSyncEffect: typeof import('vue')['watchSyncEffect']
+}
+// for type re-export
+declare global {
+  // @ts-ignore
+  export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
+  import('vue')
+}

+ 15 - 0
src/base.css

@@ -0,0 +1,15 @@
+#app {
+  margin: 0;
+  width: 100vw;
+  height: 100vh;
+  /* overflow: hidden; */
+}
+body {
+  margin: 0;
+  padding: 0;
+  display: block;
+}
+* {
+  margin: 0;
+  padding: 0;
+}

+ 7 - 0
src/images.d.ts

@@ -0,0 +1,7 @@
+declare module '*.svg'
+declare module '*.png'
+declare module '*.jpg'
+declare module '*.jpeg'
+declare module '*.gif'
+declare module '*.bmp'
+declare module '*.tiff'

+ 27 - 0
src/main.ts

@@ -0,0 +1,27 @@
+import './base.css'
+
+import { createApp } from 'vue'
+import { createPinia } from 'pinia'
+
+import App from './App.vue'
+import router from './router'
+import { Field, CellGroup, Toast, Swipe, SwipeItem, Tab, Tabs, Search } from 'vant'
+import 'vant/lib/index.css'
+// import "viewerjs/dist/viewer.css";
+// import Viewer from "v-viewer";
+
+const app = createApp(App)
+
+app.use(createPinia())
+app.use(router)
+app.use(Toast)
+app.use(Swipe)
+app.use(SwipeItem)
+app.use(Tab)
+app.use(Tabs)
+app.use(Search)
+app.use(Field)
+app.use(CellGroup)
+// app.use(Viewer)
+
+app.mount('#app')

+ 110 - 0
src/router/index.ts

@@ -0,0 +1,110 @@
+import { createRouter, createWebHashHistory } from 'vue-router'
+
+const routes = [
+  {
+    path: '/',
+    name: 'overview',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/EnterNingguo/summarize.vue')
+  },
+  {
+    path: '/dynamic',
+    name: 'dynamic',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/EnterNingguo/dynamic.vue')
+  },
+  {
+    path: '/dynamic/detail/:id',
+    name: 'dynamicDetail',
+    component: () => import('@/views/EnterNingguo/dynamic-detail.vue'),
+    props: true
+  },
+  {
+    path: '/artwork',
+    name: 'artwork',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/EnterNingguo/artwork.vue')
+  },
+  {
+    path: '/treasure',
+    name: 'treasure',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/SmartTour/treasure.vue')
+  },
+  {
+    path: '/treasure/detail/:id',
+    name: 'treasureDetail',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/SmartTour/treasure-detail.vue')
+  },
+  {
+    path: '/exhibition',
+    name: 'exhibition',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/SmartTour/exhibition.vue')
+  },
+  {
+    path: '/exhibition/detail/:id',
+    name: 'exhibitionDetail',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/SmartTour/exhibition-detail.vue')
+  },
+
+  {
+    path: '/booking',
+    name: 'booking',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/ExhibitionService/bookedList.vue')
+  },
+
+  {
+    path: '/activeBooking',
+    name: 'activeBooking',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/ExhibitionService/activeBooking.vue')
+  },
+
+  {
+    path: '/activeBooking/detail/:id',
+    name: 'activeDetail',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/ExhibitionService/active-detail.vue')
+  },
+  // 填写预约信息
+  {
+    path: '/activeBooking/booking/:id/:title',
+    name: 'activeBookInfo',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/ExhibitionService/active-info.vue')
+  },
+
+  {
+    path: '/volunteerHome',
+    name: 'volunteerHome',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/VolunteerHome/home.vue')
+  },
+
+  {
+    path: '/volunteerHome/detail/:id',
+    name: 'volunteerDetail',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/VolunteerHome/detail.vue')
+  },
+
+  {
+    path: '/volunteerHome/apply',
+    name: 'activeBookApply',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/VolunteerHome/apply.vue')
+  },
+
+  
+]
+// 路由
+const router = createRouter({
+  history: createWebHashHistory(),
+  routes
+})
+// 导出
+export default router

+ 15 - 0
src/stores/index.ts

@@ -0,0 +1,15 @@
+import { defineStore } from 'pinia'
+
+export const useStore = defineStore('home', {
+  // 相当于data
+  state: () => {
+    return {
+      // 原始数据
+      dataAll: {} as any,
+    }
+  },
+  // 相当于计算属性
+  getters: {},
+  // 相当于vuex的 mutation + action,可以同时写同步和异步的代码
+  actions: {}
+})

+ 9 - 0
src/types/api/dynamic.d.ts

@@ -0,0 +1,9 @@
+export type dynamicDetailType = {
+  id: number
+  title: String
+  thebm: String
+  abstract: String
+  mainBody: String
+  videos: String[]
+  releaseTime: String
+}

+ 7 - 0
src/types/declaration.d.ts

@@ -0,0 +1,7 @@
+declare module "history";
+declare module "*.scss";
+declare module "*.png";
+declare module "*.jpg";
+declare module "*.gif";
+declare module "js-export-excel";
+declare module 'braft-utils';

+ 4 - 0
src/types/index.d.ts

@@ -0,0 +1,4 @@
+export * from './api/dynamic'
+
+
+

+ 36 - 0
src/utils/browser.ts

@@ -0,0 +1,36 @@
+function versions () {
+  const u = window.navigator.userAgent
+  return {
+    // IE内核
+    trident: u.indexOf('Trident') > -1,
+    // Firefox
+    firefox: u.indexOf('Firefox') > -1,
+    // edge
+    edge: u.indexOf('Edge') > -1,
+    // opera内核
+    presto: u.indexOf('Presto') > -1,
+    // 苹果、谷歌内核
+    webKit: u.indexOf('AppleWebKit') > -1,
+    // 火狐内核
+    gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1,
+    // 是否为移动终端
+    mobile: /Android|webOS|iPhone|iPod|BlackBerry|SM-T|GT-P|Note|Tab|Nexus|Pixel|Tablet|Mi-Tab|Mi-Box|Huawei|Redmi|Mobile|XiaoMi/i.test(navigator.userAgent),
+    // ios终端
+    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
+    // android终端或者uc浏览器
+    android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1,
+    // 是否为iPhone或者安卓QQ浏览器
+    iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1,
+    // 是否为iPad
+    iPad: u.indexOf('iPad') > -1,
+    // 是否为web应用程序,没有头部与底部
+    webApp: u.indexOf('Safari') === -1,
+    // 是否为微信浏览器
+    weixin: ~u.indexOf('MicroMessenger'),
+    // 获取浏览器语言
+    // @ts-ignore
+    language: (navigator.browserLanguage || navigator.language).toLowerCase()
+  }
+}
+
+export default versions()

+ 10 - 0
src/utils/https.ts

@@ -0,0 +1,10 @@
+// const baseURl = ''
+// 本地
+// export const baseURl = 'http://127.0.0.1:5174/staticData'
+export const baseURl = './staticData'
+
+// 线上开发
+const baseResourceUrl = './staticData'
+
+export default baseResourceUrl
+ 

+ 100 - 0
src/utils/pass.ts

@@ -0,0 +1,100 @@
+function randomWord(randomFlag: boolean, min: number, max: number = 15) {
+  let str = "";
+  let range = min;
+  const arr = [
+    "0",
+    "1",
+    "2",
+    "3",
+    "4",
+    "5",
+    "6",
+    "7",
+    "8",
+    "9",
+    "a",
+    "b",
+    "c",
+    "d",
+    "e",
+    "f",
+    "g",
+    "h",
+    "i",
+    "j",
+    "k",
+    "l",
+    "m",
+    "n",
+    "o",
+    "p",
+    "q",
+    "r",
+    "s",
+    "t",
+    "u",
+    "v",
+    "w",
+    "x",
+    "y",
+    "z",
+    "A",
+    "B",
+    "C",
+    "D",
+    "E",
+    "F",
+    "G",
+    "H",
+    "I",
+    "J",
+    "K",
+    "L",
+    "M",
+    "N",
+    "O",
+    "P",
+    "Q",
+    "R",
+    "S",
+    "T",
+    "U",
+    "V",
+    "W",
+    "X",
+    "Y",
+    "Z",
+  ];
+  // 随机产生
+  if (randomFlag) {
+    range = Math.round(Math.random() * (max - min)) + min;
+  }
+  for (let i = 0; i < range; i++) {
+    const pos = Math.round(Math.random() * (arr.length - 1));
+    str += arr[pos];
+  }
+  return str;
+}
+
+const encodeStr = (str: string, strv = "") => {
+  const NUM = 2;
+  const front = randomWord(false, 8);
+  const middle = randomWord(false, 8);
+  const end = randomWord(false, 8);
+
+  const str1 = str.substring(0, NUM);
+  const str2 = str.substring(NUM);
+
+  if (strv) {
+    const strv1 = strv.substring(0, NUM);
+    const strv2 = strv.substring(NUM);
+    return [
+      front + str2 + middle + str1 + end,
+      front + strv2 + middle + strv1 + end,
+    ];
+  }
+
+  return front + str2 + middle + str1 + end;
+};
+
+export default encodeStr;

+ 174 - 0
src/views/EnterNingguo/artwork.vue

@@ -0,0 +1,174 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<script setup lang='ts'>
+import { ArtworkApi } from '@/api/api/artwork'
+import { showToast } from 'vant'
+
+
+export type artworkType = {
+  id: number
+  title: string
+  thebm: string
+  url: string
+  releaseTime: string
+}
+
+const searchValue = ref('')
+
+const searchList = ref([] as artworkType[])
+
+
+const onSearch = () => {
+
+}
+
+const onCancel = () => {
+
+}
+
+
+const getList = async () => {
+  const res: any = await ArtworkApi.getSearchByKeyword({ keyword: searchValue })
+  if (res.code == 0) {
+    searchList.value = res.data
+  } else {
+    showToast('活动信息获取失败')
+  }
+}
+
+onBeforeMount(() => {
+  // getList()
+  searchList.value = [
+    {
+      id: 0,
+      title: '好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fbao%2Fuploaded%2Fi3%2F2209785631188%2FO1CN016n4XME1Ke9GzZUhjw_%21%210-item_pic.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313398&t=69a2df03775aed2b358ad38a1427108a',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 1,
+      title: '好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F25%2F20190125175611_ANBHn.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313455&t=c5c12a6bcb52af950f13f93b94dee082',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 2,
+      title: '好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F25%2F20190125175611_ANBHn.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313455&t=c5c12a6bcb52af950f13f93b94dee082',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 0,
+      title: '好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fbao%2Fuploaded%2Fi3%2F2209785631188%2FO1CN016n4XME1Ke9GzZUhjw_%21%210-item_pic.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313398&t=69a2df03775aed2b358ad38a1427108a',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 1,
+      title: '好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F25%2F20190125175611_ANBHn.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313455&t=c5c12a6bcb52af950f13f93b94dee082',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 2,
+      title: '好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F25%2F20190125175611_ANBHn.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313455&t=c5c12a6bcb52af950f13f93b94dee082',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 0,
+      title: '好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fbao%2Fuploaded%2Fi3%2F2209785631188%2FO1CN016n4XME1Ke9GzZUhjw_%21%210-item_pic.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313398&t=69a2df03775aed2b358ad38a1427108a',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 1,
+      title: '好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F25%2F20190125175611_ANBHn.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313455&t=c5c12a6bcb52af950f13f93b94dee082',
+      url: '',
+      releaseTime: ''
+    },
+    {
+      id: 2,
+      title: '好物好物好物好物好物好物好物好物好物好物',
+      thebm: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F25%2F20190125175611_ANBHn.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715313455&t=c5c12a6bcb52af950f13f93b94dee082',
+      url: '',
+      releaseTime: ''
+    },
+  ]
+})
+
+</script>
+
+<template>
+  <div class='artwork-box'>
+    <div class="search-box">
+      <van-search v-model="searchValue" @search="onSearch" @cancel="onCancel" placeholder="请输入搜索关键词" />
+    </div>
+    <div class="search-list">
+      <div class="list-item" v-for="(item, index) in searchList" :key="index">
+        <img :src="item.thebm" alt="">
+        <div class="title">{{ item.title }}</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang='less' scoped>
+.artwork-box {
+  width: 100%;
+
+  .search-box {
+    width: 100%;
+  }
+
+  .search-list {
+    width: 100%;
+    padding: 10px;
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    grid-auto-rows: auto;
+    gap: 10px;
+    box-sizing: border-box;
+
+
+    .list-item {
+      width: 100%;
+      height: auto;
+      background: rgb(163, 161, 161);
+      padding: 10px;
+      box-sizing: border-box;
+
+      img {
+        width: 100%;
+        height: 25vh;
+        object-fit: cover;
+      }
+
+      .title {
+        font-size: 1em;
+        font-weight: bold;
+        display: -webkit-box;
+        /* 必须添加,以启用WebKit的弹性盒模型布局 */
+        -webkit-line-clamp: 2;
+        /* 最多显示两行 */
+        -webkit-box-orient: vertical;
+        /* 必须添加,使文本垂直显示 */
+
+        overflow: hidden;
+        /* 隐藏超出部分 */
+        text-overflow: ellipsis;
+        /* 末尾显示省略号 */
+        word-break: break-all;
+        /* 可选,根据需要断开长单词以适应行宽 */
+      }
+    }
+  }
+}
+</style>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 129 - 0
src/views/EnterNingguo/dynamic-detail.vue


+ 213 - 0
src/views/EnterNingguo/dynamic.vue

@@ -0,0 +1,213 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<script setup lang='ts'>
+import { DynamicApi } from '@/api/api/dynamic';
+import { showToast } from 'vant';
+
+
+const active = ref(0)
+
+const router = useRouter()
+
+const data = ref([] as any)
+
+const goDetai = (id: number) => {
+  router.push({ name: 'dynamicDetail', params: { id } });
+}
+
+const getList = async () => {
+  const res: any = await DynamicApi.getDynamicList()
+  if (res.code == 0) {
+    data.value = res.data
+  } else {
+    showToast('活动信息获取失败')
+  }
+}
+
+onBeforeMount(() => {
+  // getList()
+  data.value = [
+    {
+      type: '全部',
+      activitys: [
+        {
+          id: 0,
+          title: '宁国博物馆开放日',
+          thebm: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+        {
+          id: 1,
+          title: '宁国博物馆开放日',
+          thebm: '',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+        {
+          id: 2,
+          title: '宁国博物馆开放日',
+          thebm: '',
+          abstract: '',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+        {
+          id: 3,
+          title: '宁国博物馆开放日',
+          thebm: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+      ]
+    },
+    {
+      type: '展览开放',
+      activitys: [
+        {
+          id: 4,
+          title: '宁国博物馆开放日',
+          thebm: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+      ]
+    },
+    {
+      type: '展览开放',
+      activitys: [
+        {
+          id: 5,
+          title: '宁国博物馆开放日',
+          thebm: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+      ]
+    },
+    {
+      type: '展览开放',
+      activitys: [
+        {
+          id: 6,
+          title: '宁国博物馆开放日',
+          thebm: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+      ]
+    },
+    {
+      type: '展览开放',
+      activitys: [
+        {
+          id: 7,
+          title: '宁国博物馆开放日',
+          thebm: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          abstract: '这是摘要这是摘要',
+          mainBody: '这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文这是正文',
+          videos: [
+            'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+          ],
+          releaseTime: '2023-12-27'
+        },
+      ]
+    }
+  ]
+})
+</script>
+
+<template>
+  <div class='dynamic'>
+    <van-tabs v-model:active="active" id="tabs">
+      <van-tab v-for="(item, index) in data" :key="index" :title="item.type">
+        <!-- <div>{{ active }}</div> -->
+        <div class="tab-content">
+          <div class="activity-card" v-for="(item, index) in data[active].activitys" :key="index"
+            @click="goDetai(item.id)">
+            <img v-show="item.thebm != ''" class="thebm" :src="item.thebm" alt="">
+            <div class="title">{{ item.title }}</div>
+            <div v-show="item.abstract != ''" class="abstract">{{ item.abstract }}</div>
+            <div class="time">
+              {{ item.releaseTime }}
+            </div>
+          </div>
+        </div>
+      </van-tab>
+    </van-tabs>
+  </div>
+</template>
+
+<style lang='less' scoped>
+* {
+  box-sizing: border-box;
+}
+
+.dynamic {
+  width: 100%;
+
+  // padding: 0 10px;\
+  .tab-content {
+    width: 100%;
+    padding: 10px;
+
+    .activity-card {
+      width: 100%;
+      background: rgba(177, 177, 177, 0.226);
+      border-radius: 15px;
+      padding: 20px;
+      margin-bottom: 20px;
+
+      .thebm {
+        width: 100%;
+      }
+
+      .title {
+        font-size: 1.2em;
+        font-weight: bold;
+        line-height: 1.3em;
+      }
+
+      .abstract {
+        font-size: 0.9em;
+        color: gray;
+      }
+
+      .time {
+        width: 100%;
+        text-align: right;
+      }
+
+
+    }
+  }
+
+
+}
+</style>

+ 68 - 0
src/views/EnterNingguo/summarize.vue

@@ -0,0 +1,68 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<script setup lang='ts'>
+import { SummarizeApi } from "@/api/api/summarize/index";
+import { showToast } from "vant";
+
+const summarize = ref({} as any)
+
+const videos = ref([
+  'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4',
+  'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4',
+  'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4',
+  'https://wxfalangchang.4dage.com/national/1687243969660/thumb/20230710_094753323140.mp4'
+] as any)
+
+const htmlContent = ref('<p>八骏马图周器垒</p><p>      创造者、设计者:戴嘉林   高:38.8cm 口:12.1cm 足:14cm</p><p>      2017年11月8日,国家主席习近平和夫人彭丽媛陪同来华进行国事访问的美国总统特朗普和夫人梅拉尼娅一同参观故宫。宾主来到畅音阁,沿途欣赏了景泰蓝工艺精品和制作技艺展示,并尝试为景泰蓝《八骏马周器垒》,《国色天香》瓶点蓝,领略中华文化。</p><p></p>')
+
+onBeforeMount(async () => {
+  const res: any = await SummarizeApi.getSummerize()
+  if (res.code == 0) {
+    summarize.value = res.data
+  } else {
+    showToast('系统出错')
+  }
+})
+</script>
+
+<template>
+  <div class='home'>
+    <div class="video-box" v-if="videos.length > 0">
+      <van-swipe class="my-swipe" indicator-color="white" lazy-render>
+        <van-swipe-item v-for="(item, index) in videos" :key="index"><video :src="item"
+            controls></video></van-swipe-item>
+      </van-swipe>
+    </div>
+    <div class="content" v-html="htmlContent"></div>
+  </div>
+</template>
+
+<style lang='less' scoped>
+.home {
+  width: 100%;
+
+  .video-box {
+    width: 100%;
+    // height: auto;
+
+    .my-swipe .van-swipe-item {
+      width: 100%;
+      height: 31.5vh;
+      color: #fff;
+      font-size: 20px;
+      line-height: 150px;
+      text-align: center;
+      // background-color: #39a9ed;
+
+      video {
+        width: 100%;
+      }
+    }
+  }
+
+  .content {
+    white-space: pre-wrap;
+  }
+
+
+}
+</style>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 151 - 0
src/views/ExhibitionService/active-detail.vue


+ 106 - 0
src/views/ExhibitionService/active-info.vue

@@ -0,0 +1,106 @@
+<script setup lang='ts'>
+import { showToast } from 'vant';
+
+const route = useRoute()
+
+export type infoDetailType = {
+  name: string,
+  phone: string,
+  idCard: string,
+  explain: string
+}
+
+const infoDetail = ref({
+  name: '',
+  phone: '',
+  idCard: '',
+  explain: ''
+} as infoDetailType)
+
+const submit = () => {
+  if(infoDetail.value.name.length == 0){
+    showToast('预约姓名不能为空!')
+    return 
+  }
+
+  if(infoDetail.value.phone.length == 0){
+    showToast('预约联系电话不能为空!')
+    return 
+  }
+  
+  if(!/^((1[3-9]\d{9})|(09\d{8}))$/.test(infoDetail.value.phone)){
+    showToast('请输入正确的联系电话!')
+    return
+  }
+
+
+  if(infoDetail.value.idCard.length == 0){
+    showToast('预约身份证号不能为空!')
+    return 
+  }
+
+  if(!/^(^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X|x))$/.test(infoDetail.value.idCard)){
+    showToast('请输入正确的身份证号!')
+    return
+  }
+
+}
+
+</script>
+
+<template>
+  <div class='info-box'>
+    <div class="title">{{ route.params.title }}</div>
+    <div class="form">
+      <van-field v-model="infoDetail.name" required label="姓名" placeholder="请输入内容" />
+      <van-field v-model="infoDetail.phone" required label="联系电话" placeholder="请输入内容" />
+      <van-field v-model="infoDetail.idCard" required label="身份证号" placeholder="请输入内容" />
+      <van-field v-model="infoDetail.explain" label="预约说明" placeholder="请输入您想参加的活动或其他需求" />
+    </div>
+    <div class="commit-box">
+      <div class="tips"> 提交后,请等待工作人员与您取得联系</div>
+      <div class="commit-btn" @click="submit()">提交</div>
+    </div>
+  </div>
+</template>
+
+<style lang='less' scoped>
+* {
+  box-sizing: border-box;
+}
+
+.info-box {
+  width: 100%;
+  height: 100%;
+  padding: 20px;
+
+
+
+  .form {}
+
+  .commit-box {
+    position: fixed;
+    bottom: 0;
+    width: calc(100% - 40px);
+
+    .tips {
+      color: rgba(128, 128, 128, 0.767);
+      width: 100%;
+      text-align: center;
+    }
+    .commit-btn{
+      width: 100%;
+      height: 40px;
+      background: gray;
+      border-radius: 50px;
+      color: white;
+      font-weight: bold;
+      font-size: 1.2em;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      margin: 10px 0;
+    }
+  }
+}
+</style>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 154 - 0
src/views/ExhibitionService/activeBooking.vue


+ 18 - 0
src/views/ExhibitionService/bookedList.vue

@@ -0,0 +1,18 @@
+<script setup lang='ts'>
+
+const bookedList = ref([] as any)
+</script>
+
+<template>
+  <div class='booked-box'>
+    <div>我的预约</div>
+    <div v-if="bookedList.length == 0">暂无预约</div>
+    <div v-else>
+      <!-- <div class="booking-card" v-for="(item, index) in bookedList" :key="index" >
+        <div>{{ item. }}</div>
+      </div> -->
+    </div>
+  </div>
+</template>
+
+<style lang='less' scoped></style>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 162 - 0
src/views/SmartTour/exhibition-detail.vue


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 218 - 0
src/views/SmartTour/exhibition.vue


+ 261 - 0
src/views/SmartTour/treasure-detail.vue

@@ -0,0 +1,261 @@
+<script setup lang='ts'>
+import playIcon from '@/assets/images/play.png';
+import pauseIcon from '@/assets/images/pause.png';
+
+
+// import { DynamicApi } from "@/api/api/dynamic/index";
+// import { showToast } from "vant";
+
+const router = useRouter()
+// const route = useRoute()
+
+
+
+
+export type TreasureDetailType = {
+  id: number,
+  title: string,
+  type: string,
+  era: string,
+  character: string,
+  info: string,
+  size: string,
+  themb: string,
+  files: {
+    images: string[],
+    moduleUrl: string,
+    audio: string,
+    // 可能是单个可能是多个
+    videos: string[],
+  }
+  releaseTime: string
+}
+
+const dynamicDetail = ref({} as TreasureDetailType)
+
+const audioPlaying = ref(null as any)
+const audioBgUrl = ref(null as any)
+
+
+// 当前显示什么状态的多媒体  module videos images
+const curState = ref(null as any)
+
+// 当前显示的多媒体的列表内容
+const curMediaList = ref(null as any)
+
+// 当前列表的索引
+const curMediaIndex = ref(0)
+
+const initModule = () => {
+  curState.value = 'module'
+  curMediaList.value = [dynamicDetail.value.files.moduleUrl]
+  curMediaIndex.value = 0
+}
+
+const initImages = () => {
+  curState.value = 'images'
+  curMediaList.value = dynamicDetail.value.files.images
+  curMediaIndex.value = 0
+}
+
+const initVideos = () => {
+  curState.value = 'videos'
+  curMediaList.value = dynamicDetail.value.files.videos
+  curMediaIndex.value = 0
+}
+
+const audioChange = () => {
+  audioPlaying.value = !audioPlaying.value
+  const audioDom: any = document.getElementById('audioBg')
+  if (audioPlaying.value) {
+    audioDom.play()
+  } else {
+    audioDom.pause()
+  }
+}
+
+onBeforeMount(async () => {
+  // 获取活动详情
+  // const res: any = await DynamicApi.getDetailById(Number(route.params.id))
+  // if (res.code == 0) {
+  //   dynamicDetail.value = res.data
+
+  // } else {
+  //   showToast('活动信息获取失败')
+  // }
+
+  dynamicDetail.value = {
+    id: 0,
+    title: '《瓜洲马头新建石堤记》碑拓片',
+    type: '全部',
+    era: '朝代',
+    character: '质地',
+    info: '<p>八骏马图周器垒</p><p>      创造者、设计者:戴嘉林   高:38.8cm 口:12.1cm 足:14cm</p><p>      2017年11月8日,国家主席习近平和夫人彭丽媛陪同来华进行国事访问的美国总统特朗普和夫人梅拉尼娅一同参观故宫。宾主来到畅音阁,沿途欣赏了景泰蓝工艺精品和制作技艺展示,并尝试为景泰蓝《八骏马周器垒》,《国色天香》瓶点蓝,领略中华文化。</p><p></p>',
+    size: '尺寸:志盖边长 40.5 厘米、厚 8.5 厘米、志石边长 41 厘米、厚 9.5 厘米',
+    themb: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+    files: {
+      images: ['https://super.4dage.com/data/TEST/edit/20230407_114029890.jpg', 'https://super.4dage.com/data/TEST/edit/20230524_155459428.png'],
+      moduleUrl: 'https://4dscene.4dage.com/culturalrelics/demo2/Model.html?m=HG01',
+      audio: 'https://houseoss.4dkankan.com/project/bjfljtl/audio/bgMusic.mp3',
+      // 可能是单个可能是多个
+      videos: ['https://super.4dage.com/data/TEST/edit/20230228_161113155.mp4'],
+    },
+    releaseTime: '2023-12-27'
+  }
+
+  // 初始化显示状态
+  if (dynamicDetail.value.files.moduleUrl != '') {
+    initModule()
+  } else if (dynamicDetail.value.files.images.length > 0) {
+    initImages()
+  } else if (dynamicDetail.value.files.videos.length > 0) {
+    initVideos()
+  }
+
+  audioBgUrl.value = dynamicDetail.value.files.audio
+})
+</script>
+
+<template>
+  <div class='detail-box'>
+
+    <div class="media-box" v-if="curState != null">
+      <img @click="() => { curMediaIndex-- }" v-show="curMediaIndex != 0 && curMediaList.length > 1" class="left-icon"
+        src="@/assets/images/left.png" alt="">
+      <img @click="() => { curMediaIndex++ }" v-show="curMediaIndex != curMediaList.length - 1"
+        class="left-icon right-icon" src="@/assets/images/right.png" alt="">
+      <img v-if="curState === 'images'" :src="curMediaList[curMediaIndex]" alt="">
+      <video v-if="curState === 'videos'" :src="curMediaList[curMediaIndex]" controls></video>
+      <iframe v-if="curState === 'module'" :src="curMediaList[curMediaIndex]" frameborder="0"></iframe>
+
+      <div class="option-box">
+        <div v-if="dynamicDetail.files.moduleUrl != ''" @click="initModule()"
+          :class="{ active: curState === 'module' }">模型</div>
+        <div v-if="dynamicDetail.files.images.length != 0" @click="initImages()"
+          :class="{ active: curState === 'images' }">图片<span v-show="curState === 'images'">{{
+            curMediaIndex + 1 + '/' + curMediaList.length
+          }}</span></div>
+        <div v-if="dynamicDetail.files.videos.length != 0" @click="initVideos()"
+          :class="{ active: curState === 'videos' }">视频<span v-show="curState === 'videos'">{{
+            curMediaIndex + 1 + '/' + curMediaList.length
+          }}</span></div>
+      </div>
+    </div>
+    <div class="info-box">
+      <div class="title">{{ dynamicDetail.title }}</div>
+      <div class="era">{{ dynamicDetail.era + '·' + dynamicDetail.character }}</div>
+      <div class="size"> {{ dynamicDetail.size }}</div>
+      <div class="info" v-html="dynamicDetail.info"></div>
+    </div>
+
+    <audio id="audioBg" :src="audioBgUrl" style="display: none;"></audio>
+    <img v-if="audioBgUrl != null" class="playing-icon" :src="audioPlaying ? pauseIcon : playIcon" alt=""
+      @click="audioChange()">
+    <img class="back-icon" @click="() => { router.back() }" src="@/assets/images/back.png" alt="">
+  </div>
+</template>
+
+<style lang='less' scoped>
+.detail-box {
+  width: 100%;
+
+  .media-box {
+    width: 100%;
+    height: 30vh;
+    position: relative;
+
+    .left-icon {
+      width: 30px;
+      height: 30px;
+      position: absolute;
+      left: 10px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+
+    .right-icon {
+      right: 10px;
+      left: auto;
+    }
+
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+    }
+
+    video {
+      width: 100%;
+      height: 100%;
+    }
+
+    iframe {
+      width: 100%;
+      height: 100%;
+    }
+
+    .option-box {
+      width: 70%;
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      bottom: 20px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      div {
+        height: 25px;
+        padding: 0 20px;
+        box-sizing: border-box;
+        line-height: 25px;
+        border-radius: 15px;
+        background: white;
+        color: gray;
+        font-weight: bold;
+        font-size: 0.8em;
+
+        span {
+          margin-left: 5px;
+          font-size: 0.8em;
+          font-weight: 400;
+        }
+      }
+
+      .active {
+        background: gray;
+        color: white;
+      }
+    }
+
+    .info-box{
+      .title{
+
+      }
+      .era{
+
+      }
+      .size{
+
+      }
+      .info{
+        white-space: pre-wrap;
+      }
+    }
+  }
+
+  .playing-icon {
+    width: 40px;
+    position: fixed;
+    right: 10px;
+    bottom: 18vh;
+  }
+
+  .back-icon {
+    width: 40px;
+    position: fixed;
+    right: 10px;
+    bottom: 10vh;
+  }
+}
+</style>

+ 203 - 0
src/views/SmartTour/treasure.vue

@@ -0,0 +1,203 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<script setup lang='ts'>
+import { TreasureApi } from '@/api/api/treasure';
+import { showToast } from 'vant';
+
+
+const searchValue = ref('')
+const router = useRouter()
+
+const data = ref([] as any)
+
+
+const activeIndex = ref(0)
+
+const onSearch = () => {
+
+}
+
+const onCancel = () => {
+
+}
+
+const goDetai = (id: number) => {
+  router.push({ name: 'treasureDetail', params: { id } });
+}
+
+
+const getList = async () => {
+  const res: any = await TreasureApi.getTreasureList()
+  if (res.code == 0) {
+    data.value = res.data
+  } else {
+    showToast('活动信息获取失败')
+  }
+}
+
+
+onBeforeMount(() => {
+  data.value = [
+    {
+      type: '全部',
+      lists: [
+        {
+          id: 0,
+          title: '《瓜洲马头新建石堤记》碑拓片',
+          type: '全部',
+          era: '朝代',
+          character: '质地',
+          info: '',
+          size: '',
+          themb: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          files: {
+            images: [],
+            moduleUrl: '',
+            audio: '',
+            // 可能是单个可能是多个
+            videos: [],
+            releaseTime: '2023-12-27'
+          }
+        }
+      ]
+    },
+    {
+      type: '类型1',
+      lists: [
+        {
+          id: 1,
+          title: '《瓜洲马头新建石堤记》碑拓片',
+          type: '全部',
+          era: '朝代',
+          character: '质地',
+          info: '',
+          size: '',
+          themb: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          files: {
+            images: [],
+            moduleUrl: '',
+            audio: '',
+            // 可能是单个可能是多个
+            videos: [],
+            releaseTime: '2023-12-27'
+          }
+        }, {
+          id: 1,
+          title: '《瓜洲马头新建石堤记》碑拓片',
+          type: '全部',
+          era: '朝代',
+          character: '质地',
+          info: '',
+          size: '',
+          themb: 'https://n.sinaimg.cn/sinakd20112/0/w2048h1152/20220428/03e8-399a8decd0e38baf901f375ef9a4c050.jpg',
+          files: {
+            images: [],
+            moduleUrl: '',
+            audio: '',
+            // 可能是单个可能是多个
+            videos: [],
+            releaseTime: '2023-12-27'
+          }
+        }
+      ]
+    },
+    {
+      type: '类型2',
+      lists: [
+
+      ]
+    },
+    {
+      type: '类型3',
+      lists: [
+
+      ]
+    },
+    {
+      type: '类型4',
+      lists: [
+
+      ]
+    }
+  ]
+
+})
+
+
+
+
+</script>
+
+<template>
+  <div class="treasure-box">
+    <div class="search-box">
+      <van-search v-model="searchValue" @search="onSearch" @cancel="onCancel" placeholder="请输入搜索关键词" />
+    </div>
+    <div class="content-box">
+      <van-tabs v-model:active="activeIndex">
+        <van-tab v-for="(item, index) in data" :key="index" :title="item.type">
+          <!-- <div>{{ activeIndex }}</div> -->
+          <div class="tab-content" v-if="data[activeIndex].lists.length > 0">
+            <div class="activity-card" v-for="(item, index) in data[activeIndex].lists" :key="index"
+              @click="goDetai(item.id)">
+              <img v-show="item.themb != ''" class="themb" :src="item.themb" alt="">
+              <div class="detail">{{ item.era + '·' + item.character }}</div>
+              <div class="title">{{ item.title }}</div>
+            </div>
+          </div>
+          <div v-else class="no-data">暂无内容</div>
+        </van-tab>
+      </van-tabs>
+    </div>
+  </div>
+</template>
+
+<style lang='less' scoped>
+.treasure-box {
+  width: 100%;
+
+  .search-box {
+    width: 100%;
+  }
+
+  .content-box {
+    width: 100%;
+    padding: 0px 10px;
+    box-sizing: border-box;
+
+    .tab-content {
+      width: 100%;
+
+      .activity-card {
+        width: 100%;
+        padding: 10px;
+        box-sizing: border-box;
+        margin-bottom: 20px;
+
+        img {
+          width: 100%;
+        }
+
+        .detail {
+          font-size: 0.8em;
+          color: gray;
+          margin-top: 10px;
+        }
+
+        .title {
+          font-size: 1em;
+          font-weight: bold;
+          margin-top: 5px;
+        }
+      }
+    }
+
+    .no-data {
+      width: 100%;
+      height: 80vh;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+  }
+}
+</style>

+ 105 - 0
src/views/VolunteerHome/apply.vue

@@ -0,0 +1,105 @@
+<script setup lang='ts'>
+import { showToast } from 'vant';
+
+const route = useRoute()
+
+export type infoDetailType = {
+  name: string,
+  phone: string,
+  idCard: string,
+  explain: string
+}
+
+const infoDetail = ref({
+  name: '',
+  phone: '',
+  idCard: '',
+  explain: ''
+} as infoDetailType)
+
+const submit = () => {
+  if(infoDetail.value.name.length == 0){
+    showToast('预约姓名不能为空!')
+    return 
+  }
+
+  if(infoDetail.value.phone.length == 0){
+    showToast('预约联系电话不能为空!')
+    return 
+  }
+  
+  if(!/^((1[3-9]\d{9})|(09\d{8}))$/.test(infoDetail.value.phone)){
+    showToast('请输入正确的联系电话!')
+    return
+  }
+
+
+  if(infoDetail.value.idCard.length == 0){
+    showToast('预约身份证号不能为空!')
+    return 
+  }
+
+  if(!/^(^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X|x))$/.test(infoDetail.value.idCard)){
+    showToast('请输入正确的身份证号!')
+    return
+  }
+
+}
+
+</script>
+
+<template>
+  <div class='info-box'>
+    <div class="form">
+      <van-field v-model="infoDetail.name" required label="姓名" placeholder="请输入内容" />
+      <van-field v-model="infoDetail.phone" required label="联系电话" placeholder="请输入内容" />
+      <van-field v-model="infoDetail.idCard" required label="身份证号" placeholder="请输入内容" />
+      <van-field v-model="infoDetail.explain" label="预约说明" placeholder="请输入您想参加的活动或其他需求" />
+    </div>
+    <div class="commit-box">
+      <div class="tips"> 提交后,请等待工作人员与您取得联系</div>
+      <div class="commit-btn" @click="submit()">提交</div>
+    </div>
+  </div>
+</template>
+
+<style lang='less' scoped>
+* {
+  box-sizing: border-box;
+}
+
+.info-box {
+  width: 100%;
+  height: 100%;
+  padding: 20px;
+
+
+
+  .form {}
+
+  .commit-box {
+    position: fixed;
+    bottom: 0;
+    width: calc(100% - 40px);
+
+    .tips {
+      color: rgba(128, 128, 128, 0.767);
+      width: 100%;
+      text-align: center;
+    }
+    .commit-btn{
+      width: 100%;
+      height: 40px;
+      background: gray;
+      border-radius: 50px;
+      color: white;
+      font-weight: bold;
+      font-size: 1.2em;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      margin: 10px 0;
+    }
+  }
+}
+</style>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 146 - 0
src/views/VolunteerHome/detail.vue


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 156 - 0
src/views/VolunteerHome/home.vue


+ 13 - 0
tsconfig.app.json

@@ -0,0 +1,13 @@
+{
+  "extends": "@vue/tsconfig/tsconfig.dom.json",
+  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
+  "exclude": ["src/**/__tests__/*"],
+  "compilerOptions": {
+    "composite": true,
+    "noEmit": true,
+    "baseUrl": ".",
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  }
+}

+ 30 - 0
tsconfig.json

@@ -0,0 +1,30 @@
+{
+  "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,
+    "noFallthroughCasesInSwitch": true,
+
+    // 配置@别名
+    "baseUrl": ".",
+    "paths": {
+      "@/*": ["./src/*"]
+    },
+  },
+  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
+}

+ 17 - 0
tsconfig.node.json

@@ -0,0 +1,17 @@
+{
+  "extends": "@tsconfig/node18/tsconfig.json",
+  "include": [
+    "vite.config.*",
+    "vitest.config.*",
+    "cypress.config.*",
+    "nightwatch.conf.*",
+    "playwright.config.*"
+  ],
+  "compilerOptions": {
+    "composite": true,
+    "noEmit": true,
+    "module": "ESNext",
+    "moduleResolution": "Bundler",
+    "types": ["node"]
+  }
+}

+ 44 - 0
vite.config.ts

@@ -0,0 +1,44 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import Components from 'unplugin-vue-components/vite'
+import { VantResolver } from 'unplugin-vue-components/resolvers'
+// 自动按需导入
+import AutoImport from 'unplugin-auto-import/vite'
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
+
+import { resolve } from 'path'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  base: './',
+  plugins: [
+    vue(),
+    Components({
+      resolvers: [VantResolver(), ElementPlusResolver()]
+    }),
+    AutoImport({
+      //安装两行后你会发现在组件中不用再导入ref,reactive等
+      imports: ['vue', 'vue-router'],
+      //存放的位置
+      dts: 'src/auto-import.d.ts',
+      resolvers: [ElementPlusResolver(),VantResolver()]
+    })
+  ],
+  resolve: {
+    // ↓路径别名
+    alias: {
+      '@': resolve(__dirname, './src')
+    }
+  },
+  build: {
+    outDir: 'dist',
+    assetsDir: 'assets',
+    sourcemap: false,
+    terserOptions: {
+      compress: {
+        drop_console: true,
+        drop_debugger: true
+      }
+    }
+  }
+})

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 2445 - 0
yarn.lock