hookehuyr

初始化

Showing 103 changed files with 3529 additions and 0 deletions
1 +# port
2 +VITE_PORT = 8006
3 +
4 +# 反向代理服务器地址
5 +VITE_PROXY_TARGET = http://voice.onwall.cn
6 +
7 +# API请求前缀
8 +VITE_PROXY_PREFIX = /srv/
9 +
10 +# 打包输出文件夹名称
11 +VITE_OUTDIR = voice
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 +
10 +# B端账号
11 +VITE_ID = 13761653761
12 +
13 +# 验证码
14 +VITE_PIN =
1 +# 资源公共路径
2 +VITE_BASE = /f/voice/
3 +
4 +# 测试open-id
5 +VITE_APP_OPENID =
6 +
7 +# B端账号
8 +VITE_APP_ID =
9 +
10 +# 验证码
11 +VITE_APP_PIN =
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 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-27 08:59:09
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-07-08 18:15:20
6 + * @FilePath: /tswj/.eslintrc.js
7 + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
8 + */
9 +module.exports = {
10 + // parser: '@typescript-eslint/parser',
11 + parser: 'vue-eslint-parser',
12 + parserOptions: {
13 + parser: 'babel-eslint',
14 + // parser: '@typescript-eslint/parser',
15 + },
16 + extends: [
17 + // add more generic rule sets here, such as:
18 + // 'eslint:recommended',
19 + 'plugin:vue/vue3-recommended',
20 + './.eslintrc-auto-import.json'
21 + // 'plugin:vue/recommended' // Use this if you are using Vue.js 2.x.
22 + ],
23 + rules: {
24 + // override/add rules settings here, such as:
25 + // 'vue/no-unused-vars': 'error'
26 + "vue/max-attributes-per-line": ["error", {
27 + "singleline": {
28 + "max": 20
29 + },
30 + "multiline": {
31 + "max": 10
32 + }
33 + }],
34 + "vue/singleline-html-element-content-newline": 0, // 在单行元素的内容之前和之后需要换行符
35 + "vue/first-attribute-linebreak": 0, // 强制第一个属性需要换行
36 + "vue/multi-word-component-names": 0, // 要求组件名称始终为多字
37 + "vue/html-indent": 0, // 执行一致的缩进
38 + "vue/html-closing-bracket-newline": 0, // 在标签的右括号之前要求或禁止换行
39 + },
40 + overrides: [
41 + {
42 + files: ['*.ts'],
43 + parser: '@typescript-eslint/parser',
44 + plugins: ['@typescript-eslint'],
45 + extends: ['plugin:@typescript-eslint/recommended'],
46 + },
47 + ],
48 +}
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
1 +{
2 + "esversion": 11,
3 + "asi": true
4 +}
...\ No newline at end of file ...\ No newline at end of file
1 +v18.13.0
1 +“碳”寻复兴公园
......
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 +/* eslint-disable */
2 +/* prettier-ignore */
3 +// @ts-nocheck
4 +// Generated by unplugin-vue-components
5 +// Read more: https://github.com/vuejs/core/pull/3399
6 +export {}
7 +
8 +declare module 'vue' {
9 + export interface GlobalComponents {
10 + '图形验证码': typeof import('./src/components/图形验证码.vue')['default']
11 + Agreement: typeof import('./src/components/DonateFlower/agreement.vue')['default']
12 + AuditVideoCard: typeof import('./src/components/AuditVideoCard/index.vue')['default']
13 + Banner: typeof import('./src/components/MuiVideo/banner.vue')['default']
14 + BookCard: typeof import('./src/components/BookCard/index.vue')['default']
15 + BVideoCard: typeof import('./src/components/BVideoCard/index.vue')['default']
16 + CommentBox: typeof import('./src/components/CommentBox/index.vue')['default']
17 + CommentList: typeof import('./src/components/CommentList/index.vue')['default']
18 + DonateBar: typeof import('./src/components/DonateBar/index.vue')['default']
19 + DonateBook: typeof import('./src/components/DonateBook/index.vue')['default']
20 + DonateCert: typeof import('./src/components/DonateCert/index.vue')['default']
21 + DonateCertPost: typeof import('./src/components/DonateCertPost/index.vue')['default']
22 + DonateFlower: typeof import('./src/components/DonateFlower/index.vue')['default']
23 + FlowerIcon: typeof import('./src/components/FlowerIcon/index.vue')['default']
24 + ImageSliderVerify: typeof import('./src/components/ImageSliderVerify/index.vue')['default']
25 + LocalismBox: typeof import('./src/components/LocalismBox/index.vue')['default']
26 + LoginBox: typeof import('./src/components/LoginBox/index.vue')['default']
27 + MuiVideo: typeof import('./src/components/MuiVideo/index.vue')['default']
28 + MyButton: typeof import('./src/components/MyButton/index.vue')['default']
29 + NoticeOverlay: typeof import('./src/components/NoticeOverlay/index.vue')['default']
30 + NoticeOverlayModule: typeof import('./src/components/NoticeOverlayModule/index.vue')['default']
31 + RankingItem: typeof import('./src/components/RankingItem/index.vue')['default']
32 + RightSideList: typeof import('./src/components/RightSideList/index.vue')['default']
33 + RouterLink: typeof import('vue-router')['RouterLink']
34 + RouterView: typeof import('vue-router')['RouterView']
35 + ShortcutFixed: typeof import('./src/components/ShortcutFixed/index.vue')['default']
36 + Status: typeof import('./src/components/MuiVideo/status.vue')['default']
37 + Template: typeof import('./src/components/template/index.vue')['default']
38 + Test: typeof import('./src/components/LoginBox/test.vue')['default']
39 + VideoBar: typeof import('./src/components/MuiVideo/videoBar.vue')['default']
40 + VideoCard: typeof import('./src/components/VideoCard/index.vue')['default']
41 + VideoDetail: typeof import('./src/components/VideoDetail/index.vue')['default']
42 + }
43 +}
No preview for this file type
1 +<!DOCTYPE html>
2 +<html lang='zh'>
3 +<head>
4 + <meta charset="UTF-8">
5 + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
6 + <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
7 + <title></title>
8 + <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.compat.css" /> -->
9 +</head>
10 +<body>
11 + <div id="app"></div>
12 + <script type="module" src="/src/main.js"></script>
13 +</body>
14 +</html>
1 +-----BEGIN PRIVATE KEY-----
2 +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDEzFrlVSgeuOQT
3 +sglIR5RxEASnH0XKKxg/rl6U0pe6NGHwnybhdO6ZHAWRIU4OVOVDCI3OnJ2/2c2o
4 +eCT9L+fDGJew3BAMZvKKn1A/o5xM5YYJo8IKKeJbehjXajXdRJ5WkhAKwSH+rSJE
5 +nADUF4S5sqbXVlvttc1QUVL9GprPq5OBptDfcs6AM+dN1XOn/LgFt0KJ1C80Ah1a
6 +TLjLLFOGEJNLtTAUpLzJb5DKLro88QgPK8ek5afOKiOMULnFk3QJCZ1W98Xd75zq
7 +5Fz/FLCmTgkZMGe+iLr44MewmwMu1H/cHtWVkfEZiFUcRa5xc6SbvMGENfu/3/L4
8 +rLQ7ppMRAgMBAAECggEAaNnMD+WoA35Unh28DlN8xiRXpkbmIwmE2ODpKXduOVoR
9 +WGcjCvoG6XJhkOpisQYQQ/+5tfwBnCbKCNlCM9cjLvHaV/NXZZQv4yVwVwevjdS3
10 +7kjeaBXasQxDUfoXirU1e0BE5cXye8L4v/8x/c4t+9YwSAiN3/99zS4W/hz/oGaE
11 +fCkjHOHQkQKw0invQz3kf86iyanLBS/rllJAtZKmRFqZKchWR68m+sDcbAP320tb
12 +z2yi7og8QcP+kuqQWr2QVOCfD7zz5ihLDCnzipNU/7JmHIkUXqYI8NKGLSftN0LB
13 +NSmOinsx/oM4gu7IAMsyZjpM4UkAHieJEtAHM4RIMQKBgQD13iV4QgupvQauwnl/
14 +Kezse8zSjZS2YSUVZRsMDqw62sVa2BE4CV9NCWO3nPp5MDSDXahjDuoS640askM5
15 +ynWQWbDmttomlVqPbXwHUfKqTLgUIvl7byIuyoJHAIlL/7xEOeHHa5oIy49aKTnw
16 +vrJMTrBifNsdqWp2ht64hwNL3QKBgQDM6IklIbfXDEdji7LAaCzu24uttWAwLn69
17 +d1q5fMVWfWBl3l8O3gvbJSxXTeLHNcjsOb1iQq+3CT/eV+g+5xv17EQH+32ASq9d
18 +VBQ0tZC09BkMcDKPulC9JoGVsgLnIbjOy7GJKOhANqYh18FW9JAYvzZFWzNpsGAR
19 +kXZIGt/axQKBgQDotvZCSEkfxPHhUeOL0FQXVep9VFLw+SwPfx5FoFG2d0Gbha1u
20 +m7hfg0amEWgmctERkgGCmShG9jsdjKMCvTXfhnVhOqtrH6yS2y8tAoysUmddb+kx
21 +wvPY1AbRS5monItHDH4+sgMe1gV+ck0MKIM8pLJg1grTnXpOa8O9ZtVg5QKBgDFM
22 +4XJlom3DLons2p0gc28ks36f3Py6sxOy28k1E+WzVLYtwoE5O3EGiJyYyK9VaXos
23 +ijxR/yTyvMMqM16vDDMnHVcuUwvC7F5wFEx6Qs7GzCAJ/qBGG5bm5Na3datWmbhn
24 +mdd+WCLbAy2xU3swbFsH5m7Zeo07OmH/tY2zqZhhAoGBALxxnWJ4bgtZHcHREB0A
25 +QP6ZSLWoUk0ggoPuwSVgHImW+/C1/38KjHgv4UmhS59MpNqX3BOUgP1lTKQ4ifut
26 +N2/tFBdZXNdsbRNYp2UTGAHzUK6sUGyvY4g6mAZJWsIsVIzuLrZdrQywlglBpM4Q
27 +v/Q0jcIl9880opSG/+dfRbpW
28 +-----END PRIVATE KEY-----
1 +-----BEGIN CERTIFICATE-----
2 +MIIEMTCCApmgAwIBAgIRAJqTbr7oXEP7a1vMS7zyApQwDQYJKoZIhvcNAQELBQAw
3 +ZzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMR4wHAYDVQQLDBVodXlp
4 +cnVpQEhZUi1NQUMubG9jYWwxJTAjBgNVBAMMHG1rY2VydCBodXlpcnVpQEhZUi1N
5 +QUMubG9jYWwwHhcNMjMwNTE5MDcxMTE0WhcNMjUwODE5MDcxMTE0WjBVMScwJQYD
6 +VQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxKjAoBgNVBAsMIWh1
7 +eWlydWlASFlSLU1BQy5sb2NhbCAo6IOh5YWI55SfKTCCASIwDQYJKoZIhvcNAQEB
8 +BQADggEPADCCAQoCggEBAMTMWuVVKB645BOyCUhHlHEQBKcfRcorGD+uXpTSl7o0
9 +YfCfJuF07pkcBZEhTg5U5UMIjc6cnb/Zzah4JP0v58MYl7DcEAxm8oqfUD+jnEzl
10 +hgmjwgop4lt6GNdqNd1EnlaSEArBIf6tIkScANQXhLmyptdWW+21zVBRUv0ams+r
11 +k4Gm0N9yzoAz503Vc6f8uAW3QonULzQCHVpMuMssU4YQk0u1MBSkvMlvkMouujzx
12 +CA8rx6Tlp84qI4xQucWTdAkJnVb3xd3vnOrkXP8UsKZOCRkwZ76Iuvjgx7CbAy7U
13 +f9we1ZWR8RmIVRxFrnFzpJu8wYQ1+7/f8vistDumkxECAwEAAaNqMGgwDgYDVR0P
14 +AQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFJbi3Ybj
15 +xDBPnN8B3bayujege6IKMCAGA1UdEQQZMBeCCWxvY2FsaG9zdIcEfwAAAYcEwKgC
16 +ejANBgkqhkiG9w0BAQsFAAOCAYEAi3Scjz10WV/nJnlKHGbQxBgM4FqOQMEMqNoQ
17 +ojdRQqY7iTfV+6265TFaZ9pY27+ZKzL8Qyb6htqNYuRKACXqEohHHJBdDlGV9Kda
18 +hxznoP9ZBYm4NoiSiIJIQmEVy5SH/qb208gZPXb8mQT/czPPmQAE0oTWrVUDRkJl
19 +YGJmfcdVuN8JfLqW0HxUdP89gqH8nHv72+wZpcqc9i/yVwCfjhqgbinwU/rkZRqW
20 +7SIBVlDJs7d+4EuDMQMMe21w4b3isXr+LVtrH6I1MtQ0hTd9bQiMvl6HQ6hDK9Yd
21 +VRz2ubj5p2/qzCchxxfMMJjAea8YNlQCL593963PKzDPcaJnw8j9RtySpeIxiPPQ
22 +4+oRkZgO6Bd9OrxOAmoLG8+bJJbwmWC0LxH2nvYmArFgzKDu5hqwGQnLP0/7GeIk
23 +fNqWPJ84rj0V3lfVRKYWYwXNJbFTCQ3/ewN6mTChzBWgmRFUv6LjSfzq/X2l5tX0
24 +vLXgvm2XxAtQoVRUAYsRRRrFwguT
25 +-----END CERTIFICATE-----
1 +使用mkcert在本地生成2个免费的https证书(此命令会生成两个文件: localhost+2.pem, localhost+2-key.pem)
2 +mkcert localhost 127.0.0.1 ::1
3 +
4 +https://blog.csdn.net/themagickeyjianan/article/details/106836904
5 +https://blog.wangjunfeng.com/post/local_https/
6 +https://juejin.cn/post/7141308011921801223?searchId=20230817153624B0F9ACBED49D8807E243#heading-7
This diff could not be displayed because it is too large.
1 +{
2 + "name": "tjws",
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 + "@vitejs/plugin-legacy": "^1.8.2",
16 + "@vueuse/core": "^8.5.0",
17 + "animate.css": "^4.1.1",
18 + "dayjs": "^1.11.3",
19 + "default-passive-events": "^2.0.0",
20 + "global": "^4.4.0",
21 + "html2canvas": "^1.4.1",
22 + "jquery": "^3.6.0",
23 + "js-cookie": "^3.0.1",
24 + "lodash": "^4.17.21",
25 + "moment": "^2.29.3",
26 + "mui-player": "^1.6.0",
27 + "recorder-core": "^1.3.23122400",
28 + "typescript": "^4.7.3",
29 + "uuid": "^8.3.2",
30 + "vant": "^4.8.10",
31 + "vconsole": "^3.14.6",
32 + "vite-plugin-dynamic-import": "^0.9.6",
33 + "vite-plugin-mp": "^1.6.1",
34 + "vue": "^3.2.36",
35 + "weixin-js-sdk": "^1.6.5"
36 + },
37 + "devDependencies": {
38 + "@types/jquery": "^3.5.14",
39 + "@types/lodash": "^4.14.182",
40 + "@types/moment": "^2.13.0",
41 + "@typescript-eslint/parser": "^5.27.1",
42 + "@vitejs/plugin-vue": "^2.3.3",
43 + "@vue/compiler-sfc": "^3.2.36",
44 + "axios": "^0.27.2",
45 + "chai": "^4.3.6",
46 + "cypress": "^9.7.0",
47 + "eslint-plugin-vue": "^9.0.1",
48 + "less": "^4.1.2",
49 + "mocha": "^10.0.0",
50 + "pinia": "^2.0.14",
51 + "postcss-px-to-viewport": "^1.1.1",
52 + "qs": "^6.10.3",
53 + "tslint": "^6.1.3",
54 + "unplugin-auto-import": "^0.8.8",
55 + "unplugin-vue-components": "^0.26.0",
56 + "unplugin-vue-define-options": "^0.6.1",
57 + "vite": "^2.9.9",
58 + "vite-plugin-style-import": "1.4.1",
59 + "vue-router": "^4.0.15"
60 + }
61 +}
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=voice
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/voice/f/voice && git pull'``
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 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-26 23:52:36
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2024-01-02 13:59:58
6 + * @FilePath: /tswj/src/App.vue
7 + * @Description:
8 +-->
9 +<template>
10 + <!-- 页面缓存 -->
11 + <router-view v-slot="{ Component, route }">
12 + <keep-alive :include="keepPages" :max="10">
13 + <component :is="Component" :key="route.name" />
14 + </keep-alive>
15 + </router-view>
16 +</template>
17 +
18 +<script setup>
19 +import { mainStore, useTitle } from '@/utils/generatePackage'
20 +import { computed, watchEffect, onMounted } from 'vue';
21 +import { useRoute } from 'vue-router'
22 +import { setToastDefaultOptions } from 'vant';
23 +// 会根据配置判断是否显示调试控件
24 +// eslint-disable-next-line no-unused-vars
25 +import vConsole from '@/utils/vconsole'
26 +// 初始化WX环境
27 +import wx from 'weixin-js-sdk'
28 +import { wxJsAPI } from '@/api/wx/config'
29 +import { apiList } from '@/api/wx/jsApiList.js'
30 +
31 +// 使用 include + pinia 状态管理动态缓存页面
32 +const store = mainStore()
33 +const keepPages = computed(() => store.getKeepPages)
34 +
35 +// TAG: 全局设置页面标题
36 +const $route = useRoute();
37 +watchEffect(
38 + () => useTitle($route.meta.title)
39 +)
40 +
41 +// TAG: 全局配置Toast
42 +// setToastDefaultOptions({
43 +// duration: 2000,
44 +// className: 'zIndex',
45 +// wordBreak: 'all',
46 +// });
47 +
48 +onMounted(async () => {
49 + const { data } = await wxJsAPI();
50 + data.jsApiList = apiList;
51 + wx.config(data);
52 + wx.ready(() => {
53 + wx.showAllNonBaseMenuItem();
54 + });
55 + wx.error((err) => {
56 + console.warn(err);
57 + });
58 +})
59 +</script>
60 +
61 +<style lang="less">
62 +@prefix: ~'@{namespace}-x';
63 +
64 +html,
65 +body {
66 + width: 100%;
67 + height: 100%;
68 + padding: 0;
69 + margin: 0;
70 +}
71 +
72 +body {
73 + position: relative;
74 + // --van-white: #fff;
75 + // --van-blue: #1989fa;
76 + // --van-button-primary-color: var(--van-white);
77 + // --van-button-primary-background: var(--van-primary-color);
78 + /* 全局修改主色调 */
79 + // --van-blue: #F9D95C;
80 +
81 + // background-color: #FAFAFA;
82 + p {
83 + margin: 0;
84 + padding: 0;
85 + }
86 +}
87 +
88 +.@{prefix} {
89 + color: red;
90 +}
91 +
92 +.global-center {
93 + position: relative;
94 + top: 50%;
95 + transform: translateY(-50%);
96 +}
97 +
98 +.zIndex {
99 + z-index: 4500 !important;
100 +}
101 +
102 +.van-popup.van-toast {
103 + z-index: 3003 !important;
104 + background: rgba(0, 0, 0, 0.7) !important;
105 +}
106 +</style>
1 +/*
2 + * @Date: 2022-06-17 14:54:29
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-18 22:18:46
5 + * @FilePath: /tswj/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: 2024-01-02 16:46:57
5 + * @FilePath: /tswj/src/api/fn.js
6 + * @Description: 文件描述
7 + */
8 +import axios from '@/utils/axios';
9 +// import { Toast } from 'vant';
10 +import { showToast } from 'vant';
11 +import qs from 'Qs'
12 +
13 +/**
14 + * 网络请求功能函数
15 + * @param {*} api 请求axios接口
16 + * @returns 请求成功后,获取数据
17 + */
18 +export const fn = (api) => {
19 + return api
20 + .then(res => {
21 + if (res.data.code === 1) {
22 + return res.data || true;
23 + } else {
24 + // tslint:disable-next-line: no-console
25 + console.warn(res);
26 + if (!res.data.show) return false;
27 + // Toast({
28 + // icon: 'close',
29 + // message: res.data.msg
30 + // });
31 + showToast(res.data.msg);
32 + return false;
33 + }
34 + })
35 + .catch(err => {
36 + // tslint:disable-next-line: no-console
37 + console.error(err);
38 + return false;
39 + })
40 + .finally(() => { // 最终执行
41 + })
42 +}
43 +
44 +/**
45 + * 七牛返回格式
46 + * @param {*} api
47 + * @returns
48 + */
49 +export const uploadFn = (api) => {
50 + return api
51 + .then(res => {
52 + if (res.statusText === 'OK') {
53 + return res.data || true;
54 + } else {
55 + // tslint:disable-next-line: no-console
56 + console.warn(res);
57 + if (!res.data.show) return false;
58 + // Toast({
59 + // icon: 'close',
60 + // message: res.data.msg
61 + // });
62 + showToast(res.data.msg);
63 + return false;
64 + }
65 + })
66 + .catch(err => {
67 + // tslint:disable-next-line: no-console
68 + console.error(err);
69 + return false;
70 + })
71 +}
72 +
73 +/**
74 + * 统一 GET/POST 不同传参形式
75 + */
76 +export const fetch = {
77 + get: function (api, params) {
78 + return axios.get(api, { params })
79 + },
80 + post: function (api, params) {
81 + return axios.post(api, params)
82 + },
83 + stringifyPost: function (api, params) {
84 + return axios.post(api, qs.stringify(params))
85 + },
86 + basePost: function (url, data, config) {
87 + return axios.post(url, data, config)
88 + }
89 +}
1 +/*
2 + * @Date: 2023-12-31 11:20:51
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-01-02 16:48:10
5 + * @FilePath: /tswj/src/api/new_year_2024.js
6 + * @Description: 文件描述
7 + */
8 +import { fn, fetch } from '@/api/fn';
9 +
10 +const Api = {
11 + GET_AUDIO: '/srv/?a=meet_spring&t=get_audio',
12 + SAVE_EVENT: '/srv/?a=meet_spring&t=save_event',
13 + GET_BOOK: '/srv/?a=meet_spring&t=get_book',
14 + ADD_DONATE: '/srv/?a=meet_spring&t=add_donate',
15 + CERT_LIST: '/srv/?a=meet_spring&t=cert_list',
16 + SHARE_WISH_LIST: '/srv/?a=meet_spring&t=share_wish_list',
17 + WISH_PRIZE: '/srv/?a=meet_spring&t=win_prize',
18 + DEAL_PRIZE: '/srv/?a=meet_spring&t=deal_prize',
19 + PRIZE_LIST: '/srv/?a=meet_spring&t=prize_list',
20 +}
21 +
22 +/**
23 + * @description: 随机获取一个音频素材
24 + * @returns
25 + */
26 +export const getAudioAPI = (params) => fn(fetch.post(Api.GET_AUDIO, params));
27 +
28 +/**
29 + * @description: 埋点
30 + * @returns
31 + */
32 +export const saveEventAPI = (params) => fn(fetch.post(Api.SAVE_EVENT, params));
33 +
34 +/**
35 + * @description: 随机获取4本书
36 + * @returns
37 + */
38 +export const getBookAPI = (params) => fn(fetch.get(Api.GET_BOOK, params));
39 +
40 +/**
41 + * @description: 生成捐助记录
42 + * @returns
43 + */
44 +export const addDonateAPI = (params) => fn(fetch.post(Api.ADD_DONATE, params));
45 +
46 +/**
47 + * @description: 证书列表
48 + * @returns
49 + */
50 +export const certListAPI = (params) => fn(fetch.get(Api.CERT_LIST, params));
51 +
52 +/**
53 + * @description: 分享祝福语列表
54 + * @returns
55 + */
56 +export const shareWishListAPI = (params) => fn(fetch.get(Api.SHARE_WISH_LIST, params));
57 +
58 +/**
59 + * @description: 抽奖
60 + * @returns
61 + */
62 +export const wishPrizeAPI = (params) => fn(fetch.post(Api.WISH_PRIZE, params));
63 +
64 +/**
65 + * @description: 处置奖品
66 + * @returns
67 + */
68 +export const dealPrizeAPI = (params) => fn(fetch.post(Api.DEAL_PRIZE, params));
69 +
70 +/**
71 + * @description: 中奖列表
72 + * @returns
73 + */
74 +export const prizeListAPI = (params) => fn(fetch.get(Api.PRIZE_LIST, 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 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-17 12:13:13
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-12 22:50:29
6 + * @FilePath: /tswj/src/composables/index.js
7 + * @Description:
8 + */
9 +import { onMounted, onUnmounted } from 'vue'
10 +
11 +import { useVideoList } from '@/composables/useVideoList.js'
12 +import { useDefaultPerf } from '@/composables/useDefaultPerf.js'
13 +import { useBookList, useAsyncBookList } from '@/composables/useBookList.js'
14 +import { useShortcutBar } from '@/composables/useShortcutBar.js'
15 +import { useScrollTop } from '@/composables/useScrollTop.js'
16 +import { useMessageList } from '@/composables/useMessageList.ts'
17 +
18 +export {
19 + useVideoList,
20 + useDefaultPerf,
21 + useBookList,
22 + useAsyncBookList,
23 + useShortcutBar,
24 + useScrollTop,
25 + useMessageList,
26 +}
27 +
28 +/**
29 + * 添加和清除 DOM 事件监听器
30 + * @param {*} target
31 + * @param {*} event
32 + * @param {*} callback
33 + */
34 +export function useEventListener(target, event, callback) {
35 + onMounted(() => target?.addEventListener(event, callback))
36 + onUnmounted(() => target?.removeEventListener(event, callback))
37 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-07 17:46:54
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-12 22:55:58
6 + * @FilePath: /tswj/src/composables/useBookList.js
7 + * @Description:
8 + */
9 +import { ref } from 'vue'
10 +import axios from '@/utils/axios';
11 +import { Toast } from 'vant';
12 +import { useRoute } from 'vue-router';
13 +import { kgBookListAPI } from '@/api/C/kg'
14 +
15 +export const useBookList = () => {
16 + const $route = useRoute();
17 + const emptyStatus = ref(false);
18 + // tslint:disable-next-line: variable-name
19 + const kg_id = $route.query.kg_id ? $route.query.kg_id : '';
20 + const kgInfo = ref({
21 + id: '',
22 + logo: '',
23 + name: '',
24 + multi_name: '',
25 + book_list: []
26 + });
27 + if (kg_id) { // 从学校列表进入
28 + axios.get('/srv/?a=kg_book_list', {
29 + params: {
30 + kg_id
31 + }
32 + })
33 + .then(res => {
34 + if (res.data.code === 1) {
35 + kgInfo.value = res.data.data;
36 + kgInfo.value.book_list.forEach(item => {
37 + item.show = true; // 默认显示所有,给搜索功能留的hook
38 + });
39 + // 有空格分割name
40 + if (kgInfo.value.name.indexOf(' ') > -1) {
41 + kgInfo.value.multi_name = kgInfo.value.name.split(' ');
42 + }
43 + if (!kgInfo.value.book_list.length) {
44 + emptyStatus.value = true;
45 + }
46 + } else {
47 + // tslint:disable-next-line: no-console
48 + console.warn(res);
49 + if (!res.data.show) return false;
50 + Toast({
51 + icon: 'close',
52 + message: res.data.msg
53 + });
54 + }
55 + })
56 + .catch(err => {
57 + // tslint:disable-next-line: no-console
58 + console.error(err);
59 + })
60 + } else { // 从访客进入
61 + axios.get('/srv/?a=book_list')
62 + .then(res => {
63 + if (res.data.code === 1) {
64 + res.data.data.forEach(item => {
65 + item.show = true; // 默认显示所有,给搜索功能留的hook
66 + });
67 + kgInfo.value = {
68 + book_list: res.data.data
69 + }
70 + if (!kgInfo.value.book_list.length) {
71 + emptyStatus.value = true;
72 + }
73 + } else {
74 + // tslint:disable-next-line: no-console
75 + console.warn(res);
76 + if (!res.data.show) return false;
77 + Toast({
78 + icon: 'close',
79 + message: res.data.msg
80 + });
81 + }
82 + })
83 + .catch(err => {
84 + // tslint:disable-next-line: no-console
85 + console.error(err);
86 + })
87 + }
88 + return {
89 + kg_id,
90 + kgInfo,
91 + emptyStatus
92 + }
93 +}
94 +
95 +// !!废弃方法
96 +// 前端使用方式过于复杂
97 +export const useAsyncBookList = async () => {
98 + const $route = useRoute();
99 + const emptyStatus = ref(false);
100 + // tslint:disable-next-line: variable-name
101 + const kg_id = $route.query.kg_id ? $route.query.kg_id : '';
102 + const kgInfo = ref({
103 + id: '',
104 + logo: '',
105 + name: '',
106 + multi_name: [],
107 + book_list: []
108 + });
109 + const { data } = await kgBookListAPI({ kg_id });
110 + if (data) kgInfo.value = data;
111 + kgInfo.value.book_list.forEach(item => {
112 + item.show = true; // 默认显示所有,给搜索功能留的hook
113 + });
114 + // 有空格分割name
115 + if (kgInfo.value.name.indexOf(' ') > -1) {
116 + kgInfo.value.multi_name = kgInfo.value.name.split(' ');
117 + }
118 + if (!kgInfo.value.book_list.length) {
119 + emptyStatus.value = true;
120 + }
121 + return {
122 + kg_id,
123 + kgInfo,
124 + emptyStatus
125 + }
126 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-18 14:31:26
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-05-30 10:18:19
6 + * @FilePath: /tswj/src/composables/useDefaultPerf.js
7 + * @Description:
8 + */
9 +import { ref } from 'vue'
10 +import axios from '@/utils/axios';
11 +import { Toast } from 'vant';
12 +
13 +/**
14 + * @description: 获取默认儿童信息
15 + * @param {*} bookId
16 + * @param {*} params
17 + * @param {*} avatar
18 + * @param {*} name
19 + * @param {*} price
20 + * @param {*} user_id
21 + * @param {*} perf_id
22 + * @param {*} perf_name
23 + * @param {*} can_upload
24 + * @param {*} can_upload
25 + * @param {*} can_upload
26 + * @param {*} message
27 + * @return {*}
28 + */
29 +export const useDefaultPerf = (bookId) => {
30 + // 金数据准备数据
31 + const userInfo = ref({})
32 +
33 + axios.get('/srv/?a=default_perf', {
34 + params: {
35 + book_id: bookId
36 + }
37 + })
38 + .then(res => {
39 + if (res.data.code === 1) {
40 + userInfo.value = {
41 + book_id: res.data.data.book_id,
42 + avatar: res.data.data.book_cover,
43 + name: res.data.data.book_name,
44 + price: res.data.data.book_price,
45 + user_id: res.data.data.user_id,
46 + perf_id: res.data.data.perf_id,
47 + perf_name: res.data.data.perf_name,
48 + can_upload: res.data.data.can_upload, // can_upload :1=可上传,-1=用户没有实名,-2=用户没有儿童表演者
49 + // can_upload: -1, // can_upload :1=可上传,-1=用户没有实名,-2=用户没有儿童表演者
50 + }
51 + } else {
52 + console.warn(res);
53 + if (!res.data.show) return false;
54 + Toast({
55 + icon: 'close',
56 + message: res.data.msg
57 + });
58 + }
59 + })
60 + .catch(err => {
61 + console.error(err);
62 + });
63 + return {
64 + userInfo
65 + }
66 +}
1 +/*
2 + * @Date: 2022-06-22 00:07:42
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-30 13:45:54
5 + * @FilePath: /tswj/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 { Toast } 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 + Toast({
30 + message: '请检查后再次提交',
31 + icon: 'cross',
32 + });
33 + })
34 + }
35 +
36 + /**
37 + * 判断微信环境看是否弹出控件框
38 + * 桌面微信直接输入
39 + * 其他环境弹出输入框
40 + */
41 + let use_widget = ref(true);
42 + use_widget.value = !!(wxInfo().isiOS || wxInfo().isAndroid);
43 +
44 + /**
45 + * 手机号码校验
46 + * 函数返回 true 表示校验通过,false 表示不通过
47 + * @param {*} val
48 + */
49 + const sms_disabled = ref(true);
50 + const phoneValidator = (val) => {
51 + let flag = false;
52 + // 简单判断手机号位数
53 + if (/1\d{10}/.test(val) && phone.value.length === 11) {
54 + sms_disabled.value = false;
55 + flag = true;
56 + } else {
57 + sms_disabled.value = true;
58 + flag = false;
59 + }
60 + return flag
61 + };
62 +
63 + /**
64 + * 手机号数字弹框
65 + */
66 + const keyboard_show = ref(false);
67 + const refPhone = ref(null)
68 + const showKeyboard = () => { // 弹出数字弹框
69 + keyboard_show.value = true;
70 + };
71 + const keyboardBlur = () => { // 数字键盘失焦回调
72 + keyboard_show.value = false;
73 + refPhone.value.validate();
74 + };
75 +
76 + // 设置发送短信倒计时
77 + // TAG: vant 自带倒计时函数
78 + const limitSeconds = ref(60000); // 配置倒计时秒数
79 + const countDown = useCountDown({ // 配置倒计时
80 + time: limitSeconds.value,
81 + onFinish: () => {
82 + countDown.reset();
83 + }
84 + });
85 +
86 + const sendCode = async () => { // 发送验证码
87 + countDown.start();
88 + // 验证码接口
89 + const { code } = await smsAPI({ phone: phone.value });
90 + if (code) {
91 + Toast.success('发送成功');
92 + }
93 + };
94 +
95 + // 过滤输入的数字 只能四位
96 + const smsFormatter = (value) => value.substring(0, 4);
97 +
98 + /**
99 + * 用户登录
100 + * @param {*} phone
101 + * @param {*} pin
102 + */
103 + const $router = useRouter();
104 + const onSubmit = async (values) => {
105 + const { code } = await bLoginAPI({ phone: values.phone, pin: values.code })
106 + if (code) {
107 + $router.push({
108 + path: '/business/index'
109 + });
110 + }
111 + };
112 +
113 + return {
114 + phone,
115 + code,
116 + onSubmit,
117 + use_widget,
118 + sms_disabled,
119 + phoneValidator,
120 + keyboardBlur,
121 + keyboard_show,
122 + showKeyboard,
123 + refPhone,
124 + refForm,
125 + validateForm,
126 + smsFormatter,
127 + limitSeconds,
128 + countDown,
129 + sendCode,
130 + }
131 +}
1 +/*
2 + * @Date: 2022-06-12 22:51:21
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-13 01:01:33
5 + * @FilePath: /tswj/src/composables/useMessageList.ts
6 + * @Description: 测试处理列表查询功能中的重复代码问题
7 + * 感觉复用意义不大,这么写反而很麻烦
8 + */
9 +import { Ref, ref } from 'vue'
10 +import { myCommentAPI } from '@/api/C/me'
11 +import _ from 'lodash'
12 +import { commentListType } from '@/@types/message/interface';
13 +import {
14 + loading,
15 + finished,
16 + limit,
17 + offset,
18 + finishedTextStatus,
19 + emptyStatus,
20 +} from '@/composables/variable';
21 +
22 +// scrollList的类型是个麻烦,其他地方调用时类型不一定一样
23 +function fn(data: [], scrollList: Ref<commentListType[]>) {
24 +// function fn(data: [], scrollList: any) {
25 + // 数据全部加载完成
26 + if (!data.length) {
27 + // 加载状态结束
28 + finished.value = true;
29 + }
30 + scrollList.value = [...scrollList.value, ...data];
31 + offset.value = scrollList.value.length;
32 + loading.value = false;
33 + // 隐藏loading标识,空列表图标
34 + if (!scrollList.value.length) {
35 + finishedTextStatus.value = false;
36 + emptyStatus.value = true;
37 + } else {
38 + emptyStatus.value = false;
39 + }
40 +
41 + return {
42 + scrollList,
43 + finished,
44 + loading,
45 + finishedTextStatus,
46 + emptyStatus,
47 + };
48 +}
49 +
50 +export const useMessageList = () => {
51 + // 我的留言接口联调
52 + const scrollList = ref<commentListType[]>([]);
53 + let obj = {
54 + scrollList,
55 + finished,
56 + loading,
57 + finishedTextStatus,
58 + emptyStatus,
59 + };
60 +
61 + const onLoad = async () => {
62 + const { data } = await myCommentAPI({ limit: limit.value, offset: offset.value });
63 + data.forEach((item: { target_name: string | null | undefined; c_action: string; c_name: string; }) => {
64 + let arr = _.split(item.target_name, '@'); // 分割评论的动作和姓名
65 + item.c_action = arr[0]; // 评论动作
66 + item.c_name = arr[1]; // 评论姓名
67 + });
68 + // fn把重复代码抽离
69 + obj = fn(data, scrollList);
70 + }
71 +
72 + return {
73 + onLoad,
74 + scrollList: obj.scrollList,
75 + loading: obj.loading,
76 + finished: obj.finished,
77 + finishedTextStatus: obj.finishedTextStatus,
78 + emptyStatus: obj.emptyStatus,
79 + };
80 +}
1 +import { $, _, storeToRefs, mainStore } from '@/utils/generatePackage'
2 +
3 +/**
4 + * 页面滚动恢复
5 + * @returns
6 + */
7 +export const useScrollTop = () => {
8 + const store = mainStore();
9 + const resetScrollTop = (key) => {
10 + // 嵌套滚动,执行两个,先滚外面再滚里面
11 + _.times(2, () => {
12 + $("html,body").animate({ "scrollTop": String(storeToRefs(store)[key].value) + 'px' });
13 + });
14 + }
15 + return {
16 + resetScrollTop,
17 + store
18 + }
19 +}
1 +/*
2 + * @Date: 2022-06-13 17:42:32
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-18 21:14:42
5 + * @FilePath: /tswj/src/composables/useShare.js
6 + * @Description: 文件描述
7 + */
8 +import wx from 'weixin-js-sdk';
9 +// import { Toast } from 'vant';
10 +
11 +/**
12 + * @description: 微信分享功能
13 + * @param {*} title 标题
14 + * @param {*} desc 描述
15 + * @param {*} imgUrl 图标
16 + * @return {*}
17 + */
18 +export const sharePage = ({title = '童声无界', desc = '共读一本书,传递一份爱。', imgUrl = 'http://voice.onwall.cn/f/voice/images/weixin_logo.jpg'}) => {
19 + const shareData = {
20 + title, // 分享标题
21 + desc, // 分享描述
22 + link: location.origin + location.pathname + location.hash, // 分享链接,该链接域名或路径必须与当前页面对应的公众号 JS 安全域名一致
23 + imgUrl, // 分享图标
24 + success: function () {
25 + // console.warn('设置成功');
26 + }
27 + }
28 + // 分享好友(微信好友或qq好友)
29 + wx.updateAppMessageShareData(shareData);
30 + // 分享到朋友圈或qq空间
31 + wx.updateTimelineShareData(shareData);
32 + // 分享到腾讯微博
33 + wx.onMenuShareWeibo(shareData);
34 +
35 + // // 获取“分享给朋友”按钮点击状态及自定义分享内容接口(即将废弃)
36 + // wx.onMenuShareAppMessage(shareData);
37 + // // 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口(即将废弃)
38 + // wx.onMenuShareTimeline(shareData);
39 + // // 获取“分享到QQ”按钮点击状态及自定义分享内容接口(即将废弃)
40 + // wx.onMenuShareQQ(shareData);
41 +}
1 +import { useRoute } from 'vue-router';
2 +import { ref } from 'vue';
3 +import { Cookies } from '@/utils/generatePackage'
4 +
5 +export const useShortcutBar = (item) => {
6 + const $route = useRoute();
7 + const path = $route.path;
8 + const isClient = Cookies.get('userType') === 'client' ? true : false; // 判断C端入口位置,访客/客户
9 + // const case1 = ['home', 'me', 'rank'];
10 + // const case2 = ['home'];
11 + // const case3 = ['me'];
12 + const shortcutItem = ref([]);
13 +
14 + // 配置快捷跳转条
15 + if (item) {
16 + shortcutItem.value = item;
17 + } else {
18 + if (path === '/client/chooseBook') { // 爱心捐书页面
19 + if (isClient) {
20 + shortcutItem.value = ['home', 'me', 'rank']
21 + } else {
22 + shortcutItem.value = ['me']
23 + }
24 + }
25 +
26 + if (path === '/client/donateCertificate') {
27 + shortcutItem.value = ['home']
28 + }
29 +
30 + if (path === '/business/index') {
31 + shortcutItem.value = ['me']
32 + }
33 + }
34 +
35 + return {
36 + shortcutItem
37 + }
38 +}
1 +import { ref } from 'vue'
2 +import axios from '@/utils/axios';
3 +import _ from 'lodash'
4 +import { Toast } from 'vant';
5 +
6 +export const useUnwatchList = () => {
7 + // 绑定页面数据
8 + const prod_list = ref([]);
9 + const limit = ref(10)
10 + const offset = ref(0)
11 +
12 + // 处理书籍下作品列表
13 + const loading = ref(false);
14 + const finished = ref(false);
15 +
16 + // 因为不能让空图标提前出来的写法
17 + const finishedTextStatus = ref(false);
18 + const emptyStatus = ref(false);
19 +
20 + /**
21 + * 向下滚动查询数据
22 + */
23 + const onLoad = () => {
24 + // 异步更新数据
25 + axios.get('/srv/?a=my_unplay', {
26 + params: {
27 + limit: limit.value,
28 + offset: offset.value
29 + }
30 + })
31 + .then(res => {
32 + if (res.data.code === 1) {
33 + prod_list.value = _.concat(prod_list.value, res.data.data.prod);
34 + prod_list.value = _.uniqBy(prod_list.value, 'id');
35 + _.each(prod_list.value, (item) => {
36 + item.type = 'read-only' // 特殊标识,判断入口 为keepAlive使用
37 + })
38 + offset.value = prod_list.value.length;
39 + loading.value = false;
40 + // 数据全部加载完成
41 + if (!res.data.data.prod.length) {
42 + // 加载状态结束
43 + finished.value = true;
44 + }
45 + // 空数据提示
46 + if (!prod_list.value.length) {
47 + finishedTextStatus.value = false;
48 + emptyStatus.value = true;
49 + }
50 + } else {
51 + // tslint:disable-next-line: no-console
52 + console.warn(res);
53 + if (!res.data.show) return false;
54 + Toast({
55 + icon: 'close',
56 + message: res.data.msg
57 + });
58 + }
59 + })
60 + .catch(err => {
61 + // tslint:disable-next-line: no-console
62 + console.error(err);
63 + })
64 + };
65 +
66 + return {
67 + onLoad,
68 + prod_list,
69 + finished,
70 + loading,
71 + finishedTextStatus,
72 + emptyStatus,
73 + }
74 +}
1 +/*
2 + * @Date: 2022-05-10 12:15:14
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-29 23:36:29
5 + * @FilePath: /tswj/src/composables/useUpload.js
6 + * @Description: 图片上传模块
7 + */
8 +import { v4 as uuidv4 } from 'uuid';
9 +import { ref, reactive } from 'vue'
10 +import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common'
11 +
12 +export const useUpload = () => {
13 + let lock_btn = ref(false); // 保存按钮锁
14 + let fileList = ref([]);
15 + let upload_image = reactive({ src: '' });
16 + const afterRead = async (res) => {
17 + lock_btn.value = true; // 上传开始, 不能保存
18 + let affix = uuidv4();
19 + // 此时可以自行将文件上传至服务器
20 + let dataURL = res.content;
21 + let base64url = dataURL.slice(dataURL.indexOf(',') + 1); // 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA.......
22 + // 获取七牛token
23 + const { token, key, code } = await qiniuTokenAPI({ filename: `${affix}_${res.file.name}`, file: base64url });
24 + if (code) {
25 + const config = {
26 + headers: {
27 + 'Content-Type': 'application/octet-stream',
28 + 'Authorization': 'UpToken ' + token, // UpToken后必须有一个 ' '(空格)
29 + }
30 + }
31 + // 上传七牛服务器
32 + const { filekey, hash, image_info } = await qiniuUploadAPI('http://upload.qiniup.com/putb64/-1/key/' + key, base64url, config)
33 + if (filekey) {
34 + // 保存图片
35 + const { data } = await saveFileAPI({ filekey, hash, format: image_info.format, height: image_info.height, width: image_info.width });
36 + upload_image.src = data.src;
37 + lock_btn.value = false; // 头像上传完成, 打开锁
38 + }
39 + }
40 + };
41 + const beforeDelete = () => { // 删除图片回调
42 + upload_image.src = '';
43 + return true;
44 + }
45 +
46 + return {
47 + lock_btn,
48 + fileList,
49 + upload_image,
50 + afterRead,
51 + beforeDelete
52 + }
53 +}
1 +import { ref } from 'vue'
2 +import axios from '@/utils/axios';
3 +import { Toast } from 'vant';
4 +
5 +export const idCard = () => {
6 + /**
7 + * 检查用户是否已实名认证 (实名认证后可以上传作品,留言)
8 + */
9 + const can_use = ref(false)
10 + axios.get('/srv/?a=can_upload')
11 + .then(res => {
12 + if (res.data.code === 1) {
13 + can_use.value = res.data.data.can_upload ? true : false;
14 + } else {
15 + console.warn(res);
16 + if (!res.data.show) return false;
17 + Toast({
18 + icon: 'close',
19 + message: res.data.msg
20 + });
21 + }
22 + })
23 + .catch(err => {
24 + console.error(err);
25 + })
26 +
27 + return {
28 + can_use
29 + }
30 + }
1 +/*
2 + * @Date: 2022-05-05 18:07:16
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-10-01 21:13:07
5 + * @FilePath: /tswj/src/composables/useVideoList.js
6 + * @Description: 文件描述
7 + */
8 +import { ref } from 'vue'
9 +import axios from '@/utils/axios';
10 +import _ from 'lodash'
11 +import { Toast } from 'vant';
12 +import { useRoute } from 'vue-router'
13 +import { bookInfoAPI } from '@/api/C/book'
14 +import { flowFn } from '@/hooks/useFlowFn'
15 +
16 +export const useVideoList = () => {
17 + const $route = useRoute();
18 + // 切换视频语言
19 + const checkMandarin = ref(true); // 普通话选项卡
20 + const checkLocalism = ref(false); // 方言选项卡
21 + const chooseLanguage = ref({ text: '普通话', val: '普通话' }); // 默认选中普通话
22 + /**
23 + * 切换视频语言回调
24 + * @param {*} type
25 + */
26 + const toggleLanguage = (type) => {
27 + if (type === 'mandarin') {
28 + checkMandarin.value = true;
29 + checkLocalism.value = false;
30 + } else {
31 + checkMandarin.value = false;
32 + checkLocalism.value = true;
33 + }
34 + // 修改默认语言绑定数据
35 + if (checkLocalism.value) {
36 + // tslint:disable-next-line:no-string-literal
37 + chooseLanguage.value = { text: columns.value[0]['text'], val: columns.value[0]['val'] }
38 + } else {
39 + chooseLanguage.value = { text: '普通话', val: '普通话' };
40 + }
41 + // 切换语言需要更新列表数据
42 + onReload()
43 + }
44 +
45 + // 方言选择项
46 + let columns = ref([
47 + { text: '所有方言', val: '所有方言' },
48 + ])
49 + //
50 + axios.get('/srv/?a=localism_list&book_id=' + $route.query.id)
51 + .then(res => {
52 + if (res.data.code === 1) {
53 + let arr = [];
54 + _.each(res.data.data, item => {
55 + arr.push({
56 + text: item,
57 + val: item
58 + })
59 + });
60 + columns.value = _.concat(columns.value, arr);
61 + } else {
62 + // tslint:disable-next-line: no-console
63 + console.warn(res);
64 + if (!res.data.show) return false;
65 + Toast({
66 + icon: 'close',
67 + message: res.data.msg
68 + });
69 + }
70 + })
71 + .catch(err => {
72 + // tslint:disable-next-line: no-console
73 + console.error(err);
74 + })
75 +
76 + const showPicker = ref(false);
77 +
78 + /**
79 + * 选择方言确认后回调
80 + * @param {*} param
81 + */
82 + const onConfirm = ({ selectedOptions }) => {
83 + showPicker.value = false;
84 + chooseLanguage.value = {
85 + text: selectedOptions[0].text,
86 + val: selectedOptions[0].val
87 + }
88 + onReload()
89 + };
90 +
91 + // 绑定页面数据
92 + const bookInfo = ref('');
93 + // tslint:disable-next-line: variable-name
94 + const prod_list = ref([]);
95 + const limit = ref(10)
96 + const offset = ref(0)
97 +
98 + // 处理书籍下作品列表
99 + const loading = ref(false);
100 + const finished = ref(false);
101 +
102 + // 因为不能让空图标提前出来的写法
103 + const finishedTextStatus = ref(false);
104 + const emptyStatus = ref(false);
105 +
106 + /**
107 + * 向下滚动查询数据
108 + */
109 + const onLoad = async () => {
110 + // 异步更新数据
111 + const { data, code } = await bookInfoAPI({ book_id: $route.query.id, kg_id: $route.query.kg_id ? $route.query.kg_id : 0, localism_type: chooseLanguage.value.text, limit: limit.value, offset: offset.value })
112 + if (code === 1) {
113 + bookInfo.value = data;
114 + flowFn(data.prod_list, prod_list, offset, loading, finished, finishedTextStatus, emptyStatus);
115 + }
116 + };
117 +
118 + /**
119 + * 重载刷新程序
120 + */
121 + const onReload = () => {
122 + offset.value = 0
123 + prod_list.value = []
124 + loading.value = true;
125 + finished.value = false;
126 + onLoad()
127 + }
128 +
129 + return {
130 + toggleLanguage,
131 + onLoad,
132 + columns,
133 + prod_list,
134 + finished,
135 + loading,
136 + bookInfo,
137 + showPicker,
138 + checkLocalism,
139 + checkMandarin,
140 + onConfirm,
141 + chooseLanguage,
142 + finishedTextStatus,
143 + emptyStatus,
144 + }
145 +}
1 +/*
2 + * @Date: 2022-06-12 23:54:24
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-13 00:50:29
5 + * @FilePath: /tswj/src/composables/variable.js
6 + * @Description: 文件描述
7 + */
8 +import { ref } from 'vue';
9 +
10 +export const loading = ref(false);
11 +export const finished = ref(false);
12 +export const limit = ref(5);
13 +export const offset = ref(0)
14 +export const finishedTextStatus = ref(false);
15 +export const emptyStatus = ref(false);
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-30 16:55:15
6 + * @FilePath: /tswj/src/constant.js
7 + * @Description:
8 + */
9 +// 金数据表单 - 家长端(废弃)
10 +export const JSJ_FORM_C = 'https://jsjs.onwall.cn/f/NAGn1D';
11 +// 金数据表单 - 家长端(普通话/方言)
12 +export const JSJ_FORM_MANDARIN = 'https://jsjs.onwall.cn/f/NAGn1D';
13 +export const JSJ_FORM_LOCALISM = 'https://jsjs.onwall.cn/f/HFdZIx';
14 +
15 +// 金数据表单 - 老师端
16 +export const JSJ_FORM_B = 'https://jsj.onwall.cn/f/g7D0MT';
17 +
18 +// 颜色变量
19 +export const styleColor = {
20 + baseColor: '#11D2B1',
21 + baseFontColor: '#FFFFFF'
22 +}
23 +
24 +/**
25 + * 客户端类型
26 + * @param CLIENT 家长端
27 + * @param BUSINESS 老师端
28 + */
29 +export const USER_ROLE = {
30 + CLIENT: 'C',
31 + BUSINESS: 'B',
32 +}
33 +
34 +/**
35 + * 用户身份
36 + * @param CHILDREN 儿童
37 + * @param VISIT 访客
38 + * @param KINDERGARTEN 幼儿园
39 + */
40 +export const USER_TYPE = {
41 + CHILDREN: 'C',
42 + VISIT: 'V',
43 + KINDERGARTEN: 'K',
44 +}
45 +
46 +// 默认视频封面
47 +export const DEFAULT_COVER = 'http://gyzs.onwall.cn/tswj_vidieo_cover.jpg'
48 +
49 +/**
50 + * 用户操作状态
51 + * @param PASS 正常
52 + * @param NON_VERIFIED 未实名认证
53 + * @param NON_DEFAULT_CHILD 没有默认儿童
54 + */
55 +export const USER_STATUS = {
56 + PASS: 1,
57 + NON_VERIFIED: -1,
58 + NON_DEFAULT_CHILD: -2
59 +}
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-12-31 17:32:10
6 + * @FilePath: /tswj/src/main.js
7 + * @Description:
8 + */
9 +import { createApp } from 'vue';
10 +import { Button, Image as VanImage, Col, Row, Icon, Form, Field, CellGroup, ConfigProvider, Toast, Uploader, Empty, Tab, Tabs, Overlay, NumberKeyboard, Lazyload, List, PullRefresh, Popup, Picker, Sticky, Stepper, Tag, Swipe, SwipeItem, Dialog, ActionSheet, Loading, Checkbox, Search, Notify } from 'vant';
11 +import router from './router';
12 +import App from './App.vue';
13 +// import axios from './utils/axios';
14 +import axios from '@/utils/axios';
15 +// import 'default-passive-events'; // 解决Chrome控制台non-passive event listener输出问题
16 +import { createPinia } from 'pinia';
17 +import 'vant/lib/index.css';
18 +
19 +const pinia = createPinia();
20 +const app = createApp(App);
21 +
22 +app.config.globalProperties.$http = axios; // 关键语句
23 +
24 +app.use(pinia).use(router).use(Button).use(VanImage).use(Col).use(Row).use(Icon).use(Form).use(Field).use(CellGroup).use(Toast).use(Uploader).use(Empty).use(Tab).use(Tabs).use(Overlay).use(NumberKeyboard).use(Lazyload).use(List).use(PullRefresh).use(Popup).use(Picker).use(Sticky).use(Stepper).use(Tag).use(Swipe).use(SwipeItem).use(Dialog).use(ActionSheet).use(Loading).use(Checkbox).use(Search).use(ConfigProvider).use(Notify);
25 +
26 +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
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +<template>
2 + <router-view></router-view>
3 +</template>
4 +
5 +<script>
6 +export default {
7 + data () {
8 + return {
9 +
10 + }
11 + },
12 + mounted () {
13 +
14 + },
15 + methods: {
16 +
17 + }
18 +}
19 +</script>
1 +<!DOCTYPE html>
2 +<html lang="en">
3 + <head>
4 + <meta charset="UTF-8" />
5 + <link rel="icon" href="/favicon.ico" />
6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 + <title>Vite App1</title>
8 + </head>
9 + <body>
10 + <div id="app"></div>
11 + <script type="module" src="./main.js"></script>
12 + </body>
13 +</html>
1 +import { createApp } from 'vue';
2 +import App from './App.vue';
3 +// import store, { key } from './store/index';
4 +import router from './router';
5 +
6 +createApp(App).use(router).mount('#app');
1 +import { createRouter, createWebHashHistory } from 'vue-router';
2 +
3 +const router = createRouter({
4 + history: createWebHashHistory('/index.html'),
5 + routes: [
6 + {
7 + path: '/',
8 + name: 'mono2',
9 + component: () => import('./views/index.vue'),
10 + },
11 + ],
12 +});
13 +
14 +export default router;
1 +<template>
2 + <div class="">456</div>
3 +</template>
4 +
5 +<script>
6 +export default {
7 + data () {
8 + return {
9 +
10 + }
11 + },
12 + mounted () {
13 +
14 + },
15 + methods: {
16 +
17 + }
18 +}
19 +</script>
20 +
21 +<style lang="less" scoped>
22 +
23 +</style>
1 +<template>
2 + <router-view></router-view>
3 +</template>
4 +
5 +<script>
6 +export default {
7 + data () {
8 + return {
9 +
10 + }
11 + },
12 + mounted () {
13 +
14 + },
15 + methods: {
16 +
17 + }
18 +}
19 +</script>
1 +<!DOCTYPE html>
2 +<html lang="en">
3 + <head>
4 + <meta charset="UTF-8" />
5 + <link rel="icon" href="/favicon.ico" />
6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 + <title>Vite App1</title>
8 + </head>
9 + <body>
10 + <div id="app"></div>
11 + <script type="module" src="./main.js"></script>
12 + </body>
13 +</html>
1 +import { createApp } from 'vue';
2 +import App from './App.vue';
3 +// import store, { key } from './store/index';
4 +import router from './router';
5 +
6 +createApp(App).use(router).mount('#app');
1 +import { createRouter, createWebHashHistory } from 'vue-router';
2 +
3 +const router = createRouter({
4 + history: createWebHashHistory('/index.html'),
5 + routes: [
6 + {
7 + path: '/',
8 + name: 'mono2',
9 + component: () => import('./views/index.vue'),
10 + },
11 + ],
12 +});
13 +
14 +export default router;
1 +<template>
2 + <div class="">123</div>
3 +</template>
4 +
5 +<script>
6 +export default {
7 + data () {
8 + return {
9 +
10 + }
11 + },
12 + mounted () {
13 +
14 + },
15 + methods: {
16 +
17 + }
18 +}
19 +</script>
20 +
21 +<style lang="less" scoped>
22 +
23 +</style>
1 +export default [{
2 + path: '/about',
3 + component: () => import('@/views/about.vue'),
4 + meta: {
5 + title: 'about'
6 + }
7 +}];
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 18:03:50
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-08 19:35:53
6 + * @FilePath: /tswj/src/router/methods/goToVideoDetail.ts
7 + * @Description:
8 + */
9 +// import { useRouter } from 'vue-router';
10 +import $router from '@/router';
11 +
12 +/**
13 + * 路由跳转视频详情页
14 + * @param prod_id 作品ID
15 + * @param perf_id 表演者ID
16 + * @param book_id 书籍ID
17 + * @param type 特殊标识,判断入口 为keepAlive使用
18 + */
19 +const fn = ({
20 + prod_id,
21 + perf_id,
22 + book_id,
23 + type,
24 +}: {
25 + prod_id: string;
26 + perf_id: string;
27 + book_id: string;
28 + type?: string;
29 +}): void => {
30 + $router.push({
31 + path: '/client/videoDetail',
32 + query: {
33 + prod_id,
34 + perf_id,
35 + book_id,
36 + type,
37 + },
38 + });
39 +};
40 +
41 +export default fn;
1 +const index = [{
2 + path: '/auth',
3 + name: '授权跳转页',
4 + component: () => import('@/views/auth.vue'),
5 + meta: {
6 + title: '微信授权'
7 + },
8 + children: []
9 +}]
10 +
11 +export default index;
1 +/*
2 + * @Date: 2024-04-07 10:14:17
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-04-07 10:28:36
5 + * @FilePath: /fxPark/src/router/routes/modules/fxPark/index.js
6 + * @Description: 文件描述
7 + */
8 +const index = [{
9 + path: '/fxPark',
10 + name: '“碳”寻复兴公园',
11 + component: () => import('@/views/fxPark/index.vue'),
12 + redirect: '',
13 + meta: {
14 + title: '“碳”寻复兴公园',
15 + },
16 + children: [],
17 +},]
18 +
19 +export default index;
1 +/*
2 + * @Date: 2022-06-15 17:09:03
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-29 20:09:00
5 + * @FilePath: /tswj/src/router/routes/modules/test/index.js
6 + * @Description: 文件描述
7 + */
8 +const index = [{
9 + path: '/html2canvas',
10 + name: 'html2canvas',
11 + component: () => import('@/views/html2canvas.vue'),
12 + redirect: '',
13 + meta: {
14 + icon: '',
15 + title: 'DOM转image',
16 + },
17 + children: [],
18 +}, {
19 + path: '/test-slot',
20 + name: 'test-slot',
21 + component: () => import('@/views/test/test-slot.vue'),
22 + redirect: '',
23 + meta: {
24 + icon: '',
25 + title: '测试slot插槽',
26 + },
27 + children: [],
28 +}, { // 配置404为动态路由中转页面
29 + path: '/:pathMatch(.*)*',
30 + redirect: '/404'
31 +}, {
32 + path: '/404',
33 + name: '404',
34 + component: () => import('@/views/test/404.vue'),
35 + meta: {
36 + icon: '',
37 + title: '404',
38 + },
39 + children: [],
40 +}];
41 +
42 +export default index;
1 +export default {
2 + defaultPageSize: 10,
3 +}
1 +/*
2 + * @Author: hookehuyr hookehuyr@gmail.com
3 + * @Date: 2022-05-26 10:08:06
4 + * @LastEditors: hookehuyr hookehuyr@gmail.com
5 + * @LastEditTime: 2022-06-02 22:50:53
6 + * @FilePath: /tswj/src/settings/designSetting.js
7 + * @Description:
8 + */
9 +import { ref } from 'vue';
10 +import { styleColor } from '@/constant.js';
11 +
12 +export const styleObject1 = ref({
13 + backgroundColor: styleColor.baseFontColor,
14 + color: styleColor.baseColor,
15 + borderColor: styleColor.baseColor
16 +})
17 +
18 +export const styleObject2 = ref({
19 + backgroundColor: styleColor.baseColor,
20 + color: styleColor.baseFontColor,
21 + borderColor: styleColor.baseColor
22 +})
23 +
24 +export const styleObject3 = ref({
25 + // backgroundColor: '#6D97D2',
26 + backgroundColor: '#F4675A',
27 + color: styleColor.baseFontColor,
28 + // borderColor: '#6D97D2'
29 + borderColor: '#F4675A'
30 +})
31 +
32 +export const styleObject4 = ref({
33 + backgroundColor: styleColor.baseFontColor,
34 + color: '#713610',
35 + borderColor: '#713610'
36 +})
37 +
38 +export const styleObject5 = ref({
39 + backgroundColor: styleColor.baseFontColor,
40 + color: '#FDD347',
41 + borderColor: '#FDD347'
42 +})
43 +
44 +export const styleObject6 = ref({
45 + backgroundColor: styleColor.baseFontColor,
46 + color: '#777777',
47 + borderColor: '#777777'
48 +})
49 +
50 +export const styleObject7 = ref({
51 + backgroundColor: styleColor.baseFontColor,
52 + color: '#0B3A72',
53 + borderColor: '#0B3A72'
54 +})
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: 2022-06-13 11:30:40
5 + * @FilePath: /tswj/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 + comment_num: 0,
20 + video_detail: {},
21 + scrollTop: 0,
22 + scrollTopCollection: 0,
23 + scrollTopLike: 0,
24 + scrollTopPerson: 0,
25 + keepPages: ['default'], // 很坑爹,空值全部都缓存
26 + };
27 + },
28 + getters: {
29 + getKeepPages () {
30 + return this.keepPages
31 + },
32 + // getTestStoreList () {
33 + // return testStore().list // 返回另一个store的值
34 + // }
35 + },
36 + actions: {
37 + changeState (state) {
38 + this.auth = state;
39 + },
40 + changeCommentNum (num) {
41 + this.comment_num = num;
42 + },
43 + changeVideoDetail (v) {
44 + this.video_detail = v;
45 + },
46 + changeScrollTop (v) {
47 + this.scrollTop = v;
48 + },
49 + changeScrollTopCollection (v) {
50 + this.scrollTopCollection = v;
51 + },
52 + changeScrollTopLike (v) {
53 + this.scrollTopLike = v;
54 + },
55 + changeScrollTopPerson (v) {
56 + this.scrollTopPerson = v;
57 + },
58 + changeKeepPages () { // 清空所有缓存,用一个不存在的值覆盖
59 + this.keepPages = ['default'];
60 + },
61 + keepThisPage () { // 新增缓存页
62 + const $router = useRouter();
63 + const page = $router.currentRoute.value.meta.name;
64 + this.keepPages.push(page);
65 + },
66 + removeThisPage () { // 删除缓存页
67 + const $router = useRouter();
68 + const page = $router.currentRoute.value.meta.name;
69 + _.remove(this.keepPages, item => item === page)
70 + }
71 + },
72 +});
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: 2024-01-02 18:02:31
6 + * @FilePath: /tswj/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: 'voice',
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 + if (config.method === 'post' && !strExist(['a=upload', 'upload.qiniup.com'], config.url)) {
32 + if (qs.stringify(config.data)) {
33 + config.data = qs.stringify(config.data)
34 + }
35 + }
36 + // 绑定默认请求头
37 + config.params = { ...config.params, timestamp }
38 + return config;
39 + },
40 + error => {
41 + // 请求错误处理
42 + return Promise.reject(error);
43 + });
44 +
45 +/**
46 + * @description 响应拦截器
47 + */
48 +axios.interceptors.response.use(
49 + response => {
50 + // 默认显示错误提示
51 + response.data.show = true;
52 + // 判断微信授权状态,进入页面时未授权需要授权跳转
53 + // C/B 授权拼接头特殊标识,openid_x
54 + let prefixAPI = router?.currentRoute.value.href?.indexOf('business') > 0 ? 'b' : 'c';
55 + if (response.data.code === 401) {
56 + // 特殊标识-带此标识报错不显示
57 + response.data.show = false;
58 + /**
59 + * 未授权跳转登录页
60 + * 带着上一个页面的信息, 授权完成后 返回当前页面
61 + */
62 + router.replace({ path: '/auth', query: { href: location.hash, prefixAPI } });
63 + }
64 + // 拦截B端未登录情况
65 + if (['老师请先登录!', '老师不存在!'].includes(response.data.msg)) { router.replace({ path: '/business/login' }); }
66 + return response;
67 + },
68 + error => {
69 + return Promise.reject(error);
70 + });
71 +
72 +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 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 +<template>
2 + <div class="">
3 + <iframe id="iframe" :src="src" style="height: 100vh" width="100%" frameborder="0"></iframe>
4 + </div>
5 +</template>
6 +
7 +<script setup>
8 +import { ref } from 'vue'
9 +import { useRoute, useRouter } from 'vue-router'
10 +const $route = useRoute();
11 +
12 +const src = ref($route.query.href)
13 +</script>
14 +
15 +<script>
16 +import mixin from 'common/mixin';
17 +
18 +export default {
19 + mixins: [mixin.init],
20 + data () {
21 + return {
22 + myIframe: null
23 + }
24 + },
25 + mounted () {
26 +
27 + },
28 + methods: {
29 + onLoad(frame) {
30 + this.myIframe = frame.contentWindow
31 + }
32 + }
33 +}
34 +</script>
35 +
36 +<style lang="less" scoped>
37 +
38 +</style>
1 +<template>
2 + <div class="">router test</div>
3 +</template>
4 +
5 +<script setup>
6 +</script>
7 +
8 +<style lang="less" scoped>
9 +</style>
1 +<template>
2 + <div />
3 +</template>
4 +
5 +<script setup>
6 +import { onMounted } from 'vue'
7 +import { useRoute } from 'vue-router'
8 +
9 +const $route = useRoute();
10 +
11 +onMounted(() => {
12 + // php需要先跳转链接获取openid
13 + /**
14 + * encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。
15 + * 该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
16 + * 其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
17 + */
18 + let raw_url = encodeURIComponent(location.origin + location.pathname + $route.query.href); // 未授权的地址
19 + // TAG: 开发环境测试数据
20 + const short_url = `/srv/?f=voice&a=openid_${$route.query.prefixAPI}&res=${raw_url}`;
21 + location.href = import.meta.env.DEV
22 + ? `${short_url}&input_openid=${import.meta.env.VITE_OPENID}`
23 + : `${short_url}`;
24 +})
25 +</script>
1 +<!--
2 + * @Date: 2022-06-29 15:57:45
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2022-06-29 22:04:25
5 + * @FilePath: /tswj/src/views/children-test.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="">test</div>
10 +</template>
11 +
12 +<script setup>
13 +</script>
14 +
15 +<style lang="less" scoped>
16 +</style>
1 +<!--
2 + * @Date: 2024-04-07 10:15:55
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-04-07 10:19:13
5 + * @FilePath: /fxPark/src/views/fxPark/index.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="">123</div>
10 +</template>
11 +
12 +<script setup>
13 +import { ref } from 'vue'
14 +import { useRoute, useRouter } from 'vue-router'
15 +
16 +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js'
17 +//import { } from '@/utils/generateModules.js'
18 +//import { } from '@/utils/generateIcons.js'
19 +//import { } from '@/composables'
20 +const $route = useRoute();
21 +const $router = useRouter();
22 +useTitle($route.meta.title);
23 +
24 +</script>
25 +
26 +<style lang="less" scoped>
27 +
28 +</style>
1 +<template>
2 + <div>
3 + <!-- 生成图片后隐藏原始结构 -->
4 + <div v-if="flag" ref="canvasRef" style="width: 200px; height: 200px;">
5 + <img :src="logo_image" alt="">
6 + </div>
7 + <div v-if="imgUrl">
8 + <img :src="imgUrl" alt="" crossOrigin="anonymous" style="width: 300px; height: 300px;">
9 + </div>
10 + <div>
11 + <div @click="createImage">合成图片</div>
12 + <div @click="btn">child</div>
13 + </div>
14 + <router-view />
15 + </div>
16 +</template>
17 +
18 +<script setup>
19 +
20 +import logo_image from '@images/logo@3x.png'
21 +</script>
22 +
23 +<script>
24 +import mixin from 'common/mixin';
25 +import html2canvas from "html2canvas";
26 +
27 +export default {
28 + mixins: [mixin.init],
29 + data() {
30 + return {
31 + imgUrl: "",
32 + flag: true
33 + }
34 + },
35 + mounted() {
36 +
37 + },
38 + methods: {
39 + createImage() {
40 + this.$nextTick(() => {
41 + // 获取要生成图片的 DOM 元素
42 + let canvasDom = this.$refs.canvasRef;
43 + const options = {
44 + // backgroundColor: '#ffffff',
45 + // canvas: canvas,
46 + useCORS: true,//配置允许跨域
47 + // scale:1,
48 + // windowWidth: document.body.scrollWidth,
49 + // windowHeight: document.body.scrollHeight,
50 + // x: 0,
51 + // y: window.pageYOffset,
52 + // allowTaint: true,
53 + // background: "#ffffff", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的
54 + dpi: 300 // 处理模糊问题
55 + };
56 + // console.log("获取指定的宽高", width, height, canvas);
57 + html2canvas(canvasDom, options)
58 + .then(canvas => {
59 + try {
60 + // 生成图片地址
61 + this.imgUrl = canvas.toDataURL("image/png");
62 + // console.log("canvas.toDataURL('image/png')", this.imgUrl);
63 + this.flag = false;
64 + } catch (e) {
65 + alert("图片跨域,保存失败");
66 + }
67 + })
68 + .catch(error => {
69 + console.error("绘制失败");
70 + console.error(error);
71 + });
72 + });
73 + },
74 + btn () {
75 + this.$router.push({
76 + path: '/image/children',
77 + query: {
78 + abc: 1
79 + }
80 + })
81 + }
82 + }
83 +}
84 +</script>
85 +
86 +<style lang="less" scoped>
87 +.m-html2canvas {
88 + display: flex;
89 +}
90 +
91 +.m-canvasRef {
92 + width: 500px;
93 + height: 500px;
94 + /* border: 1px solid red; */
95 + /* box-sizing: border-box; */
96 + box-shadow: 10px 10px 5px #888888;
97 +}
98 +
99 +.m-imageList {
100 + width: 500px;
101 + height: calc(500px / 3);
102 +}
103 +
104 +img {
105 + width: 100%;
106 + height: 100%;
107 + float: left;
108 +}
109 +
110 +.m-showImage {
111 + margin-left: 50px;
112 + background: red;
113 + width: 500px;
114 + height: 500px;
115 +}
116 +
117 +.m-btn {
118 + margin-left: 50px;
119 +}
120 +</style>
1 +<template>
2 + <div />
3 +</template>
4 +
5 +<script setup>
6 +</script>
7 +
8 +<style lang="less" scoped>
9 +</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}>
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.