hookehuyr

初始化

Showing 80 changed files with 2454 additions and 0 deletions
1 +# port
2 +VITE_PORT = 8208
3 +
4 +# 反向代理服务器地址
5 +VITE_PROXY_TARGET = https://oa.onwall.cn
6 +
7 +# API请求前缀
8 +VITE_PROXY_PREFIX = /srv/
9 +
10 +# 打包输出文件夹名称
11 +VITE_OUTDIR = xysBooking
12 +
13 +# 是否开启调试
14 +VITE_CONSOLE = 0
15 +
16 +# appID相关
17 +VITE_APPID=微信appID
1 +# 资源公共路径
2 +VITE_BASE = /
3 +
4 +# 测试open-id
5 +VITE_OPENID = api-test-openid
6 +# VITE_OPENID = o8BRf1gLDWieH3Y3JvbrI_4IjaME
7 +# VITE_OPENID = oJLZq5t9PIKLW9tm1oSUNAuPwssA
8 +# VITE_OPENID = oJLZq5uT_6GwIh2tQWh1F9IoHZ3U
9 +# VITE_OPENID =
10 +
11 +# B端账号
12 +VITE_ID = 13761653761
13 +
14 +# 验证码
15 +VITE_PIN =
16 +
17 +# 反向代理服务器地址
18 +VITE_PROXY_TARGET = https://oa-dev.onwall.cn
19 +# VITE_PROXY_TARGET = http://oa.onwall.cn
20 +
21 +# PC端地址
22 +VITE_MOBILE_URL = http://localhost:5173/
1 +###
2 + # @Date: 2023-08-24 15:30:45
3 + # @LastEditors: hookehuyr hookehuyr@gmail.com
4 + # @LastEditTime: 2023-08-24 16:02:52
5 + # @FilePath: /xysBooking/.env.production
6 + # @Description: 文件描述
7 +###
8 +# 资源公共路径
9 +VITE_BASE = /f/xysBooking/
10 +
11 +# 测试open-id
12 +VITE_APP_OPENID =
13 +
14 +# B端账号
15 +VITE_APP_ID =
16 +
17 +# 验证码
18 +VITE_APP_PIN =
19 +
20 +# 反向代理服务器地址
21 +VITE_PROXY_TARGET = https://oa.onwall.cn
22 +
23 +# PC端地址
24 +# VITE_MOBILE_URL = http://oa.onwall.cn/f/guanzong/web/
25 +# VITE_MOBILE_URL = http://guanzong.onwall.cn/f/guanzong/web/
1 +{
2 + "globals": {
3 + "EffectScope": true,
4 + "computed": true,
5 + "createApp": true,
6 + "customRef": true,
7 + "defineAsyncComponent": true,
8 + "defineComponent": true,
9 + "effectScope": true,
10 + "getCurrentInstance": true,
11 + "getCurrentScope": true,
12 + "h": true,
13 + "inject": true,
14 + "isProxy": true,
15 + "isReactive": true,
16 + "isReadonly": true,
17 + "isRef": true,
18 + "markRaw": true,
19 + "nextTick": true,
20 + "onActivated": true,
21 + "onBeforeMount": true,
22 + "onBeforeUnmount": true,
23 + "onBeforeUpdate": true,
24 + "onDeactivated": true,
25 + "onErrorCaptured": true,
26 + "onMounted": true,
27 + "onRenderTracked": true,
28 + "onRenderTriggered": true,
29 + "onScopeDispose": true,
30 + "onServerPrefetch": true,
31 + "onUnmounted": true,
32 + "onUpdated": true,
33 + "provide": true,
34 + "reactive": true,
35 + "readonly": true,
36 + "ref": true,
37 + "resolveComponent": true,
38 + "shallowReactive": true,
39 + "shallowReadonly": true,
40 + "shallowRef": true,
41 + "toRaw": true,
42 + "toRef": true,
43 + "toRefs": true,
44 + "triggerRef": true,
45 + "unref": true,
46 + "useAttrs": true,
47 + "useCssModule": true,
48 + "useCssVars": true,
49 + "useRoute": true,
50 + "useRouter": true,
51 + "useSlots": true,
52 + "watch": true,
53 + "watchEffect": true,
54 + "watchPostEffect": true,
55 + "watchSyncEffect": true
56 + }
57 +}
...\ No newline at end of file ...\ No newline at end of file
1 +node_modules
2 +.DS_Store
3 +dist
4 +dist-ssr
5 +*.local
6 +.history
7 +doc
8 +.vscode
9 +src/views/test/*
10 +src/store/test.js
11 +cypress
12 +src/test/mocha/test.js
13 +cypress.json
14 +src/test
15 +.idea
16 +xysBooking
1 +{
2 + "esversion": 11,
3 + "asi": true
4 +}
...\ No newline at end of file ...\ No newline at end of file
1 +西园寺预约
2 +
3 +编译产物放到master上面,nsi到oa上面更新
......
1 +export function createProxy(prefix, target) {
2 + const ret = {};
3 + ret[prefix] = {
4 + target,
5 + changeOrigin: true,
6 + ws: true,
7 + // rewrite: (path) => path.replace(/^\/api/, '')
8 + // rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
9 + }
10 + return ret
11 +}
1 +// generated by unplugin-vue-components
2 +// We suggest you to commit this file into source control
3 +// Read more: https://github.com/vuejs/core/pull/3399
4 +import '@vue/runtime-core'
5 +
6 +export {}
7 +
8 +declare module '@vue/runtime-core' {
9 + export interface GlobalComponents {
10 + RouterLink: typeof import('vue-router')['RouterLink']
11 + RouterView: typeof import('vue-router')['RouterView']
12 + VanButton: typeof import('vant/es')['Button']
13 + VanCalendar: typeof import('vant/es')['Calendar']
14 + VanCol: typeof import('vant/es')['Col']
15 + VanDialog: typeof import('vant/es')['Dialog']
16 + VanField: typeof import('vant/es')['Field']
17 + VanForm: typeof import('vant/es')['Form']
18 + VanIcon: typeof import('vant/es')['Icon']
19 + VanRadio: typeof import('vant/es')['Radio']
20 + VanRadioGroup: typeof import('vant/es')['RadioGroup']
21 + VanRow: typeof import('vant/es')['Row']
22 + }
23 +}
1 +<!--
2 + * @Date: 2023-06-13 13:26:46
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-10-25 17:30:49
5 + * @FilePath: /xysBooking/index.html
6 + * @Description: 文件描述
7 +-->
8 +<!DOCTYPE html>
9 +<html lang='zh'>
10 +<head>
11 + <meta charset="UTF-8">
12 + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
13 + <!-- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> -->
14 + <title></title>
15 + <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.compat.css" /> -->
16 +</head>
17 +<body>
18 + <div id="app"></div>
19 + <script type="module" src="/src/main.js"></script>
20 +</body>
21 +</html>
This diff could not be displayed because it is too large.
1 +{
2 + "name": "xysBooking",
3 + "description": "项目, 编译上传直接执行publish, 不需要其他额外操作。",
4 + "version": "1.0.0",
5 + "scripts": {
6 + "dev": "vite",
7 + "start": "vite --host 0.0.0.0",
8 + "build": "vite build",
9 + "build-watch": "vite build --watch",
10 + "build-ts": "vue-tsc --noEmit && vite build",
11 + "serve": "vite preview",
12 + "cypress:open": "cypress open"
13 + },
14 + "dependencies": {
15 + "@vant/area-data": "^1.3.1",
16 + "@vant/touch-emulator": "^1.4.0",
17 + "@vitejs/plugin-legacy": "^1.8.2",
18 + "@vueuse/core": "^8.5.0",
19 + "animate.css": "^4.1.1",
20 + "browser-md5-file": "^1.1.1",
21 + "dayjs": "^1.11.3",
22 + "default-passive-events": "^2.0.0",
23 + "global": "^4.4.0",
24 + "html2canvas": "^1.4.1",
25 + "jquery": "^3.6.0",
26 + "js-cookie": "^3.0.1",
27 + "js-sha1": "^0.6.0",
28 + "lodash": "^4.17.21",
29 + "moment": "^2.29.3",
30 + "mui-player": "^1.7.0",
31 + "sha1": "^1.1.1",
32 + "typescript": "^4.7.3",
33 + "uuid": "^8.3.2",
34 + "vant": "^4.8.2",
35 + "vconsole": "^3.14.6",
36 + "vite-plugin-dynamic-import": "^0.9.6",
37 + "vite-plugin-mp": "^1.6.1",
38 + "vue": "^3.2.36",
39 + "weixin-js-sdk": "^1.6.0",
40 + "xijs": "^1.2.6"
41 + },
42 + "devDependencies": {
43 + "@types/jquery": "^3.5.14",
44 + "@types/lodash": "^4.14.182",
45 + "@types/moment": "^2.13.0",
46 + "@typescript-eslint/parser": "^5.27.1",
47 + "@vitejs/plugin-vue": "^2.3.3",
48 + "@vue/compiler-sfc": "^3.2.36",
49 + "axios": "^0.27.2",
50 + "chai": "^4.3.6",
51 + "cypress": "^9.7.0",
52 + "eslint-plugin-vue": "^9.0.1",
53 + "less": "^4.1.2",
54 + "mocha": "^10.0.0",
55 + "pinia": "^2.0.14",
56 + "postcss-px-to-viewport": "^1.1.1",
57 + "qs": "^6.10.3",
58 + "tslint": "^6.1.3",
59 + "unplugin-auto-import": "^0.8.8",
60 + "unplugin-vue-components": "^0.23.0",
61 + "unplugin-vue-define-options": "^0.6.1",
62 + "vite": "^2.9.9",
63 + "vite-plugin-style-import": "1.4.1",
64 + "vue-esign": "^1.1.4",
65 + "vue-router": "^4.0.15"
66 + }
67 +}
1 +module.exports = {
2 + printWidth: 100, // 代码行的宽度,通用建议每行最大长度建议为100/120,但最好不超过这两个数。
3 + tabWidth: 2, // 指定每次缩进的空格数。
4 + semi: true, // 是否在代码语句结尾添加分号。
5 + vueIndentScriptAndStyle: true,
6 + singleQuote: true, // 是否使用单引号,JSX单独设置。
7 + trailingComma: 'all', // 在多行以逗号分割的句法中尽可能补充尾行逗号。
8 + bracketSpacing: true, // 是否在对象属性与大括号之间填充空格。
9 + bracketSameLine: false, // 开始标签的右尖括号是否跟随在最后一行属性末尾。
10 + proseWrap: 'never',
11 + htmlWhitespaceSensitivity: 'strict',
12 + endOfLine: 'auto', // 设置换行风格,避免不同操作系统造成的大量代码diff。
13 + singleAttributePerLine: false // 在Html,Vue,JSX中是否强制每条属性占用一行。
14 +};
1 +#!/usr/bin/env sh
2 +# -----------------------------------------------
3 +# Filename: publish.sh
4 +# Revision: 1.0
5 +# Date: 2022年5月20日
6 +# Author: Hooke
7 +# Description: **** 根据php项目相应特征书写项目发布流程
8 +# -----------------------------------------------
9 +
10 +# 当发生错误时中止脚本
11 +set -e
12 +
13 +# 本地Git服务器目录路径
14 +path=/Users/huyirui/program/itomix/git/isp/f
15 +
16 +# 编译输出文件夹
17 +output=xysBooking
18 +
19 +# 打包
20 +npm run build
21 +
22 +# 移除Git服务器目录下项目文件夹
23 +rm -r $path"/${output:?}/images"
24 +rm -r $path"/${output:?}/index.html"
25 +rm -r $path"/${output:?}/static"
26 +
27 +# 把本地编译输出文件夹添加到服务器目录
28 +mv "${output:?}/images" $path"/${output:?}"
29 +mv "${output:?}/index.html" $path"/${output:?}"
30 +mv "${output:?}/static" $path"/${output:?}"
31 +
32 +# 提交到Git服务器
33 +cd $path"/${output:?}"
34 +git pull
35 +git add -A
36 +git commit -m '别院预约前端网页更新'
37 +git push
38 +
39 +# 更新SSH服务器上文件
40 +ssh -p 22 itomix@ipadbiz.cn 'cd /opt/space-dev/ && git pull origin develop'
1 +export interface commentListType {
2 + id: string;
3 + avatar: string;
4 + name: string;
5 + kg_name: string;
6 + comment_time: string;
7 + note: string;
8 + c_action: string;
9 + c_name: string;
10 + cover: string;
11 + prod_id: string;
12 + perf_id: string;
13 + book_id: string;
14 + perf_name: string;
15 + book_name: string;
16 + localism_type: string;
17 + is_new: number;
18 +}
1 +<!--
2 + * @Date: 2023-06-13 13:26:46
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-01-15 10:04:45
5 + * @FilePath: /xysBooking/src/App.vue
6 + * @Description: 启动页
7 +-->
8 +<template>
9 + <div class="bg-wrapper">
10 + <div class="box-wrapper">
11 + <div class="box-top"></div>
12 + <router-view></router-view>
13 + </div>
14 + </div>
15 +</template>
16 +
17 +<script setup>
18 +import { mainStore, useTitle } from '@/utils/generatePackage'
19 +import { computed, watchEffect, onMounted } from 'vue';
20 +import { useRoute, useRouter } from 'vue-router'
21 +import { setToastDefaultOptions } from 'vant';
22 +// 会根据配置判断是否显示调试控件
23 +// eslint-disable-next-line no-unused-vars
24 +import vConsole from '@/utils/vconsole'
25 +/*// 初始化WX环境
26 +import wx from 'weixin-js-sdk'
27 +import { wxJsAPI } from '@/api/wx/config'
28 +import { apiList } from '@/api/wx/jsApiList.js'*/
29 +
30 +import { orderInfoAPI } from '@/api/index'
31 +
32 +// 使用 include + pinia 状态管理动态缓存页面
33 +const store = mainStore()
34 +const keepPages = computed(() => store.getKeepPages)
35 +
36 +// TAG: 全局设置页面标题
37 +const $route = useRoute();
38 +const $router = useRouter();
39 +watchEffect(
40 + () => useTitle($route.meta.title)
41 +)
42 +
43 +// TAG: 全局配置Toast
44 +setToastDefaultOptions({
45 + duration: 2000,
46 + className: 'zIndex'
47 +});
48 +
49 +onMounted(async () => {
50 + /*const { data } = await wxJsAPI();
51 + data.jsApiList = apiList;
52 + wx.config(data);
53 + wx.ready(() => {
54 + wx.showAllNonBaseMenuItem();
55 + });
56 + wx.error((err) => {
57 + console.warn(err);
58 + });*/
59 + // 进入后先查询有没有订单,有订单直接跳转最终页面
60 + const { data } = await orderInfoAPI();
61 + if (data?.id) {
62 + $router.replace({
63 + path: '/result',
64 + query: {
65 + id: data.id
66 + }
67 + })
68 + }
69 +})
70 +</script>
71 +
72 +<style lang="less">
73 +@prefix: ~'@{namespace}-x';
74 +
75 +// html,
76 +// body {
77 +// width: 100%;
78 +// height: 100%;
79 +// }
80 +
81 +body {
82 + position: relative;
83 + // --van-white: #fff;
84 + // --van-blue: #1989fa;
85 + // --van-button-primary-color: var(--van-white);
86 + // --van-button-primary-background: var(--van-primary-color);
87 + /* 全局修改主色调 */
88 + // --van-blue: #F9D95C;
89 +
90 + background-color: #F7EFEB;
91 +
92 + p {
93 + margin: 0;
94 + padding: 0;
95 + }
96 +}
97 +
98 +.@{prefix} {
99 + color: red;
100 +}
101 +
102 +.global-center {
103 + position: relative;
104 + top: 50%;
105 + transform: translateY(-50%);
106 +}
107 +
108 +.zIndex {
109 + z-index: 4500 !important;
110 +}
111 +
112 +.bg-wrapper {
113 + padding: 1rem;
114 + padding-bottom: 0;
115 + background-image: url('https://cdn.ipadbiz.cn/bieyuan/bg@2x~1.png');
116 + background-repeat: no-repeat;
117 +}
118 +
119 +.box-wrapper {
120 + background: #FFFFFF;
121 + box-shadow: 0px 0px 13px 0px rgba(95, 69, 54, 0.25);
122 + border-radius: 10px;
123 + border-bottom-right-radius: 0;
124 + border-bottom-left-radius: 0;
125 + min-height: calc(100vh - 1rem);
126 +
127 + .box-top {
128 + padding: 0 1rem 1rem;
129 + height: 1rem;
130 + background-image: url('https://cdn.ipadbiz.cn/bieyuan/top@2x~1.png');
131 + background-repeat: no-repeat;
132 + background-size: calc(100% - 2rem);
133 + background-position: 1rem 0;
134 + /* 向右位移 1rem */
135 + }
136 +}
137 +</style>
1 +/*
2 + * @Date: 2022-06-17 14:54:29
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-06-25 09:33:28
5 + * @FilePath: /huizhu/src/api/common.js
6 + * @Description: 通用接口
7 + */
8 +import { fn, fetch, uploadFn } from '@/api/fn';
9 +
10 +const Api = {
11 + SMS: '/srv/?a=sms',
12 + TOKEN: '/srv/?a=upload',
13 + SAVE_FILE: '/srv/?a=upload&t=save_file',
14 +}
15 +
16 +/**
17 + * @description: 发送验证码
18 + * @param {*} phone 手机号码
19 + * @returns
20 + */
21 +export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
22 +
23 +/**
24 + * @description: 获取七牛token
25 + * @param {*} filename 文件名
26 + * @param {*} file 图片base64
27 + * @returns
28 + */
29 +export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params));
30 +
31 +/**
32 + * @description: 上传七牛
33 + * @param {*}
34 + * @returns
35 + */
36 +export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config));
37 +
38 +/**
39 + * @description: 保存图片
40 + * @param {*} format
41 + * @param {*} hash
42 + * @param {*} height
43 + * @param {*} width
44 + * @param {*} filekey
45 + * @returns
46 + */
47 +export const saveFileAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_FILE, params));
1 +/*
2 + * @Date: 2022-05-18 22:56:08
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-08-24 10:56:44
5 + * @FilePath: /front/src/api/fn.js
6 + * @Description: 文件描述
7 + */
8 +import axios from '@/utils/axios';
9 +import { showSuccessToast, showFailToast } from 'vant';
10 +import qs from 'Qs'
11 +
12 +/**
13 + * 网络请求功能函数
14 + * @param {*} api 请求axios接口
15 + * @returns 请求成功后,获取数据
16 + */
17 +export const fn = (api) => {
18 + return api
19 + .then(res => {
20 + if (res.data.code === 1) {
21 + return res.data || true;
22 + } else {
23 + // tslint:disable-next-line: no-console
24 + console.warn(res);
25 + if (!res.data.show) return false;
26 + showFailToast(res.data.msg);
27 + return false;
28 + }
29 + })
30 + .catch(err => {
31 + // tslint:disable-next-line: no-console
32 + console.error(err);
33 + return false;
34 + })
35 + .finally(() => { // 最终执行
36 + })
37 +}
38 +
39 +/**
40 + * 七牛返回格式
41 + * @param {*} api
42 + * @returns
43 + */
44 +export const uploadFn = (api) => {
45 + return api
46 + .then(res => {
47 + if (res.statusText === 'OK') {
48 + return res.data || true;
49 + } else {
50 + // tslint:disable-next-line: no-console
51 + console.warn(res);
52 + if (!res.data.show) return false;
53 + showFailToast(res.data.msg);
54 + return false;
55 + }
56 + })
57 + .catch(err => {
58 + // tslint:disable-next-line: no-console
59 + console.error(err);
60 + return false;
61 + })
62 +}
63 +
64 +/**
65 + * 统一 GET/POST 不同传参形式
66 + */
67 +export const fetch = {
68 + get: function (api, params) {
69 + return axios.get(api, { params })
70 + },
71 + post: function (api, params) {
72 + return axios.post(api, params)
73 + },
74 + stringifyPost: function (api, params) {
75 + return axios.post(api, qs.stringify(params))
76 + },
77 + basePost: function (url, data, config) {
78 + return axios.post(url, data, config)
79 + }
80 +}
1 +/*
2 + * @Date: 2023-08-24 09:42:27
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-08-24 12:52:26
5 + * @FilePath: /front/src/api/index.js
6 + * @Description: 文件描述
7 + */
8 +import { fn, fetch } from '@/api/fn';
9 +
10 +const Api = {
11 + ORDER_REST_COUNT: '/srv/?a=order_rest_count',
12 + ORDER_INFO: '/srv/?a=order_info',
13 + ORDER_DETAIL_MY_LAST: '/srv/?a=order_detail_my_last',
14 + ORDER_ADD: '/srv/?a=order_add',
15 + ORDER_CANCEL: '/srv/?a=order_cancel',
16 +};
17 +
18 +/**
19 + * @description: 剩余预约数量列表
20 + * @param {Array} dates 查询日期
21 + * @returns
22 + */
23 +export const orderRestCountAPI = (params) => fn(fetch.get(Api.ORDER_REST_COUNT, params));
24 +
25 +/**
26 + * @description: 查询预约信息
27 + * @param {String} id 预约订单ID
28 + * @returns
29 + */
30 +export const orderInfoAPI = (params) => fn(fetch.get(Api.ORDER_INFO, params));
31 +
32 +/**
33 + * @description: 我的预约信息
34 + * @returns
35 + */
36 +export const orderDetailMyLastAPI = (params) => fn(fetch.get(Api.ORDER_DETAIL_MY_LAST, params));
37 +
38 +/**
39 + * @description: 保存预约信息
40 + * @param {Array} dates 日期列表
41 + * @param {Array} details
42 + * @returns
43 + */
44 +export const orderAddAPI = (params) => fn(fetch.post(Api.ORDER_ADD, params));
45 +
46 +/**
47 + * @description: 取消预约
48 + * @param {String} id 预约订单的ID
49 + * @returns
50 + */
51 +export const orderCancelAPI = (params) => fn(fetch.post(Api.ORDER_CANCEL, params));
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-06-09 13:32:44
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-14 14:47:01
6 + * @FilePath: /tswj/src/api/wx/config.js
7 + * @Description:
8 + */
9 +import { fn, fetch } from '@/api/fn';
10 +
11 +const Api = {
12 + WX_JSAPI: '/srv/?a=wx_share',
13 +}
14 +
15 +/**
16 + * @description 获取微信CONFIG配置文件
17 + * @param {*} url
18 + * @returns {*} cfg
19 + */
20 +export const wxJsAPI = (params) => fn(fetch.get(Api.WX_JSAPI, params));
1 +/*
2 + * @Date: 2022-06-13 14:18:57
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-13 14:27:21
5 + * @FilePath: /tswj/src/api/wx/jsApiList.js
6 + * @Description: 文件描述
7 + */
8 +export const apiList = [
9 + "updateAppMessageShareData",
10 + "updateTimelineShareData",
11 + "onMenuShareTimeline",
12 + "onMenuShareAppMessage",
13 + "onMenuShareQQ",
14 + "onMenuShareWeibo",
15 + "onMenuShareQZone",
16 + "startRecord",
17 + "stopRecord",
18 + "onVoiceRecordEnd",
19 + "playVoice",
20 + "pauseVoice",
21 + "stopVoice",
22 + "onVoicePlayEnd",
23 + "uploadVoice",
24 + "downloadVoice",
25 + "chooseImage",
26 + "previewImage",
27 + "uploadImage",
28 + "downloadImage",
29 + "translateVoice",
30 + "getNetworkType",
31 + "openLocation",
32 + "getLocation",
33 + "hideOptionMenu",
34 + "showOptionMenu",
35 + "hideMenuItems",
36 + "showMenuItems",
37 + "hideAllNonBaseMenuItem",
38 + "showAllNonBaseMenuItem",
39 + "closeWindow",
40 + "scanQRCode",
41 + "chooseWXPay",
42 + "openProductSpecificView",
43 + "addCard",
44 + "chooseCard",
45 + "openCard"
46 +]
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-06-09 13:32:44
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-09 13:42:06
6 + * @FilePath: /tswj/src/api/wx/config.js
7 + * @Description:
8 + */
9 +import { fn, fetch } from '@/api/fn';
10 +
11 +const Api = {
12 + WX_PAY: 'c/bill_paymentForBill.do',
13 +}
14 +
15 +/**
16 + * @description 微信支付接口
17 + * @param {*}
18 + * @returns {*}
19 + */
20 +export const wxPayAPI = (params) => fn(fetch.get(Api.WX_PAY, params));
1 +
2 +.modify-top {
3 + z-index: 36;
4 + position: absolute;
5 + left: 0;
6 + top: 0;
7 + width: 100%;
8 + height: 10px;
9 + background-image: url('http://gyzs.onwall.cn/top-xian%402x.png');
10 + background-size: contain;
11 +}
12 +.content-bg {
13 + /**
14 + * background-color and background-image 共存,不能使用渐变色
15 + * 图片铺平当时精度提高看看效果
16 + * 直接用渐变色
17 + * 不使用渐变色背景
18 + */
19 + height: 100%;
20 + min-height: 100vh;
21 + // background-image: url('@images/bg-yellow-duan@2x.png');
22 + background-image: url('http://gyzs.onwall.cn/bg-yellow-duan%402x.png');
23 + // background-size: cover;
24 + // background: linear-gradient(360deg, #FDD347 0%, #FFED6D 100%) ;
25 +}
1 +@namespace: 'tswj';
2 +
3 +/* ============ 颜色 ============ */
4 +
5 +// 主色调
6 +@base-color: #11D2B1;
7 +// 文字颜色
8 +@base-font-color: #FFFFFF;
9 +
10 +// 定义一个映射
11 +#colors() {
12 + base-color: @base-color;
13 + base-font-color: @base-font-color;
14 +}
15 +
16 +// 混合
17 +.width100 {
18 + width: 100%;
19 +}
1 +// Generated by 'unplugin-auto-import'
2 +export {}
3 +declare global {
4 + const EffectScope: typeof import('vue')['EffectScope']
5 + const computed: typeof import('vue')['computed']
6 + const createApp: typeof import('vue')['createApp']
7 + const customRef: typeof import('vue')['customRef']
8 + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
9 + const defineComponent: typeof import('vue')['defineComponent']
10 + const effectScope: typeof import('vue')['effectScope']
11 + const getCurrentInstance: typeof import('vue')['getCurrentInstance']
12 + const getCurrentScope: typeof import('vue')['getCurrentScope']
13 + const h: typeof import('vue')['h']
14 + const inject: typeof import('vue')['inject']
15 + const isProxy: typeof import('vue')['isProxy']
16 + const isReactive: typeof import('vue')['isReactive']
17 + const isReadonly: typeof import('vue')['isReadonly']
18 + const isRef: typeof import('vue')['isRef']
19 + const markRaw: typeof import('vue')['markRaw']
20 + const nextTick: typeof import('vue')['nextTick']
21 + const onActivated: typeof import('vue')['onActivated']
22 + const onBeforeMount: typeof import('vue')['onBeforeMount']
23 + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
24 + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
25 + const onDeactivated: typeof import('vue')['onDeactivated']
26 + const onErrorCaptured: typeof import('vue')['onErrorCaptured']
27 + const onMounted: typeof import('vue')['onMounted']
28 + const onRenderTracked: typeof import('vue')['onRenderTracked']
29 + const onRenderTriggered: typeof import('vue')['onRenderTriggered']
30 + const onScopeDispose: typeof import('vue')['onScopeDispose']
31 + const onServerPrefetch: typeof import('vue')['onServerPrefetch']
32 + const onUnmounted: typeof import('vue')['onUnmounted']
33 + const onUpdated: typeof import('vue')['onUpdated']
34 + const provide: typeof import('vue')['provide']
35 + const reactive: typeof import('vue')['reactive']
36 + const readonly: typeof import('vue')['readonly']
37 + const ref: typeof import('vue')['ref']
38 + const resolveComponent: typeof import('vue')['resolveComponent']
39 + const shallowReactive: typeof import('vue')['shallowReactive']
40 + const shallowReadonly: typeof import('vue')['shallowReadonly']
41 + const shallowRef: typeof import('vue')['shallowRef']
42 + const toRaw: typeof import('vue')['toRaw']
43 + const toRef: typeof import('vue')['toRef']
44 + const toRefs: typeof import('vue')['toRefs']
45 + const triggerRef: typeof import('vue')['triggerRef']
46 + const unref: typeof import('vue')['unref']
47 + const useAttrs: typeof import('vue')['useAttrs']
48 + const useCssModule: typeof import('vue')['useCssModule']
49 + const useCssVars: typeof import('vue')['useCssVars']
50 + const useRoute: typeof import('vue-router')['useRoute']
51 + const useRouter: typeof import('vue-router')['useRouter']
52 + const useSlots: typeof import('vue')['useSlots']
53 + const watch: typeof import('vue')['watch']
54 + const watchEffect: typeof import('vue')['watchEffect']
55 + const watchPostEffect: typeof import('vue')['watchPostEffect']
56 + const watchSyncEffect: typeof import('vue')['watchSyncEffect']
57 +}
1 +import axios from 'axios';
2 +import { Toast } from 'vant';
3 +
4 +export default {
5 + // 初始化设置
6 + init: {
7 + mounted () {
8 + document.title = this.$route.meta.title;
9 + }
10 + },
11 + likeFn: {
12 + methods: {
13 + /**
14 + * 用户相关操作
15 + * @param {String} type 动作类型:like, favor, play
16 + * @param {String} id 作品 ID
17 + */
18 + handleAction (type, id) { // 用户操作
19 + axios.post('/srv/?a=prod_action', {
20 + action_type: type,
21 + prod_id: id
22 + })
23 + .then(res => {
24 + if (res.data.code === 1) {
25 + if (res.data.msg === `${type}-add-OK`) { // 动作操作成功
26 + this.getProductDetail(type, id);
27 + if (type === 'favor') {
28 + Toast('收藏成功');
29 + }
30 + if (type === 'like') {
31 + Toast('点赞成功');
32 + }
33 + } else { // 取消操作
34 + this.getProductDetail(type, id);
35 + if (type !== 'play') {
36 + Toast('取消成功');
37 + }
38 + }
39 + } else {
40 + // tslint:disable-next-line: no-console
41 + console.warn(res);
42 + if (!res.data.show) return false;
43 + Toast({
44 + icon: 'close',
45 + message: res.data.msg
46 + });
47 + }
48 + })
49 + .catch(err => {
50 + // tslint:disable-next-line: no-console
51 + console.error(err);
52 + });
53 + },
54 + getProductDetail (type, id) { // 查询更新作品详情
55 + axios.get('/srv/?a=prod_info', {
56 + params: {
57 + prod_id: id
58 + }
59 + })
60 + .then(res => {
61 + if (res.data.code === 1) {
62 + this.detail[`is_${type}`] = res.data.data[`is_${type}`];
63 + this.detail[`${type}_num`] = res.data.data[`${type}_num`];
64 + } else {
65 + // tslint:disable-next-line: no-console
66 + console.warn(res);
67 + if (!res.data.show) return false;
68 + Toast({
69 + icon: 'close',
70 + message: res.data.msg
71 + });
72 + }
73 + })
74 + .catch(err => {
75 + // tslint:disable-next-line: no-console
76 + console.error(err);
77 + });
78 + }
79 + }
80 + }
81 +};
1 +/**
2 + * 判断多行省略文本
3 + * @param {*} id 目标dom标签
4 + * @returns
5 + */
6 +const hasEllipsis = (id) => {
7 + let oDiv = document.getElementById(id);
8 + let flag = false
9 + if (oDiv.scrollHeight > oDiv.clientHeight) {
10 + flag = true
11 + }
12 + return flag
13 +}
14 +
15 +export default {
16 + hasEllipsis
17 +}
...\ No newline at end of file ...\ No newline at end of file
1 +import { ref } from 'vue'
2 +import { useBrowserLocation, useEventListener, useTitle, useUrlSearchParams, useWindowScroll, logicAnd } from '@vueuse/core'
3 +export const fn = () => {
4 + // const location = useBrowserLocation()
5 + // console.warn(location.value);
6 +
7 + // useEventListener(window, 'scroll', (evt) => {
8 + // const { x, y } = useWindowScroll()
9 + // // console.warn(x.value);
10 + // console.warn(y.value);
11 + // })
12 +
13 + // useTitle('New Title')
14 +
15 + const a = ref(true)
16 + const b = ref(true)
17 + const flag = a.value && b.value
18 + console.warn(flag);
19 +
20 +}
1 +/*
2 + * @Date: 2022-06-22 00:07:42
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-06-21 15:58:52
5 + * @FilePath: /huizhu/src/composables/useLogin.js
6 + * @Description: 文件描述
7 + */
8 +import { bLoginAPI } from '@/api/B/login'
9 +import { useRouter } from 'vue-router'
10 +import { wxInfo } from '@/utils/tools';
11 +import { ref } from 'vue'
12 +import { useCountDown } from '@vant/use';
13 +import { smsAPI } from '@/api/common'
14 +import { showSuccessToast, showFailToast } from 'vant';
15 +
16 +export const useLogin = () => {
17 + const phone = ref('');
18 + const code = ref('')
19 +
20 + const refForm = ref(null);
21 + const validateForm = () => {
22 + const valid = refForm.value.validate();
23 + valid
24 + .then(() => {
25 + refForm.value.submit();
26 + })
27 + .catch(error => {
28 + console.error(error);
29 + showFailToast('请检查后再次提交');
30 + })
31 + }
32 +
33 + /**
34 + * 判断微信环境看是否弹出控件框
35 + * 桌面微信直接输入
36 + * 其他环境弹出输入框
37 + */
38 + let use_widget = ref(true);
39 + use_widget.value = !!(wxInfo().isiOS || wxInfo().isAndroid);
40 +
41 + /**
42 + * 手机号码校验
43 + * 函数返回 true 表示校验通过,false 表示不通过
44 + * @param {*} val
45 + */
46 + const sms_disabled = ref(false);
47 + const phoneValidator = (val) => {
48 + let flag = false;
49 + // 简单判断手机号位数
50 + if (/1\d{10}/.test(val) && phone.value.length === 11) {
51 + sms_disabled.value = false;
52 + flag = true;
53 + } else {
54 + sms_disabled.value = true;
55 + flag = false;
56 + }
57 + return flag
58 + };
59 +
60 + /**
61 + * 手机号数字弹框
62 + */
63 + const keyboard_show = ref(false);
64 + const refPhone = ref(null)
65 + const showKeyboard = () => { // 弹出数字弹框
66 + keyboard_show.value = true;
67 + };
68 + const keyboardBlur = () => { // 数字键盘失焦回调
69 + keyboard_show.value = false;
70 + refPhone.value.validate();
71 + };
72 +
73 + // 设置发送短信倒计时
74 + // TAG: vant 自带倒计时函数
75 + const limitSeconds = ref(60000); // 配置倒计时秒数
76 + const countDown = useCountDown({ // 配置倒计时
77 + time: limitSeconds.value,
78 + onFinish: () => {
79 + countDown.reset();
80 + }
81 + });
82 +
83 + const sendCode = async () => { // 发送验证码
84 + countDown.start();
85 + // 验证码接口
86 + const { code } = await smsAPI({ phone: phone.value });
87 + if (code) {
88 + showSuccessToast('发送成功');
89 + }
90 + };
91 +
92 + // 过滤输入的数字 只能四位
93 + const smsFormatter = (value) => value.substring(0, 4);
94 +
95 + /**
96 + * 用户登录
97 + * @param {*} phone
98 + * @param {*} pin
99 + */
100 + const $router = useRouter();
101 + const onSubmit = async (values) => {
102 + const { code } = await bLoginAPI({ phone: values.phone, pin: values.code })
103 + if (code) {
104 + $router.push({
105 + path: '/business/index'
106 + });
107 + }
108 + };
109 +
110 + return {
111 + phone,
112 + code,
113 + onSubmit,
114 + use_widget,
115 + sms_disabled,
116 + phoneValidator,
117 + keyboardBlur,
118 + keyboard_show,
119 + showKeyboard,
120 + refPhone,
121 + refForm,
122 + validateForm,
123 + smsFormatter,
124 + limitSeconds,
125 + countDown,
126 + sendCode,
127 + }
128 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-25 18:34:17
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2023-06-14 09:55:42
6 + * @FilePath: /huizhu/src/constant.js
7 + * @Description:
8 + */
9 +
10 +// 颜色变量
11 +export const styleColor = {
12 + baseColor: '#11D2B1',
13 + baseFontColor: '#FFFFFF'
14 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-14 23:28:39
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-07 22:49:56
6 + * @FilePath: /tswj/src/env.d.ts
7 + * @Description:
8 + */
9 +interface ImportMetaEnv extends Readonly<Record<string, string>> {
10 + readonly VITE_OPENID: string;
11 + readonly VITE_ID: string;
12 + readonly VITE_PIN: string;
13 + readonly VITE_APPID: string;
14 +}
15 +
16 +interface ImportMeta {
17 + readonly env: ImportMetaEnv
18 +}
1 +/**
2 + * 依赖注入命名集合
3 + */
4 +export const myInjectionKey = Symbol()
5 +export const fooInjectionKey = Symbol()
1 +import { provide, inject } from "vue";
2 +
3 +// const key = Symbol();
4 +
5 +/**
6 + * 创建全局变量
7 + * @param {*} context
8 + * @param {*} key
9 + */
10 +export function createContext(context, key) {
11 + provide(key, context)
12 +}
13 +/**
14 + * 使用全局变量
15 + * @param {*} key
16 + * @returns
17 + */
18 +export function useContext(key) {
19 + return inject(key)
20 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-28 22:31:25
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-05-30 10:18:09
6 + * @FilePath: /tswj/src/hooks/useDebounce.js
7 + * @Description:
8 + */
9 +import _ from 'lodash';
10 +/**
11 + * 封装lodash防抖
12 + * @param {*} fn 执行函数
13 + * @param {*} timestamp 执行间隔
14 + * @param {*} options 函数配置 - 在延迟开始前调用,在延迟结束后不调用
15 + * @returns 返回新的 debounced(防抖动)函数。
16 + */
17 +export const useDebounce = (fn, timestamp = 500, options = { leading: true, trailing: false }) => {
18 + return _.debounce(fn, timestamp, options);
19 +}
1 +
2 +/**
3 + * @description 封装简化滚动查询列表执行流程
4 + * @param {*} data 接口返回列表数据
5 + * @param {*} list 自定义列表
6 + * @param {*} offset
7 + * @param {*} loading
8 + * @param {*} finished
9 + * @param {*} finishedTextStatus
10 + * @param {*} emptyStatus
11 + */
12 +import _ from 'lodash'
13 +
14 +export const flowFn = (data, list, offset, loading, finished, finishedTextStatus, emptyStatus) => {
15 + list.value = _.concat(list.value, data);
16 + list.value = _.uniqBy(list.value, 'id');
17 + offset.value = list.value.length;
18 + loading.value = false;
19 + // 数据全部加载完成
20 + if (!data.length) {
21 + // 加载状态结束
22 + finished.value = true;
23 + }
24 + // 空数据提示
25 + if (!list.value.length) {
26 + finishedTextStatus.value = false;
27 + }
28 + emptyStatus.value = Object.is(list.value.length, 0);
29 +}
1 +import { useRouter } from 'vue-router';
2 +
3 +/**
4 + * 封装路由跳转方便行内调用
5 + * @returns
6 + */
7 +export function useGo () {
8 + let router = useRouter()
9 + function go (path, query) {
10 + router.push({
11 + path: path,
12 + query: query
13 + })
14 + }
15 + return go
16 +}
17 +
18 +export function useReplace () {
19 + let router = useRouter()
20 + function replace (path, query) {
21 + router.replace({
22 + path: path,
23 + query: query
24 + })
25 + }
26 + return replace
27 +}
1 +import { mainStore } from '@/utils/generatePackage.js'
2 +
3 +// 删除 keep-alive 缓存
4 +export const store = mainStore();
5 +
6 +export const killPages = () => {
7 + store.changeKeepPages();
8 +}
9 +
10 +export const addPages = () => {
11 + store.keepThisPage();
12 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-31 12:06:19
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2023-08-22 10:42:53
6 + * @FilePath: /front/src/main.js
7 + * @Description:
8 + */
9 +import { createApp } from 'vue';
10 +import {
11 + Button,
12 + Image as VanImage,
13 + Col,
14 + Row,
15 + Icon,
16 + Form,
17 + Field,
18 + CellGroup,
19 + ConfigProvider,
20 + Toast,
21 + Uploader,
22 + Empty,
23 + Tab,
24 + Tabs,
25 + Overlay,
26 + NumberKeyboard,
27 + Lazyload,
28 + List,
29 + PullRefresh,
30 + Popup,
31 + Picker,
32 + Sticky,
33 + Stepper,
34 + Tag,
35 + Swipe,
36 + SwipeItem,
37 + Dialog,
38 + ActionSheet,
39 + Loading,
40 + Checkbox,
41 + CheckboxGroup,
42 + Search,
43 + Signature,
44 + Calendar,
45 +} from 'vant';
46 +import router from './router';
47 +import App from './App.vue';
48 +// import axios from './utils/axios';
49 +import axios from '@/utils/axios';
50 +// import 'default-passive-events'; // 解决Chrome控制台non-passive event listener输出问题
51 +import { createPinia } from 'pinia';
52 +import 'vant/lib/index.css';
53 +import vueEsign from 'vue-esign';
54 +
55 +const pinia = createPinia();
56 +const app = createApp(App);
57 +
58 +app.config.globalProperties.$http = axios; // 关键语句
59 +
60 +app
61 + .use(pinia)
62 + .use(router)
63 + .use(Button)
64 + .use(VanImage)
65 + .use(Col)
66 + .use(Row)
67 + .use(Icon)
68 + .use(Form)
69 + .use(Field)
70 + .use(CellGroup)
71 + .use(Toast)
72 + .use(Uploader)
73 + .use(Empty)
74 + .use(Tab)
75 + .use(Tabs)
76 + .use(Overlay)
77 + .use(NumberKeyboard)
78 + .use(Lazyload)
79 + .use(List)
80 + .use(PullRefresh)
81 + .use(Popup)
82 + .use(Picker)
83 + .use(Sticky)
84 + .use(Stepper)
85 + .use(Tag)
86 + .use(Swipe)
87 + .use(SwipeItem)
88 + .use(Dialog)
89 + .use(ActionSheet)
90 + .use(Loading)
91 + .use(Checkbox)
92 + .use(CheckboxGroup)
93 + .use(Search)
94 + .use(ConfigProvider)
95 + .use(Signature)
96 + .use(Calendar);
97 +
98 +app.use(vueEsign);
99 +
100 +app.mount('#app');
1 +const routes = [{
2 + path: '/image',
3 + redirect: '',
4 + name: 'html转图片',
5 + component: 'html2canvas',
6 + keepAlive: '',
7 + meta: {
8 + title: 'html转图片',
9 + name: ''
10 + },
11 + children: [{
12 + path: 'children',
13 + redirect: '',
14 + name: 'html转图片',
15 + component: 'children-test',
16 + keepAlive: '',
17 + meta: {
18 + title: 'html转图片',
19 + name: ''
20 + }
21 + }]
22 +}]
23 +// const routes = []
24 +
25 +export default routes
1 +/*
2 + * @Date: 2023-06-13 13:26:46
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-08-23 14:47:37
5 + * @FilePath: /front/src/route.js
6 + * @Description: 文件描述
7 + */
8 +export default [
9 + {
10 + path: '/',
11 + component: () => import('@/views/index.vue'),
12 + meta: {
13 + title: '别院预约',
14 + },
15 + },
16 + {
17 + path: '/auth',
18 + component: () => import('@/views/auth.vue'),
19 + meta: {
20 + title: '授权页面',
21 + },
22 + },
23 +];
1 +/*
2 + * @Date: 2022-05-26 13:57:28
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-29 21:36:59
5 + * @FilePath: /tswj/src/router.js
6 + * @Description: 文件描述
7 + */
8 +import { createRouter, createWebHashHistory } from 'vue-router';
9 +import RootRoute from './route.js';
10 +import asyncRoutesArr from "./mock/routes"
11 +import generateRoutes from './utils/generateRoute'
12 +
13 +// TAG: 路由配置表
14 +/**
15 + * 把项目独有的路由配置到相应的路径,默认路由文件只放公用部分
16 + * 但是 vue 文件内容还是要事先准备好
17 + */
18 +const modules = import.meta.globEager('@/router/routes/modules/**/*.js'); // Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块
19 +const routeModuleList = [];
20 +
21 +Object.keys(modules).forEach((key) => {
22 + const mod = modules[key].default || {};
23 + const modList = Array.isArray(mod) ? [...mod] : [mod];
24 + routeModuleList.push(...modList);
25 +});
26 +
27 +// 创建路由实例并传递 `routes` 配置
28 +const router = createRouter({
29 + history: createWebHashHistory('/index.html'),
30 + routes: [...RootRoute, ...routeModuleList]
31 +});
32 +
33 +// TAG: 动态生成路由
34 +/**
35 + * generateRoute 负责把后台返回数据拼接成项目需要的路由结构,动态添加到路由表里面
36 + */
37 +router.beforeEach((to, from, next) => {
38 + // 使用404为中转页面,避免动态路由没有渲染出来,控制台报警告问题
39 + if (to.path == '/404' && to.redirectedFrom != undefined) {
40 + // 模拟异步操作
41 + setTimeout(() => {
42 + if (!asyncRoutesArr.length) return; // 没有动态路由避免报错
43 + const arr = generateRoutes(asyncRoutesArr); // 在路由守卫处生成,避免有子路由时刷新白屏问题。
44 + arr.forEach(item => {
45 + router.addRoute(item) // 新增路由
46 + })
47 + // 重写被404覆盖路由信息
48 + next({ ...to.redirectedFrom, replace: true });
49 + }, 1000);
50 + } else {
51 + next()
52 + }
53 +})
54 +
55 +router.afterEach(() => {
56 + // console.warn(to);
57 + // console.warn(wx);
58 + // share(to)
59 +})
60 +
61 +export default router;
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-06-07 22:46:46
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-08 05:34:56
6 + * @FilePath: /tswj/src/shims-vue.d.ts
7 + * @Description:
8 + */
9 +declare module '*.vue' {
10 + import type { DefineComponent } from 'vue';
11 + const component: DefineComponent;
12 + export default component;
13 +}
1 +/*
2 + * @Date: 2022-04-18 15:59:42
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-08-22 17:36:03
5 + * @FilePath: /front/src/store/index.js
6 + * @Description: 文件描述
7 + */
8 +import { defineStore } from 'pinia';
9 +// import { testStore } from './test'; // 另一个store
10 +import _ from 'lodash';
11 +import { useRouter } from 'vue-router'
12 +
13 +export const mainStore = defineStore('main', {
14 + state: () => {
15 + return {
16 + msg: 'Hello world',
17 + count: 0,
18 + auth: false,
19 + keepPages: ['default'], // 很坑爹,空值全部都缓存
20 + appUserInfo: [], // 缓存预约人信息
21 + };
22 + },
23 + getters: {
24 + getKeepPages () {
25 + return this.keepPages
26 + },
27 + // getTestStoreList () {
28 + // return testStore().list // 返回另一个store的值
29 + // }
30 + },
31 + actions: {
32 + changeState (state) {
33 + this.auth = state;
34 + },
35 + changeKeepPages () { // 清空所有缓存,用一个不存在的值覆盖
36 + this.keepPages = ['default'];
37 + },
38 + keepThisPage () { // 新增缓存页
39 + const $router = useRouter();
40 + const page = $router.currentRoute.value.meta.name;
41 + this.keepPages.push(page);
42 + },
43 + removeThisPage () { // 删除缓存页
44 + const $router = useRouter();
45 + const page = $router.currentRoute.value.meta.name;
46 + _.remove(this.keepPages, item => item === page)
47 + },
48 + changeUserInfo (info) {
49 + this.appUserInfo = info;
50 + }
51 + },
52 +});
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-25 18:34:17
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-22 01:35:44
6 + * @FilePath: /tswj/src/theme-vars.js
7 + * @Description: 修改vant默认表单样式
8 + */
9 +import { styleColor } from '@/constant.js';
10 +
11 +export const loginTheme = {
12 + buttonPrimaryBackground: styleColor.baseColor,
13 + buttonPrimaryBorderColor: styleColor.baseColor,
14 + buttonPrimaryColor: styleColor.baseFontColor,
15 + CellVerticalPadding: '14px'
16 +};
1 +/*
2 + * @Date: 2022-06-20 01:22:50
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-20 01:23:18
5 + * @FilePath: /tswj/src/composables/useMonitorKeyboard.js
6 + * @Description: 文件描述
7 + */
8 +/**
9 + * @class 监听虚拟键盘
10 + * @classdesc 监听虚拟键盘弹出隐藏
11 + * @public onEnd 结束监听虚拟键盘
12 + * @public onShow 传递一个回调 监听虚拟键盘弹出
13 + * @public onHidden 传递一个回调 监听虚拟键盘隐藏
14 + */
15 +class MonitorKeyboard {
16 + constructor() {
17 + this.type = this.IsIA();
18 + this.originalHeight = window.innerHeight;
19 + }
20 +
21 + /**
22 + * @function IsIA 获取设备类型
23 + * @param 1 Android 2 iOS
24 + */
25 + IsIA = () => {
26 + const userAgent = typeof window === 'object' ? window.navigator.userAgent : '';
27 + if (/android/i.test(userAgent)) {
28 + return 1;
29 + } else if (/iPhone|iPod|iPad/i.test(userAgent)) {
30 + return 2;
31 + }
32 + }
33 +
34 + // Android系统
35 + onResize = () => {
36 + //键盘弹起与隐藏都会引起窗口的高度发生变化
37 + const resizeHeight = window.innerHeight;
38 +
39 + if (this.originalHeight - resizeHeight > 50) {
40 + this.show('Android系统: 软键盘弹出');
41 + } else {
42 + this.hidden('Android系统: 软键盘收起');
43 + }
44 + }
45 +
46 + // iOS获取焦点
47 + onFocusin = () => {
48 + this.show('iOS系统:软键盘弹出');
49 + }
50 +
51 + // iOS失去焦点
52 + onFocusout = () => {
53 + this.hidden('iOS系统:软键盘收起');
54 + }
55 +
56 + /**
57 + * @function onStart 开始监听虚拟键盘
58 + */
59 + onStart = () => {
60 + if (this.type == 1) {
61 + // 获取窗口的高度
62 + window.addEventListener('resize', this.onResize);
63 + }
64 + if (this.type == 2) {
65 + // iOS系统
66 + window.addEventListener('focusin', this.onFocusin);
67 + window.addEventListener('focusout', this.onFocusout);
68 + }
69 + }
70 +
71 + /**
72 + * @function onEnd 结束监听虚拟键盘
73 + */
74 + onEnd = () => {
75 + if (this.type == 1) {
76 + //获取窗口的高度
77 + window.removeEventListener('resize', this.onResize);
78 + }
79 + if (this.type == 2) {
80 + window.removeEventListener('focusin', this.onFocusin);
81 + window.removeEventListener('focusout', this.onFocusout);
82 + }
83 + }
84 +
85 + /**
86 + * @function onShow 传递一个回调函数
87 + * @param 虚拟键盘弹出时触发
88 + */
89 + onShow = (fn) => {
90 + this.show = fn;
91 + }
92 +
93 + /**
94 + * @function onHidden 传递一个回调函数
95 + * @param 虚拟键盘隐藏时触发
96 + */
97 + onHidden = (fn) => {
98 + this.hidden = fn;
99 + }
100 +}
101 +
102 +export default MonitorKeyboard
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-28 10:17:40
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2023-08-24 10:56:20
6 + * @FilePath: /front/src/utils/axios.js
7 + * @Description:
8 + */
9 +import axios from 'axios';
10 +import router from '@/router';
11 +import qs from 'Qs'
12 +import { strExist } from '@/utils/tools'
13 +// import { parseQueryString } from '@/utils/tools'
14 +
15 +axios.defaults.params = {
16 + f: 'xysBooking',
17 +};
18 +
19 +/**
20 + * @description 请求拦截器
21 + */
22 +axios.interceptors.request.use(
23 + config => {
24 + // const url_params = parseQueryString(location.href);
25 + // GET请求默认打上时间戳,避免从缓存中拿数据。
26 + const timestamp = config.method === 'get' ? (new Date()).valueOf() : '';
27 + /**
28 + * POST PHP需要修改数据格式
29 + * 序列化POST请求时需要屏蔽上传相关接口,上传相关接口序列化后报错
30 + */
31 + // config.data = config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url) ? qs.stringify(config.data) : config.data;
32 + // 绑定默认请求头
33 + config.params = { ...config.params, timestamp }
34 + return config;
35 + },
36 + error => {
37 + // 请求错误处理
38 + return Promise.reject(error);
39 + });
40 +
41 +/**
42 + * @description 响应拦截器
43 + */
44 +axios.interceptors.response.use(
45 + response => {
46 + // // 默认显示错误提示
47 + // response.data.show = true;
48 + // // 判断微信授权状态,进入页面时未授权需要授权跳转
49 + // // C/B 授权拼接头特殊标识,openid_x
50 + // let prefixAPI = router?.currentRoute.value.href?.indexOf('business') > 0 ? 'b' : 'c';
51 + if (response.data.code === 401) {
52 + // 特殊标识-带此标识报错不显示
53 + response.data.show = false;
54 + /**
55 + * 未授权跳转登录页
56 + * 带着上一个页面的信息, 授权完成后 返回当前页面
57 + */
58 + router.replace({ path: '/auth', query: { href: location.hash } });
59 + }
60 + if (['预约ID不存在'].includes(response.data.msg)) {
61 + response.data.show = false;
62 + }
63 + // // 拦截B端未登录情况
64 + // if (['老师请先登录!', '老师不存在!'].includes(response.data.msg)) { router.replace({ path: '/business/login' }); }
65 + return response;
66 + },
67 + error => {
68 + return Promise.reject(error);
69 + });
70 +
71 +export default axios;
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-17 11:34:35
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-20 16:31:28
6 + * @FilePath: /tswj/src/utils/generateIcons.js
7 + * @Description: 图标集合
8 + */
9 +import icon_video from '@images/video.png'
10 +import icon_up from '@images/icon-guanbi@2x.png'
11 +import icon_down from '@images/icon-zhankai@2x.png'
12 +import icon_subscribed from '@images/icon-dingyue01@2x.png'
13 +import icon_unsubscribe from '@images/icon-dingyue02@2x.png'
14 +import no_image from '@images/que-shuju@2x.png'
15 +import icon_avatar from '@images/que-touxiang@2x.png'
16 +import icon_logo from '@images/que-logo@2x.png'
17 +import icon_dianzan1 from '@images/icon-dianzan01@2x.png'
18 +import icon_dianzan2 from '@images/icon-dianzan02@2x.png'
19 +import icon_shoucang1 from '@images/icon-shoucang01@2x.png'
20 +import icon_shoucang2 from '@images/icon-shoucang02@2x.png'
21 +import icon_liuyan from '@images/icon-liuyan@2x.png'
22 +import icon_book from '@images/shu@2x.png'
23 +import icon_me from '@images/icon-my@2x.png'
24 +import icon_home from '@images/icon-home@2x.png'
25 +import icon_rank from '@images/icon-paihang@2x.png'
26 +import icon_ranking1 from '@images/1@2x.png'
27 +import icon_ranking2 from '@images/2@2x.png'
28 +import icon_ranking3 from '@images/3@2x.png'
29 +import icon_flower from '@images/xiaohua@2x.png'
30 +import icon_refuse from '@images/icon-jujue@2x.png'
31 +import icon_apply from '@images/icon-shenhe@2x.png'
32 +import icon_enable from '@images/icon-tongguo@2x.png'
33 +
34 +export {
35 + icon_video,
36 + icon_up,
37 + icon_down,
38 + icon_subscribed,
39 + icon_unsubscribe,
40 + no_image,
41 + icon_avatar,
42 + icon_logo,
43 + icon_dianzan1,
44 + icon_dianzan2,
45 + icon_liuyan,
46 + icon_shoucang1,
47 + icon_shoucang2,
48 + icon_book,
49 + icon_me,
50 + icon_home,
51 + icon_rank,
52 + icon_ranking1,
53 + icon_ranking2,
54 + icon_ranking3,
55 + icon_flower,
56 + icon_refuse,
57 + icon_apply,
58 + icon_enable,
59 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-17 11:17:58
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-07-01 14:55:12
6 + * @FilePath: /tswj/src/utils/generateModules.js
7 + * @Description:
8 + */
9 +import MyButton from '@/components/MyButton/index.vue'
10 +import VideoCard from '@/components/VideoCard/index.vue'
11 +import NoticeOverlay from '@/components/NoticeOverlay/index.vue'
12 +import NoticeOverlayModule from '@/components/NoticeOverlayModule/index.vue'
13 +import DonateBook from '@/components/DonateBook/index.vue'
14 +import ShortcutFixed from '@/components/ShortcutFixed/index.vue'
15 +import BookCard from '@/components/BookCard/index.vue'
16 +import VideoDetail from '@/components/VideoDetail/index.vue'
17 +import DonateBar from '@/components/DonateBar/index.vue'
18 +import DonateFlower from '@/components/DonateFlower/index.vue'
19 +
20 +export {
21 + MyButton,
22 + VideoCard,
23 + NoticeOverlay,
24 + NoticeOverlayModule,
25 + DonateBook,
26 + ShortcutFixed,
27 + BookCard,
28 + VideoDetail,
29 + DonateBar,
30 + DonateFlower,
31 +}
1 +/*
2 + * @Date: 2022-05-17 11:26:03
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-20 14:00:13
5 + * @FilePath: /tswj/src/utils/generatePackage.js
6 + * @Description: 文件描述
7 + */
8 +import Cookies from 'js-cookie'
9 +import $ from 'jquery'
10 +import _ from 'lodash'
11 +import axios from '@/utils/axios';
12 +import { storeToRefs } from 'pinia'
13 +import { mainStore } from '@/store'
14 +import { Toast, Dialog } from 'vant';
15 +import { wxInfo, hasEllipsis } from '@/utils/tools';
16 +import { useTitle } from '@vueuse/core'
17 +
18 +export {
19 + Cookies,
20 + $,
21 + _,
22 + axios,
23 + storeToRefs,
24 + mainStore,
25 + Toast,
26 + Dialog,
27 + wxInfo,
28 + hasEllipsis,
29 + useTitle
30 +}
1 +/*
2 + * @Date: 2022-05-16 17:21:45
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-29 17:00:15
5 + * @FilePath: /tswj/src/utils/generateRoute.js
6 + * @Description: 文件描述
7 + */
8 +
9 +/**
10 + * 根据后台返回的路径,生成页面的组件模版
11 + * @param {*} component
12 + * @returns 模版地址
13 + */
14 +function loadView(component) {
15 + return () => import(`../views/${component}.vue`)
16 +}
17 +
18 +/**
19 + * 生成路由结构
20 + * @param {*} routes
21 + */
22 +const generateRoutes = (routes) => {
23 + const arr = []
24 + routes.forEach(route => {
25 + const router = {}
26 + const {
27 + path,
28 + redirect,
29 + name,
30 + component,
31 + keepAlive,
32 + meta,
33 + children
34 + } = route
35 +
36 + router.path = path
37 + redirect && (router.redirect = redirect)
38 + name && (router.name = name)
39 + router.component = loadView(component)
40 + keepAlive && (router.keepAlive = keepAlive)
41 + meta && (router.meta = meta)
42 + router.children = !Array.isArray(children) || generateRoutes(children);
43 + arr.push(router)
44 + })
45 + return arr
46 +}
47 +
48 +export default generateRoutes;
1 +import sha1 from "js-sha1";
2 +
3 +function getEtag(buffer, callback) {
4 + // sha1算法
5 + var shA1 = sha1.digest;
6 +
7 + // 以4M为单位分割
8 + var blockSize = 4 * 1024 * 1024;
9 + var sha1String = [];
10 + var prefix = 0x16;
11 + var blockCount = 0;
12 +
13 + var bufferSize = buffer.size || buffer.length || buffer.byteLength;
14 + blockCount = Math.ceil(bufferSize / blockSize);
15 +
16 + for (var i = 0; i < blockCount; i++) {
17 + sha1String.push(shA1(buffer.slice(i * blockSize, (i + 1) * blockSize)));
18 + }
19 + function concatArr2Uint8(s) {//Array 2 Uint8Array
20 + var tmp = [];
21 + for (var i of s) tmp = tmp.concat(i);
22 + return new Uint8Array(tmp);
23 + }
24 + function Uint8ToBase64(u8Arr, urisafe) {//Uint8Array 2 Base64
25 + var CHUNK_SIZE = 0x8000; //arbitrary number
26 + var index = 0;
27 + var length = u8Arr.length;
28 + var result = '';
29 + var slice;
30 + while (index < length) {
31 + slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length));
32 + result += String.fromCharCode.apply(null, slice);
33 + index += CHUNK_SIZE;
34 + }
35 + return urisafe ? btoa(result).replace(/\//g, '_').replace(/\+/g, '-') : btoa(result);
36 + }
37 + function calcEtag() {
38 + if (!sha1String.length) return 'Fto5o-5ea0sNMlW_75VgGJCv2AcJ';
39 + var sha1Buffer = concatArr2Uint8(sha1String);
40 + // 如果大于4M,则对各个块的sha1结果再次sha1
41 + if (blockCount > 1) {
42 + prefix = 0x96;
43 + sha1Buffer = shA1(sha1Buffer.buffer);
44 + } else {
45 + sha1Buffer = Array.apply([], sha1Buffer);
46 + }
47 + sha1Buffer = concatArr2Uint8([[prefix], sha1Buffer]);
48 + return Uint8ToBase64(sha1Buffer, true);
49 + }
50 + return (calcEtag());
51 +}
52 +
53 +export { getEtag }
1 +import wx from 'weixin-js-sdk'
2 +import axios from '@/utils/axios';
3 +
4 +const fn = (to) => {
5 + // 路由名
6 + let ruleName = location.href.split('#/')[1].split('?')[0];
7 +
8 + const icon = 'https://cdn.lifeat.cn/webappgroup/betterLifelogo.png'
9 +
10 + const shareInfoMap = {
11 + 'client/index': {
12 + title: '童声无界',
13 + desc: '引导页',
14 + icon
15 + },
16 + 'client/chooseSchool': {
17 + title: '选择幼儿园',
18 + desc: '引导页',
19 + icon
20 + },
21 + default: {
22 + title: to.name,
23 + desc: window.location.href,
24 + icon
25 + },
26 + }
27 + let infoMap = shareInfoMap[ruleName] ? shareInfoMap[ruleName] : shareInfoMap['default'];
28 + // console.warn(ruleName);
29 + console.warn(infoMap);
30 + console.warn(wx);
31 + console.warn(axios);
32 +}
33 +export default fn
34 +// 这个判断后加的为了减少请求次数,据后端说有次数限制,当需要分享的页面才去请求接口。
35 +// if (shareInfoMap[ruleName]) {
36 +// // request 是封装的请求
37 +// request.post('/wxmp/sign/jsSdk', {
38 +// url: location.href,
39 +// }).then(res => {
40 +// let { timestamp, nonceStr, signature, appId } = res;
41 +// wx.config({
42 +// debug: false,
43 +// appId,
44 +// timestamp,
45 +// nonceStr,
46 +// signature,
47 +// jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData']
48 +// });
49 +// wx.error(function (errres) {
50 +// console.info(errres)
51 +// })
52 +// wx.ready(() => { //需在用户可能点击分享按钮前就先调用
53 +// console.info('ready')
54 +// //分享朋友
55 +// wx.updateAppMessageShareData({
56 +// title: infoMap.title, // 分享标题
57 +// desc: infoMap.desc, // 分享描述
58 +// link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
59 +// imgUrl: infoMap.icon, // 分享图标
60 +// success: function () {
61 +// console.info("成功")
62 +// // 设置成功
63 +// },
64 +// fail: function (erres) {
65 +// console.info('失败:', erres)
66 +// }
67 +// })
68 +// //分享到 朋友圈
69 +// wx.updateTimelineShareData({
70 +// title: infoMap.title, // 分享标题
71 +// link: location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
72 +// imgUrl: infoMap.icon, // 分享图标
73 +// success: function () {
74 +// console.info("成功")
75 +// // 设置成功
76 +// },
77 +// fail: function (erres) {
78 +// console.info('失败:', erres)
79 +// }
80 +// })
81 +// });
82 +// }).catch(err => {
83 +// console.info('err:', err)
84 +// })
85 +// }
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * @Date: 2022-04-18 15:59:42
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-30 13:54:32
5 + * @FilePath: /tswj/src/utils/tools.js
6 + * @Description: 文件描述
7 + */
8 +import dayjs from 'dayjs';
9 +
10 +// 格式化时间
11 +const formatDate = (date) => {
12 + return dayjs(date).format('YYYY-MM-DD HH:mm');
13 +};
14 +
15 +/**
16 + * @description 判断浏览器属于平台
17 + * @returns
18 + */
19 +const wxInfo = () => {
20 + let u = navigator.userAgent;
21 + let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器
22 + let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
23 + let uAgent = navigator.userAgent.toLowerCase();
24 + let isTable = (uAgent.match(/MicroMessenger/i) == 'micromessenger') ? true : false;
25 + return {
26 + isAndroid,
27 + isiOS,
28 + isTable
29 + };
30 +};
31 +
32 +/**
33 + * @description 判断多行省略文本
34 + * @param {*} id 目标dom标签
35 + * @returns
36 + */
37 +const hasEllipsis = (id) => {
38 + let oDiv = document.getElementById(id);
39 + let flag = false;
40 + if (oDiv.scrollHeight > oDiv.clientHeight) {
41 + flag = true
42 + }
43 + return flag
44 +}
45 +
46 +/**
47 + * @description 解析URL参数
48 + * @param {*} url
49 + * @returns
50 + */
51 +const parseQueryString = url => {
52 + var json = {};
53 + var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : [];
54 + arr.forEach(item => {
55 + var tmp = item.split('=');
56 + json[tmp[0]] = tmp[1];
57 + });
58 + return json;
59 +}
60 +
61 +/**
62 + * 字符串包含字符数组中字符的状态
63 + * @param {*} array 字符数组
64 + * @param {*} str 字符串
65 + * @returns 包含状态
66 + */
67 +const strExist = (array, str) => {
68 + const exist = array.filter(arr => {
69 + if (str.indexOf(arr) >= 0) return str;
70 + })
71 + return exist.length > 0
72 +}
73 +
74 +export { formatDate, wxInfo, hasEllipsis, parseQueryString, strExist };
1 +import VConsole from 'vconsole';
2 +
3 +// const vConsole = new VConsole();
4 +let vConsole = '';
5 +// 或者使用配置参数来初始化,详情见文档
6 +if (+import.meta.env.VITE_CONSOLE) {
7 + vConsole = new VConsole({ theme: 'dark' });
8 +}
9 +
10 +export default vConsole
1 +<!--
2 + * @Date: 2022-08-29 13:55:31
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-08-24 10:52:35
5 + * @FilePath: /front/src/views/auth.vue
6 + * @Description: 授权模块
7 +-->
8 +<template>
9 + <div />
10 +</template>
11 +
12 +<script setup>
13 +import { onMounted } from 'vue'
14 +import { useRoute } from 'vue-router'
15 +
16 +const $route = useRoute();
17 +
18 +onMounted(() => {
19 + // php需要先跳转链接获取openid
20 + /**
21 + * encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。
22 + * 该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
23 + * 其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
24 + */
25 + let raw_url = encodeURIComponent(location.origin + location.pathname + $route.query.href); // 未授权的地址
26 + // TAG: 开发环境测试数据
27 + const short_url = `/srv/?a=openid&res=${raw_url}`;
28 + location.href = import.meta.env.DEV
29 + ? `${short_url}&test_openid=${import.meta.env.VITE_OPENID}`
30 + : `${short_url}`;
31 +})
32 +</script>
1 +<!--
2 + * @Date: 2023-06-21 10:23:09
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-01-15 10:07:06
5 + * @FilePath: /xysBooking/src/views/index.vue
6 + * @Description: 预约页首页
7 +-->
8 +<template>
9 + <div class="index-page">
10 + </div>
11 +</template>
12 +
13 +<script setup>
14 +import { ref } from 'vue'
15 +import { useRoute, useRouter } from 'vue-router'
16 +import dayjs from 'dayjs'
17 +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js'
18 +//import { } from '@/utils/generateModules.js'
19 +//import { } from '@/utils/generateIcons.js'
20 +//import { } from '@/composables'
21 +import { showSuccessToast, showFailToast } from 'vant';
22 +import { orderRestCountAPI } from '@/api/index'
23 +const $route = useRoute();
24 +const $router = useRouter();
25 +useTitle($route.meta.title);
26 +
27 +onMounted(async () => {
28 +});
29 +
30 +</script>
31 +
32 +<style lang="less" scoped>
33 +.index-page {
34 + padding: 1rem 1rem 0;
35 +}
36 +</style>
1 +{
2 + "compilerOptions": {
3 + /* 基本选项 */
4 + "target": "esnext", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
5 + "module": "CommonJS", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
6 + "lib": [ // 指定要包含在编译中的库文件
7 + "esnext",
8 + "dom",
9 + "dom.iterable",
10 + "scripthost"
11 + ],
12 + "allowJs": true, // 允许编译 javascript 文件
13 + // "checkJs": true, // 报告 javascript 文件中的错误
14 + "jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
15 + // "declaration": true, // 生成相应的 '.d.ts' 文件
16 + // "sourceMap": true, // 生成相应的 '.map' 文件
17 + // "outFile": "./", // 将输出文件合并为一个文件
18 + "outDir": "./", // 指定输出目录
19 + // "rootDir": "./", // 用来控制输出目录结构 --outDir.
20 + "removeComments": true, // 删除编译后的所有的注释
21 + // "noEmit": true, // 不生成输出文件
22 + "importHelpers": true, // tslib 导入辅助工具函数
23 + "isolatedModules": false, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似)
24 +
25 + /* 严格的类型检查选项 */
26 + "strict": true, // 启用所有严格类型检查选项
27 + // "noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
28 + // "strictNullChecks": true, // 启用严格的 null 检查
29 + // "noImplicitThis": true, // this 表达式值为 any 类型的时候,生成一个错误
30 + // "alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
31 +
32 + /* 额外的检查 */
33 + "noUnusedLocals": true, // 有未使用的变量时,抛出错误
34 + "noUnusedParameters": true, // 有未使用的参数时,抛出错误
35 + "noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
36 + "noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch case 语句贯穿)
37 +
38 + /* 模块解析选项 */
39 + "moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
40 + "baseUrl": ".", // 用于解析非相对模块名称的基目录
41 + "paths": { // 模块名到基于 baseUrl 的路径映射的列表
42 + "@/*": [
43 + "src/*"
44 + ]
45 + },
46 + // "rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
47 + // "typeRoots": [], // 包含类型声明的文件列表
48 + "types": [ // 需要包含的类型声明文件名列表
49 + // "webpack-env",
50 + "vite/client",
51 + "lodash",
52 + "moment",
53 + "node",
54 + "jquery",
55 + ],
56 + "allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
57 +
58 + /* Source Map Options */
59 + // "sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
60 + // "mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
61 + // "inlineSourceMap": true, // 生成单个 sourcemaps 文件,而不是将 sourcemaps 生成不同的文件
62 + // "inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap --sourceMap 属性
63 +
64 + /* 其他选项 */
65 + // "experimentalDecorators": true, // 启用装饰器
66 + // "emitDecoratorMetadata": true, // 为装饰器提供元数据的支持
67 +
68 + "esModuleInterop": true, // 可以在es6中导入commonjs
69 + },
70 + "include": [
71 + "src/**/*"
72 + ],
73 + "exclude": [
74 + "node_modules",
75 + "dist"
76 + ],
77 + "vueCompilerOptions": {
78 + "target": 2,
79 + "experimentalSuppressInvalidJsxElementTypeErrors": true
80 + }
81 +}
1 +{
2 + "defaultSeverity": "warning",
3 + "extends": [
4 + "tslint:recommended"
5 + ],
6 + "linterOptions": {
7 + "exclude": [
8 + "node_modules/**"
9 + ]
10 + },
11 + "rules": {
12 + "quotemark": [
13 + true,
14 + "single"
15 + ],
16 + "indent": [
17 + true,
18 + "spaces",
19 + 2
20 + ],
21 + "interface-name": false,
22 + "ordered-imports": false,
23 + "object-literal-sort-keys": false,
24 + "no-consecutive-blank-lines": false,
25 + "no-console": true
26 + }
27 +}
1 +/*
2 + * @Date: 2022-06-13 10:39:44
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-13 10:41:43
5 + * @FilePath: /tswj/typings/index.d.ts
6 + * @Description: 文件描述
7 + */
8 +export {};
9 +
10 +// => 全局类型声明
11 +declare global {
12 + interface Window {
13 + _hmt: any;
14 + wx: any;
15 + AlipayJSBridge: any;
16 + }
17 + namespace GD {
18 + interface BaseResponse<T = any> {
19 + code: number;
20 + data: T;
21 + msg: string;
22 + page: {
23 + pageNo: number;
24 + pageSize: number;
25 + pages: number;
26 + total: number;
27 + };
28 + }
29 + }
30 +}
31 +
32 +// const response = GD.BaseResponse<{name: string}>
1 +/*
2 + * @Date: 2023-06-13 13:26:46
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-08-25 14:14:26
5 + * @FilePath: /xysBooking/vite.config.js
6 + * @Description: 文件描述
7 + */
8 +import vue from '@vitejs/plugin-vue';
9 +import dynamicImport from 'vite-plugin-dynamic-import';
10 +// import legacy from '@vitejs/plugin-legacy';
11 +// import styleImport, { VantResolve } from 'vite-plugin-style-import';
12 +import Components from 'unplugin-vue-components/vite';
13 +import { VantResolver } from 'unplugin-vue-components/resolvers';
14 +import { defineConfig, loadEnv } from 'vite';
15 +import { createProxy } from './build/proxy'
16 +import DefineOptions from 'unplugin-vue-define-options/vite';
17 +import AutoImport from 'unplugin-auto-import/vite';
18 +import postcsspxtoviewport from 'postcss-px-to-viewport'
19 +
20 +var path = require('path');
21 +
22 +export default ({ command, mode }) => {
23 + const root = process.cwd();
24 +
25 + const viteEnv = loadEnv(mode, root);
26 + // let isProd = (command === 'serve'); // 情景配置是否为开发模式 serve 或 build
27 +
28 + return defineConfig({
29 + // root: '',
30 + // root: './src/packages', // 多页面应用配置入口根目录
31 + base: viteEnv.VITE_BASE, // 开发或生产环境服务的公共基础路径。
32 + // base: isProd ? '/' : '/f/voice/', // 开发或生产环境服务的公共基础路径。
33 + // mode: '', // 在配置中指明将会把 serve 和 build 时的模式 都 覆盖掉。也可以通过命令行 --mode 选项来重写。
34 + // define: '', // 定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换。
35 + plugins: [ // 将要用到的插件数组。Falsy 虚值的插件将被忽略,插件数组将被扁平化(flatten)。查看 插件 API 获取 Vite 插件的更多细节。
36 + vue(),
37 + Components({
38 + resolvers: [VantResolver()],
39 + }),
40 + // styleImport({
41 + // resolves: [VantResolve()],
42 + // libs: [
43 + // {
44 + // libraryName: 'vant',
45 + // esModule: true,
46 + // resolveStyle: name => `../es/${name}/style`
47 + // }
48 + // ]
49 + // }), // 按需引入 vant 位置报错问题
50 + dynamicImport(), // 增强 Vite 内置的 dynamic import, 支持在 import() 中使用别名
51 + // legacy({
52 + // targets: ['defaults', 'not IE 11']
53 + // }), // Vite 的默认旧版浏览器支持时提供此插件本机ESM的支持。
54 + DefineOptions(), // TAG: 插件来对组件名进行注册的, 解决setup没法写name的问题
55 + AutoImport({ // API 自动导入
56 + // 可以自定义文件生成的位置,默认是根目录下,使用ts的建议放src目录下
57 + dts: 'src/auto-imports.d.ts',
58 + imports: ['vue', 'vue-router'],
59 + // 解决eslint报错问题
60 + eslintrc: {
61 + enabled: true
62 + }
63 + }),
64 + ],
65 + publicDir: 'public', // 作为静态资源服务的文件夹。这个目录中的文件会在开发中被服务于 /,在开发模式时,会被拷贝到 outDir 的根目录,并没有转换,永远只是复制到这里。该值可以是文件系统的绝对路径,也可以是相对于项目的根目录路径。
66 + // cacheDir: '', // 存储缓存文件的目录。此目录下会存储预打包的依赖项或 vite 生成的某些缓存文件,使用缓存可以提高性能。如需重新生成缓存文件,你可以使用 --force 命令行选项或手动删除目录。此选项的值可以是文件的绝对路径,也可以是以项目根目录为基准的相对路径。
67 + resolve: {
68 + alias: { // 将会被传递到 @rollup/plugin-alias 作为 entries 的选项。也可以是一个对象,或一个 { find, replacement } 的数组. 当使用文件系统路径的别名时,请始终使用绝对路径。相对路径的别名值会被原封不动地使用,因此无法被正常解析。 更高级的自定义解析方法可以通过 插件 实现。
69 + "@": path.resolve(__dirname, "src"),
70 + "@components": path.resolve(__dirname, "src/components"),
71 + "@composables": path.resolve(__dirname, "src/composables"),
72 + "@utils": path.resolve(__dirname, "src/utils"),
73 + "@images": path.resolve(__dirname, "src/assets/images"),
74 + "@css": path.resolve(__dirname, "src/assets/css"),
75 + "@mock": path.resolve(__dirname, "src/assets/mock"),
76 + "common": path.resolve(__dirname, "src/common"),
77 + },
78 + dedupe: ['vue'], // 如果你在你的应用程序中有相同依赖的副本(比如 monorepos),使用这个选项来强制 Vite 总是将列出的依赖关系解析到相同的副本(从项目根目录)。
79 + // conditions: [''], // 在解析包的 情景导出 时允许的附加条件。
80 + // mainFields: [''], // package.json 中,在解析包的入口点时尝试的字段列表。注意,这比从 exports 字段解析的情景导出优先级低:如果一个入口点从 exports 成功解析,主字段将被忽略。
81 + extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], // 导入时想要省略的扩展名列表。注意,不 建议忽略自定义导入类型的扩展名(例如:.vue),因为它会干扰 IDE 和类型支持。
82 + },
83 + css: {
84 + modules: '', // 配置 CSS modules 的行为。选项将被传递给 postcss-modules。
85 + postcss: { // 内联的 PostCSS 配置(格式同 postcss.config.js),或者一个(默认基于项目根目录的)自定义的 PostCSS 配置路径。其路径搜索是通过 postcss-load-config 实现的。 注意,如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源。
86 + plugins: [
87 + // postcsspxtoviewport({
88 + // unitToConvert: 'px', // 要转化的单位
89 + // viewportWidth: 375, // UI设计稿的宽度
90 + // unitPrecision: 6, // 转换后的精度,即小数点位数
91 + // propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
92 + // viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
93 + // fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
94 + // selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
95 + // minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
96 + // mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
97 + // replace: true, // 是否转换后直接更换属性值
98 + // // exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
99 + // exclude: [],
100 + // landscape: false // 是否处理横屏情况
101 + // })
102 + ]
103 + },
104 + preprocessorOptions: {
105 + less: {
106 + javascriptEnabled: true,
107 + additionalData: `@import "${path.resolve(__dirname, 'src/assets/styles/base.less')}";`
108 + }
109 + } // 指定传递给 CSS 预处理器的选项。
110 + },
111 + // json: {
112 + // namedExports: true, // 是否支持从 .json 文件中进行按名导入。
113 + // stringify: false, // 若设置为 true,导入的 JSON 会被转换为 export default JSON.parse("...") 会比转译成对象字面量性能更好,尤其是当 JSON 文件较大的时候。 开启此项,则会禁用按名导入。
114 + // },
115 + // esbuild: false, //
116 + // assetsInclude: '', // 指定其他文件类型作为静态资源处理
117 + logLevel: 'info', // 调整控制台输出的级别,默认为 'info'。
118 + // clearScreen: true, // 设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息。命令行模式下请通过 --clearScreen false 设置。
119 + server: {
120 + host: '0.0.0.0',
121 + port: viteEnv.VITE_PORT, // 本地服务端口
122 + // strictPort: true, // 设为true时若端口已被占用则会直接退出, 而不是尝试下一个可用端口
123 + // https: '',
124 + // open: false, // 在服务器启动时自动在浏览器中打开应用程序. 当此值为字符串时, 会被当作URL的路径名.
125 + // proxy: { // 代理
126 + // '/srv/': {
127 + // // target: 'http://voice.onwall.cn',
128 + // target: viteEnv.VITE_PROXY_TARGET,
129 + // changeOrigin: true,
130 + // // rewrite: (path) => path.replace(/^\/api/, '')
131 + // },
132 + // },
133 + proxy: createProxy(viteEnv.VITE_PROXY_PREFIX, viteEnv.VITE_PROXY_TARGET),
134 + // cors: '', // 为开发服务器配置 CORS。默认启用并允许任何源,传递一个 选项对象 来调整行为或设为 false 表示禁用。
135 + // force: '', // 设置为 true 强制使依赖预构建。
136 + // hmr: '', // 禁用或配置 HMR 连接(用于 HMR websocket 必须使用不同的 http 服务器地址的情况)。 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层。
137 + // watch: '', // 传递给 chokidar 的文件系统监视器选项。
138 + },
139 + build: {
140 + // outDir: 'voice', // 指定输出路径(相对于项目根目录).
141 + outDir: viteEnv.VITE_OUTDIR, // 指定输出路径(相对于项目根目录).
142 + assetsDir: 'static',
143 + rollupOptions: {
144 + output: {
145 + chunkFileNames: 'static/js/[name]-[hash].js',
146 + entryFileNames: 'static/js/[name]-[hash].js',
147 + assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
148 + },
149 + input: { // 多页面应用模式, 打包时配置,运行配置要处理root
150 + main: path.resolve(__dirname, 'index.html'),
151 + // mono1: path.resolve(__dirname, 'src/packages/mono1/index.html'),
152 + // mono2: path.resolve(__dirname, 'src/packages/mono2/index.html'),
153 + }
154 + },
155 + },
156 + optimizeDeps: {
157 + // entries: '',
158 + // exclude: [],
159 + include: ['jquery', 'lodash', 'moment', 'axios', 'pinia', 'vue-router', 'vant'], // 默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。
160 + // keepNames: false, // 打包器有时需要重命名符号以避免冲突。 设置此项为 true 可以在函数和类上保留 name 属性。 若想获取更多详情,请参阅 keepNames
161 + }
162 + });
163 +};
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.