Compare commits

..

No commits in common. "master" and "develop" have entirely different histories.

316 changed files with 2699 additions and 26343 deletions

View File

@ -121,10 +121,6 @@
"newDetail": true, "newDetail": true,
"newsDetail": true, "newsDetail": true,
"useNewsList": true, "useNewsList": true,
"newsList": true, "newsList": true
"useLogin": true,
"useWxInfo": true,
"useUniversityInfo": true,
"universityBaseInfo": true
} }
} }

View File

@ -58,9 +58,5 @@
"explorer.fileNesting.patterns": { "explorer.fileNesting.patterns": {
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc", "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc",
".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*,.eslintrc-auto-import.json,.editorconfig,.commitlint.cjs" ".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*,.eslintrc-auto-import.json,.editorconfig,.commitlint.cjs"
}, }
"vetur.validation.template": false,
"vetur.validation.script": false,
"vetur.validation.style": false,
"vetur.experimental.templateInterpolationService": true
} }

View File

@ -1,6 +1,14 @@
# 六志愿 # 六志愿
六纬志愿小程序 六维志愿小程序
## 平台兼容性
| H5 | IOS | 安卓 | 微信小程序 | 字节小程序 | 快手小程序 | 支付宝小程序 | 钉钉小程序 | 百度小程序 |
| --- | --- | ---- | ---------- | ---------- | ---------- | ------------ | ---------- | ---------- |
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
注意每种 `UI框架` 支持的平台有所不同,详情请看各 `UI框架` 的官网,也可以看 `unibest` 文档。
## ⚙️ 环境 ## ⚙️ 环境
@ -27,4 +35,4 @@
- web平台 `pnpm build:h5`,打包后的文件在 `dist/build/h5`可以放到web服务器如nginx运行。如果最终不是放在根目录可以在 `manifest.config.ts` 文件的 `h5.router.base` 属性进行修改。 - web平台 `pnpm build:h5`,打包后的文件在 `dist/build/h5`可以放到web服务器如nginx运行。如果最终不是放在根目录可以在 `manifest.config.ts` 文件的 `h5.router.base` 属性进行修改。
- weixin平台`pnpm build:mp-weixin`, 打包后的文件在 `dist/build/mp-weixin`,然后通过微信开发者工具导入,并点击右上角的“上传”按钮进行上传。 - weixin平台`pnpm build:mp-weixin`, 打包后的文件在 `dist/build/mp-weixin`,然后通过微信开发者工具导入,并点击右上角的“上传”按钮进行上传。
- APP平台`pnpm build:app`, 然后打开 `HBuilderX`,导入刚刚生成的`dist/build/app` 文件夹,选择发行 - APP云打包 - APP平台`pnpm build:app`, 然后打开 `HBuilderX`,导入刚刚生成的`dist/build/app` 文件夹,选择发行 - APP云打包

4
env/.env vendored
View File

@ -1,8 +1,8 @@
VITE_APP_TITLE = '六志愿' VITE_APP_TITLE = '六志愿'
VITE_APP_PORT = 9000 VITE_APP_PORT = 9000
VITE_UNI_APPID = 'H57F2ACE4' VITE_UNI_APPID = 'H57F2ACE4'
VITE_WX_APPID = 'wx05e75004e657527c' VITE_WX_APPID = 'wxa2abb91f64032a2b'
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base # h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE= VITE_APP_PUBLIC_BASE=

View File

@ -79,7 +79,8 @@ export default defineManifestConfig({
}, },
}, },
}, },
/* 快应用特有相关 */
quickapp: {},
/* 小程序特有相关 */ /* 小程序特有相关 */
'mp-weixin': { 'mp-weixin': {
appid: VITE_WX_APPID, appid: VITE_WX_APPID,
@ -90,11 +91,18 @@ export default defineManifestConfig({
optimization: { optimization: {
subPackages: true, subPackages: true,
}, },
requiredPrivateInfos: ['getLocation'],
// requiredBackgroundModes: ['audio'],
lazyCodeLoading: 'requiredComponents',
// __usePrivacyCheck__: true, // __usePrivacyCheck__: true,
}, },
'mp-alipay': {
usingComponents: true,
styleIsolation: 'shared',
},
'mp-baidu': {
usingComponents: true,
},
'mp-toutiao': {
usingComponents: true,
},
uniStatistics: { uniStatistics: {
enable: false, enable: false,
}, },

View File

@ -3,7 +3,21 @@
"type": "commonjs", "type": "commonjs",
"version": "2.5.5", "version": "2.5.5",
"description": "unibest - 最好的 uniapp 开发模板", "description": "unibest - 最好的 uniapp 开发模板",
"author": {
"name": "feige996",
"zhName": "菲鸽",
"email": "1020103647@qq.com",
"github": "https://github.com/feige996",
"gitee": "https://gitee.com/feige996"
},
"license": "MIT", "license": "MIT",
"repository": "https://github.com/feige996/unibest",
"repository-gitee": "https://gitee.com/feige996/unibest",
"repository-deprecated": "https://github.com/codercup/unibest",
"bugs": {
"url": "https://github.com/feige996/unibest/issues"
},
"homepage": "https://feige996.github.io/unibest/",
"engines": { "engines": {
"node": ">=18", "node": ">=18",
"pnpm": ">=7.30" "pnpm": ">=7.30"
@ -74,10 +88,20 @@
}, },
"dependencies": { "dependencies": {
"@dcloudio/uni-app": "3.0.0-4020920240930001", "@dcloudio/uni-app": "3.0.0-4020920240930001",
"@dcloudio/uni-app-harmony": "3.0.0-4020920240930001",
"@dcloudio/uni-app-plus": "3.0.0-4020920240930001", "@dcloudio/uni-app-plus": "3.0.0-4020920240930001",
"@dcloudio/uni-components": "3.0.0-4020920240930001", "@dcloudio/uni-components": "3.0.0-4020920240930001",
"@dcloudio/uni-h5": "3.0.0-4020920240930001", "@dcloudio/uni-h5": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-alipay": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-baidu": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-jd": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-lark": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-qq": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-toutiao": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-weixin": "3.0.0-4020920240930001", "@dcloudio/uni-mp-weixin": "3.0.0-4020920240930001",
"@dcloudio/uni-mp-xhs": "3.0.0-4020920240930001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4020920240930001",
"@tanstack/vue-query": "^5.62.16", "@tanstack/vue-query": "^5.62.16",
"abortcontroller-polyfill": "^1.7.8", "abortcontroller-polyfill": "^1.7.8",
"dayjs": "1.11.10", "dayjs": "1.11.10",
@ -86,7 +110,8 @@
"pinyin-pro": "^3.26.0", "pinyin-pro": "^3.26.0",
"qs": "6.5.3", "qs": "6.5.3",
"vue": "3.4.21", "vue": "3.4.21",
"wot-design-uni": "^1.4.0" "wot-design-uni": "^1.4.0",
"z-paging": "^2.8.4"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^18.6.1", "@commitlint/cli": "^18.6.1",
@ -146,8 +171,5 @@
"vite": "5.2.8", "vite": "5.2.8",
"vite-plugin-restart": "^0.4.2", "vite-plugin-restart": "^0.4.2",
"vue-tsc": "^1.8.27" "vue-tsc": "^1.8.27"
},
"minimize": {
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"
} }
} }

View File

@ -3,7 +3,7 @@ import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'
export default defineUniPages({ export default defineUniPages({
globalStyle: { globalStyle: {
navigationBarTextStyle: 'black', navigationBarTextStyle: 'black',
navigationBarTitleText: '六纬升学', navigationBarTitleText: '六纬志愿',
navigationBarBackgroundColor: '#fff', navigationBarBackgroundColor: '#fff',
backgroundColor: '#F8F8F8', backgroundColor: '#F8F8F8',
}, },
@ -52,11 +52,20 @@ export default defineUniPages({
}, },
], ],
}, },
pages: [], pages: [
{
path: 'pages/home/index/index',
type: 'home',
style: {
navigationBarTitleText: '六维志愿',
navigationStyle: 'custom',
},
},
],
preloadRule: { preloadRule: {
'pages/home/index/index': { 'pages/home/index/index': {
network: 'all', network: 'all',
packages: ['pages-evaluation-sub', 'aiService-sub'], packages: ['__APP__'],
}, },
}, },
condition: { condition: {
@ -69,12 +78,4 @@ export default defineUniPages({
}, },
], ],
}, },
permission: {
'scope.userLocation': {
desc: '你的位置信息将用于小程序位置接口的效果展示',
},
'scope.record': {
desc: '你的录音功能将用于小程序录音接口的效果展示',
},
},
}) })

View File

@ -14,6 +14,9 @@ importers:
'@dcloudio/uni-app': '@dcloudio/uni-app':
specifier: 3.0.0-4020920240930001 specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(@dcloudio/types@3.4.14)(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2)) version: 3.0.0-4020920240930001(@dcloudio/types@3.4.14)(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-app-harmony':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-app-plus': '@dcloudio/uni-app-plus':
specifier: 3.0.0-4020920240930001 specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2)) version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2))
@ -23,9 +26,36 @@ importers:
'@dcloudio/uni-h5': '@dcloudio/uni-h5':
specifier: 3.0.0-4020920240930001 specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2)) version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-alipay':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-baidu':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-jd':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-kuaishou':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-lark':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-qq':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-toutiao':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-weixin': '@dcloudio/uni-mp-weixin':
specifier: 3.0.0-4020920240930001 specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2)) version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-xhs':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-quickapp-webview':
specifier: 3.0.0-4020920240930001
version: 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@tanstack/vue-query': '@tanstack/vue-query':
specifier: ^5.62.16 specifier: ^5.62.16
version: 5.62.16(vue@3.4.21(typescript@5.7.2)) version: 5.62.16(vue@3.4.21(typescript@5.7.2))
@ -53,6 +83,9 @@ importers:
wot-design-uni: wot-design-uni:
specifier: ^1.4.0 specifier: ^1.4.0
version: 1.4.0(vue@3.4.21(typescript@5.7.2)) version: 1.4.0(vue@3.4.21(typescript@5.7.2))
z-paging:
specifier: ^2.8.4
version: 2.8.4
devDependencies: devDependencies:
'@commitlint/cli': '@commitlint/cli':
specifier: ^18.6.1 specifier: ^18.6.1
@ -926,6 +959,9 @@ packages:
'@dcloudio/types@3.4.14': '@dcloudio/types@3.4.14':
resolution: {integrity: sha512-VolQeZfTh8pQFsr2IlfIVX93blfvGTuBoJuZUc7iWOqtHV8gDrq6fXLhzsVlgZyuhhRZLOxlo33rkEqnY+ucAw==} resolution: {integrity: sha512-VolQeZfTh8pQFsr2IlfIVX93blfvGTuBoJuZUc7iWOqtHV8gDrq6fXLhzsVlgZyuhhRZLOxlo33rkEqnY+ucAw==}
'@dcloudio/uni-app-harmony@3.0.0-4020920240930001':
resolution: {integrity: sha512-YHAJSX1DCaLTr7MDc4mOJ/0JfECn2YS9b5EvMyl5WUy8CIDSupOxFpygnpcUHTlyExdQOivp35TerYfLa0BDew==}
'@dcloudio/uni-app-plus@3.0.0-4020920240930001': '@dcloudio/uni-app-plus@3.0.0-4020920240930001':
resolution: {integrity: sha512-0MQx5lAZ+y8E5/jjkjSfpyZvhUNaqRZbcD7u+cragHjE17PndQo+h7wmyGYgzGQYmuikiD8CX+o+NtTo4Z/TiA==} resolution: {integrity: sha512-0MQx5lAZ+y8E5/jjkjSfpyZvhUNaqRZbcD7u+cragHjE17PndQo+h7wmyGYgzGQYmuikiD8CX+o+NtTo4Z/TiA==}
@ -971,9 +1007,30 @@ packages:
'@dcloudio/uni-i18n@3.0.0-4020920240930001': '@dcloudio/uni-i18n@3.0.0-4020920240930001':
resolution: {integrity: sha512-ltKiciML0ptWRytvbFt1dd4YglEjh4fsUc0D/dY+y5YKNxK7h/V2HT3qkQtP05T1kjEput4KrWNn23fczO3YFg==} resolution: {integrity: sha512-ltKiciML0ptWRytvbFt1dd4YglEjh4fsUc0D/dY+y5YKNxK7h/V2HT3qkQtP05T1kjEput4KrWNn23fczO3YFg==}
'@dcloudio/uni-mp-alipay@3.0.0-4020920240930001':
resolution: {integrity: sha512-52XHUPmZixd8TZQ9BKrme139Uq5wfYy6DjMdeSQRJ9DJRtVe4WsWxgJ6DoKdPJLtiG1OSljmZOjU5V35WuhsWA==}
'@dcloudio/uni-mp-baidu@3.0.0-4020920240930001':
resolution: {integrity: sha512-2MyZYMQdiU3Xog/f/HdRZLoQk5uVPICfysfnxirjdd4O/umhsRkdwMjq092mmmmkSEdTQIlwiQGK+8d3snLofQ==}
'@dcloudio/uni-mp-compiler@3.0.0-4020920240930001': '@dcloudio/uni-mp-compiler@3.0.0-4020920240930001':
resolution: {integrity: sha512-ngbbKTDWCzE8j3Xf5ezBRdV4NiXPTIS9GylIvL1quJVjcWEwbfoSvROTCBxLv+i8unu5+UbtRa1+KdsrUKtFOQ==} resolution: {integrity: sha512-ngbbKTDWCzE8j3Xf5ezBRdV4NiXPTIS9GylIvL1quJVjcWEwbfoSvROTCBxLv+i8unu5+UbtRa1+KdsrUKtFOQ==}
'@dcloudio/uni-mp-jd@3.0.0-4020920240930001':
resolution: {integrity: sha512-L9WncaToo27wZcmLbFFZGkIo7iBKEk53bOy6fntUhECPJe0076q2KUnWyFF8Mq9euOz9KESazBo8u6PyoZkwuA==}
'@dcloudio/uni-mp-kuaishou@3.0.0-4020920240930001':
resolution: {integrity: sha512-y8xmnGZX1cjgx5A3V0g43+0LrNrafb6J7NjdYjjzvlelTalAICofMMxOB/TMY4kIvAcAO8pTrvJ8gsxQTj3Law==}
'@dcloudio/uni-mp-lark@3.0.0-4020920240930001':
resolution: {integrity: sha512-6siEc/tbZLGh3DDZin+3hEWtncUs+Nk6ttEsZgIyNwX+SPTf2pFDj23dZAq3h/Lc89EvIgSjyFOuKJ1yivrLdg==}
'@dcloudio/uni-mp-qq@3.0.0-4020920240930001':
resolution: {integrity: sha512-TD4HUZiXa/3pjhRFJo0uMygMCZZk09pbzmR9FPU/kMQk3pxfgrMrMAY3To9boMULKNJenT1pIVy/QxEXiTyH1Q==}
'@dcloudio/uni-mp-toutiao@3.0.0-4020920240930001':
resolution: {integrity: sha512-eo0a+cwY9mgs/DxMplKpqTyIJmJUJpPr/hT2DPsqnPA8OXAbIKbhJBZbwC2z/EJDduOhzNpCkliHhv4Ahks2vQ==}
'@dcloudio/uni-mp-vite@3.0.0-4020920240930001': '@dcloudio/uni-mp-vite@3.0.0-4020920240930001':
resolution: {integrity: sha512-awTd9X+yZ67shjBVxZ02bJ5ImU4/mODprz2lmYHA19RjjhzfNrDsIYBWAtfWMZ2WP5z1OL7WnZNiwPHWiuh9mQ==} resolution: {integrity: sha512-awTd9X+yZ67shjBVxZ02bJ5ImU4/mODprz2lmYHA19RjjhzfNrDsIYBWAtfWMZ2WP5z1OL7WnZNiwPHWiuh9mQ==}
@ -983,12 +1040,18 @@ packages:
'@dcloudio/uni-mp-weixin@3.0.0-4020920240930001': '@dcloudio/uni-mp-weixin@3.0.0-4020920240930001':
resolution: {integrity: sha512-ip/OtXFLlnkztxOXMXPsjktp9rSo+c1OxlCase32xBVn+Jt0GyIFiA6Js9icz5uwIXtt14jWi4mRXfjncUV7QA==} resolution: {integrity: sha512-ip/OtXFLlnkztxOXMXPsjktp9rSo+c1OxlCase32xBVn+Jt0GyIFiA6Js9icz5uwIXtt14jWi4mRXfjncUV7QA==}
'@dcloudio/uni-mp-xhs@3.0.0-4020920240930001':
resolution: {integrity: sha512-4+3qaWsqfbIentMmFCSUdf7ngpQXqt/2k/TqT6+6985tfzXUKoi0YrGwnZbf5e6b6RVDMuLMsokm2z7kfSXdXw==}
'@dcloudio/uni-nvue-styler@3.0.0-4020920240930001': '@dcloudio/uni-nvue-styler@3.0.0-4020920240930001':
resolution: {integrity: sha512-bmMJKf4FoSQy6PfTfojOeskcc1239V38B3dtG/zFFll7pzBAVi68xYvgF9KgYDBkztTM0PmAukyVNRl1VAFOww==} resolution: {integrity: sha512-bmMJKf4FoSQy6PfTfojOeskcc1239V38B3dtG/zFFll7pzBAVi68xYvgF9KgYDBkztTM0PmAukyVNRl1VAFOww==}
'@dcloudio/uni-push@3.0.0-4020920240930001': '@dcloudio/uni-push@3.0.0-4020920240930001':
resolution: {integrity: sha512-AL03ysBAi8d/VBQ0/UG0EqcC0Fiohb/pkzR88kNLxIn3VouMje3pw3h++zH5Oa/DppP4M47TTMDoGlcAqBpqrg==} resolution: {integrity: sha512-AL03ysBAi8d/VBQ0/UG0EqcC0Fiohb/pkzR88kNLxIn3VouMje3pw3h++zH5Oa/DppP4M47TTMDoGlcAqBpqrg==}
'@dcloudio/uni-quickapp-webview@3.0.0-4020920240930001':
resolution: {integrity: sha512-P0G/u/DSJyEw+Txnpxbg8fMOJE1nNcRLwdTCWe43KefPBQRiRVo4n/tWWxBgV+tnbryqolPivkxLsLDfi358+w==}
'@dcloudio/uni-shared@3.0.0-4020920240930001': '@dcloudio/uni-shared@3.0.0-4020920240930001':
resolution: {integrity: sha512-8EEQAaY+Y9BRCZIqpoaI7ciQFTO/sggxPO1kJNVAkxvJs/GVb4mawPlW9UNsMiWEqRvOJlV7KldCu6eMYlyyfg==} resolution: {integrity: sha512-8EEQAaY+Y9BRCZIqpoaI7ciQFTO/sggxPO1kJNVAkxvJs/GVb4mawPlW9UNsMiWEqRvOJlV7KldCu6eMYlyyfg==}
@ -6590,6 +6653,10 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
z-paging@2.8.4:
resolution: {integrity: sha512-967aWGPZsC9siwIoWtXH6L+9gCoKe29jZtW+AMD9NSfsfymPZjBBYu7owT/siUQyCaaNJ7uUbpAet+YgpMn0xA==}
engines: {HBuilderX: ^3.0.7}
snapshots: snapshots:
'@ampproject/remapping@2.3.0': '@ampproject/remapping@2.3.0':
@ -7495,6 +7562,23 @@ snapshots:
'@dcloudio/types@3.4.14': {} '@dcloudio/types@3.4.14': {}
'@dcloudio/uni-app-harmony@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-app-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2))
debug: 4.3.7
fs-extra: 10.1.0
licia: 1.46.0
postcss-selector-parser: 6.1.2
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vite
- vue
'@dcloudio/uni-app-plus@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2))': '@dcloudio/uni-app-plus@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vite@5.2.8(@types/node@20.17.9)(sass@1.77.8)(terser@5.36.0))(vue@3.4.21(typescript@5.7.2))':
dependencies: dependencies:
'@dcloudio/uni-app-uts': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2)) '@dcloudio/uni-app-uts': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
@ -7760,6 +7844,50 @@ snapshots:
'@dcloudio/uni-i18n@3.0.0-4020920240930001': {} '@dcloudio/uni-i18n@3.0.0-4020920240930001': {}
'@dcloudio/uni-mp-alipay@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-mp-baidu@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-compiler': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-mp-weixin': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
jimp: 0.10.3
licia: 1.46.0
qrcode-reader: 1.0.4
qrcode-terminal: 0.12.0
ws: 8.18.0
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- bufferutil
- debug
- postcss
- rollup
- supports-color
- ts-node
- utf-8-validate
- vue
'@dcloudio/uni-mp-compiler@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))': '@dcloudio/uni-mp-compiler@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies: dependencies:
'@babel/generator': 7.26.2 '@babel/generator': 7.26.2
@ -7780,6 +7908,99 @@ snapshots:
- ts-node - ts-node
- vue - vue
'@dcloudio/uni-mp-jd@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-compiler': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-mp-kuaishou@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-compiler': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-mp-weixin': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- bufferutil
- debug
- postcss
- rollup
- supports-color
- ts-node
- utf-8-validate
- vue
'@dcloudio/uni-mp-lark@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-compiler': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-toutiao': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-mp-qq@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/shared': 3.4.21
fs-extra: 10.1.0
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-mp-toutiao@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-compiler': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-mp-vite@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))': '@dcloudio/uni-mp-vite@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies: dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2)) '@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
@ -7828,6 +8049,23 @@ snapshots:
- utf-8-validate - utf-8-validate
- vue - vue
'@dcloudio/uni-mp-xhs@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-compiler': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-nvue-styler@3.0.0-4020920240930001': '@dcloudio/uni-nvue-styler@3.0.0-4020920240930001':
dependencies: dependencies:
parse-css-font: 4.0.0 parse-css-font: 4.0.0
@ -7845,6 +8083,22 @@ snapshots:
- ts-node - ts-node
- vue - vue
'@dcloudio/uni-quickapp-webview@3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))':
dependencies:
'@dcloudio/uni-cli-shared': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vite': 3.0.0-4020920240930001(postcss@8.4.49)(rollup@4.28.0)(vue@3.4.21(typescript@5.7.2))
'@dcloudio/uni-mp-vue': 3.0.0-4020920240930001
'@dcloudio/uni-shared': 3.0.0-4020920240930001
'@vue/shared': 3.4.21
transitivePeerDependencies:
- '@nuxt/kit'
- '@vueuse/core'
- postcss
- rollup
- supports-color
- ts-node
- vue
'@dcloudio/uni-shared@3.0.0-4020920240930001': '@dcloudio/uni-shared@3.0.0-4020920240930001':
dependencies: dependencies:
'@vue/shared': 3.4.21 '@vue/shared': 3.4.21
@ -14557,3 +14811,5 @@ snapshots:
yargs-parser: 21.1.1 yargs-parser: 21.1.1
yocto-queue@0.1.0: {} yocto-queue@0.1.0: {}
z-paging@2.8.4: {}

View File

@ -1,25 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationBarTitleText: '六纬AI小助手',
},
}
</route>
<template>
<view class="w-full h-screen">
<image
src="https://api-static-zhiy.oss-cn-shanghai.aliyuncs.com/images/shengxue_aibg.png"
mode="widthFix"
class="w-full"
@click="navigateToAi"
/>
</view>
</template>
<script setup lang="ts">
const navigateToAi = () => {
uni.navigateTo({ url: '/aiService-sub/index/newAi' })
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,46 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationBarTitleText: '六纬AI小助手',
},
needLogin: true,
}
</route>
<template>
<web-view :src="url" @message="handleChildMessage" :update-title="false" />
</template>
<script setup lang="ts">
import { useUserStore } from '@/store'
import { getAssistant } from '@/service/index/api'
const userStore = useUserStore()
//chat.ycymedu.com
//chatv2.ycymedu.com
const url = ref(``)
const handleChildMessage = (event) => {
console.log('子应用传递的消息', event)
}
onLoad((options) => {
getAssistant().then((res) => {
if (res.code === 200) {
const data = res.result as unknown as string
url.value = `${data}?userId=${userStore.userInfo.estimatedAchievement.wxId}&subjectGroup=${userStore.userInfo.estimatedAchievement.subjectGroup}&expectedScore=${userStore.userInfo.estimatedAchievement.expectedScore}&provinceName=${userStore.userInfo.estimatedAchievement.provinceName}&locationCode=${userStore.userInfo.estimatedAchievement.provinceCode}&token=${userStore.userInfo.token}&timestamp=${new Date().getTime()}`
}
if (options.id) {
url.value += `&reportId=${options.id}`
}
if (options.type) {
url.value += `&reportType=${options.type}`
}
if (options.fileId) {
url.value += `&fileId=${options.fileId}`
}
})
})
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,106 @@
<template>
<wd-action-sheet
v-model="localShow"
title="筛选"
@close="close"
custom-header-class="text-[36rpx]! text-[#303030]! font-medium!"
>
<view class="flex flex-col sheet-body-border">
<view class="flex">
<view class="w-[176rpx] h-initial bg-[#F7F8FA] flex flex-col items-center">
<view
:class="`flex items-center justify-center h-[104rpx] w-full ${item.id === currentMenu ? 'active' : ''}`"
v-for="item in menus"
:key="item.id"
@click="changeMenu(item)"
>
{{ item.name }}
</view>
</view>
<view class="flex-1 px-[32rpx] py-[24rpx] h-[50vh] overflow-y-auto">
<Phase v-show="currentMenu === 1" />
<Region v-show="currentMenu === 2" />
<UniType v-show="currentMenu === 3" />
<Nature v-show="currentMenu === 4" />
</view>
</view>
<view class="pt-[32rpx] px-[32rpx] wei-xin-pt box-shadow">
<!-- <view class="flex items-center flex-wrap gap-[24rpx]">
<view
class="px-[20rpx] py-[12rpx] bg-[#f8f8f8] rounded-[8rpx]"
v-for="item in 4"
:key="item"
>
<text class="text-[#303030] text-[24rpx] font-medium mr-[16rpx]">中外合作</text>
<wd-icon name="close-outline" size="24rpx" color="#cbcbcb"></wd-icon>
</view>
</view> -->
<view class="flex items-center">
<wd-button
plain
custom-class="border-[#f5f5f5]! px-[134rpx]! py-[26rpx]! bg-[#f5f5f5]! rounded-[8rpx]! text-[#1580FF]! text-[32rpx]! font-normal! mr-[22rpx]"
>
清空
</wd-button>
<wd-button
custom-class="border-[#1580FF]! px-[134rpx]! py-[26rpx]! bg-[#1580FF]! rounded-[8rpx]! text-[#fff]! text-[32rpx]! font-normal!"
>
查看结果
</wd-button>
</view>
</view>
</view>
</wd-action-sheet>
</template>
<script lang="ts" setup>
import Phase from './Phase.vue'
import Region from './Region.vue'
import UniType from './UniType.vue'
import Nature from './Nature.vue'
const props = defineProps({
show: {
type: Boolean,
default: false,
},
})
const localShow = computed(() => props.show)
const emit = defineEmits(['update:show'])
const close = () => {
emit('update:show', false)
}
const menus = [
{ id: 1, name: '阶段' },
{ id: 2, name: '院校省份' },
{ id: 3, name: '院校类型' },
{ id: 4, name: '办学性质' },
]
const currentMenu = ref(1)
const changeMenu = (item: { id: number; name: string }) => {
currentMenu.value = item.id
}
</script>
<style lang="scss" scoped>
/* #ifdef H5 */
.wei-xin-pt {
padding-bottom: 40rpx;
}
/* #endif */
.box-shadow {
box-shadow: 0rpx -8rpx 8rpx 0rpx rgba(225, 225, 225, 0.2);
}
.active {
background-color: #fff;
}
.sheet-body-border {
border-top: 2rpx solid #f5f5f5;
}
</style>

View File

@ -0,0 +1,21 @@
<template>
<CheckGroup
:list="infoList"
@change="handleChange"
:default-value="defaultInfo"
value-key="id"
label-key="name"
/>
</template>
<script lang="ts" setup>
import CheckGroup from '@/components/checkGroup/CheckGroup.vue'
import { useNatureList } from '@/hooks/useFilterSchool'
const { natureList: infoList } = useNatureList()
const defaultInfo = ref<string[]>([])
const handleChange = (val: string[]) => {
console.log(val)
}
</script>

View File

@ -0,0 +1,66 @@
<template>
<view class="">
<wd-radio-group
v-model="choosePhase"
cell
inline
custom-class="flex flex-wrap gap-[32rpx] justify-items-center"
checked-color="#1580FF"
>
<wd-radio
v-for="item in phaseList"
:key="item.code"
:value="item.code"
shape="button"
custom-class="w-[240rpx]! h-[60rpx] p-0! mr-0! radio-item-border"
>
{{ item.name }}
</wd-radio>
</wd-radio-group>
<view
class="px-[24rpx] py-[12rpx] rounded-[8rpx] bg-[rgba(255,96,68,0.1)] flex flex-col gap-[8rpx] text-[#FF6044] text-[22rpx] w-max mx-auto mt-[82rpx]"
>
<text class="">普通类一段批次线442分线高139分</text>
<text class="">普通类二段批次线150分线高432分</text>
</view>
</view>
</template>
<script lang="ts" setup>
import { useUniversityLevel } from '@/hooks/useFilterSchool'
defineOptions({
options: {
styleIsolation: 'shared',
},
})
const { phaseList } = useUniversityLevel()
const choosePhase = ref('')
</script>
<style lang="scss">
:deep(.radio-item-border) {
border: 2rpx solid #fff !important;
.wd-icon-check-bold {
display: none;
}
> .wd-radio__label {
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 100% !important;
height: 100% !important;
padding: 16rpx 96rpx !important;
line-height: unset !important;
background-color: #f7f8fa !important;
border-radius: 8rpx !important;
}
}
:deep(.wd-radio__shape) {
display: none !important;
}
</style>

View File

@ -0,0 +1,34 @@
<template>
<CheckGroup
:list="regionList"
@change="handleChange"
:default-value="regionInfo"
label-key="simplename"
/>
</template>
<script lang="ts" setup>
import { useRegionInfo } from '@/hooks/useFilterSchool'
import CheckGroup from '@/components/checkGroup/CheckGroup.vue'
defineOptions({
options: {
styleIsolation: 'shared',
},
})
const { regionList } = useRegionInfo()
const regionInfo = ref<string[]>(['110000', '120000'])
const handleChange = (val: string[]) => {
console.log(val)
}
</script>
<style lang="scss">
:deep(.checkbox-item-border) {
border: 2rpx solid #fff;
> .wd-icon-check-bold {
display: none !important;
}
}
</style>

View File

@ -0,0 +1,21 @@
<template>
<CheckGroup
:list="infoList"
@change="handleChange"
:default-value="defaultInfo"
value-key="id"
label-key="name"
/>
</template>
<script lang="ts" setup>
import CheckGroup from '@/components/checkGroup/CheckGroup.vue'
import { useUniversityType } from '@/hooks/useFilterSchool'
const { typeList: infoList } = useUniversityType()
const defaultInfo = ref<string[]>([])
const handleChange = (val: string[]) => {
console.log(val)
}
</script>

View File

@ -1,174 +0,0 @@
<template>
<!-- TabBar占位块 - 与TabBar高度一致 -->
<view
v-if="showPlaceholder"
class="tabbar-placeholder"
:style="{ height: `${tabbarTotalHeight}px` }"
></view>
<!-- TabBar组件 -->
<view class="custom-tabbar pb-safe">
<view class="tabbar-content">
<view
class="tabbar-item"
v-for="item in tabbarList"
:key="item.id"
:class="[item.centerItem ? 'center-item' : '']"
@click="changeItem(item)"
>
<view class="item-top">
<image
class="w-full h-full object-contain item-icon"
:src="currentPage == item.id ? item.selectIcon : item.icon"
></image>
</view>
<view class="item-bottom" :class="[currentPage == item.id ? 'item-active' : '']">
<text>{{ item.text }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { TabesItem } from '@/service/app/types'
import { tabbarList } from '@/hooks/useTabbarList'
import { ref, computed, onMounted } from 'vue'
import { useUserStore } from '@/store'
defineProps({
currentPage: {
type: Number,
default: 0,
},
//
showPlaceholder: {
type: Boolean,
default: true,
},
})
//
const safeAreaBottom = ref(0)
const userStore = useUserStore()
// TabBar (TabBar + )
const tabbarTotalHeight = computed(() => {
// 100rpxpx
const tabbarHeight = uni.upx2px(100)
return tabbarHeight + safeAreaBottom.value
})
const changeItem = (item: TabesItem) => {
if (item.navigatorItem) {
// ai
if (item.path === '/aiService-sub/index/index' && !userStore.isLoginFlag) {
uni.navigateTo({
url: item.path,
})
} else {
uni.navigateTo({
url: '/aiService-sub/index/newAi',
})
}
} else {
uni.switchTab({
url: item.path,
})
}
}
onMounted(() => {
uni.hideTabBar()
//
uni.getSystemInfo({
success: (res) => {
if (res.safeAreaInsets) {
safeAreaBottom.value = res.safeAreaInsets.bottom || 0
}
},
})
})
//
defineExpose({
tabbarTotalHeight,
})
</script>
<style scoped>
.custom-tabbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
border-top: 1px solid #f5f5f5;
z-index: 999;
}
.tabbar-content {
display: flex;
height: 100rpx;
padding: 0 20rpx;
position: relative;
}
.tabbar-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
padding: 10rpx 0;
}
.item-top {
display: flex;
align-items: center;
justify-content: center;
}
.item-bottom {
font-size: 20rpx;
margin-top: 6rpx;
color: #999;
}
.item-active {
color: #3370ff;
}
.center-item {
position: relative;
}
.item-icon {
width: 48rpx;
height: 48rpx;
}
.center-item .item-icon {
width: 98rpx;
height: 98rpx;
}
.center-item .item-bottom {
position: absolute;
bottom: 5rpx;
}
/* 占位块样式 */
.tabbar-placeholder {
width: 100%;
box-sizing: border-box;
}
/* 安全区域适配 */
.pb-safe {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
</style>

View File

@ -1,9 +1,33 @@
<template> <template>
<custom-tab-bar :current-page="currentPage" :safe-area-inset-bottom="true" /> <wd-tabbar :bordered="false" safeAreaInsetBottom :placeholder="true" fixed>
<view
class="tabbar-item h-[100rpx] flex flex-col justify-center w-full items-center text-center"
v-for="(item, index) in tabbarList"
:key="index"
:class="[item.centerItem ? 'center-item' : '']"
@click="changeItem(item)"
>
<view class="item-top w-[48rpx] h-[48rpx] p-[10rpx]">
<image
class="w-full h-full object-container"
:src="currentPage == item.id ? item.selectIcon : item.icon"
></image>
</view>
<view
class="item-bottom text-[20rpx] mt-[6rpx]"
:class="[currentPage == item.id ? 'item-active text-[#3370ff]' : '']"
>
<text>{{ item.text }}</text>
</view>
</view>
</wd-tabbar>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import CustomTabBar from './CustomTabBar.vue' import { TabesItem } from '@/service/app/types'
import { tabbarList } from '@/hooks/useTabbarList'
const tabbar = ref(1)
defineProps({ defineProps({
currentPage: { currentPage: {
@ -11,4 +35,35 @@ defineProps({
default: 0, default: 0,
}, },
}) })
const changeItem = (item: TabesItem) => {
uni.switchTab({
url: item.path,
})
}
onMounted(() => {
uni.hideTabBar()
})
</script> </script>
<style scoped>
view {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.center-item {
position: relative;
}
.center-item .item-top {
width: 98rpx;
height: 98rpx;
}
.center-item .item-bottom {
position: absolute;
bottom: 5rpx;
}
</style>

View File

@ -0,0 +1,73 @@
<template>
<wd-checkbox-group
v-model="defValue"
custom-class="flex flex-wrap gap-[16rpx] justify-items-center items-center"
checked-color="#1580FF"
@change="handleChange"
>
<wd-checkbox
v-for="item in list"
:key="item[valueKey]"
:model-value="item[valueKey]"
cell
shape="button"
custom-class="w-[152rpx]! h-[76rpx] p-0! mr-0!"
custom-label-class="w-[152rpx]! h-[76rpx]! rounded-[8rpx]! checkbox-item-border bg-[#f7f8fa]!"
>
{{ item[labelKey] }}
</wd-checkbox>
</wd-checkbox-group>
</template>
<script lang="ts" setup>
const props = defineProps({
list: {
type: Array,
default: () => [],
},
labelKey: {
type: String,
default: 'name',
},
valueKey: {
type: String,
default: 'code',
},
defaultValue: {
type: Array<string>,
default: () => [],
},
})
defineOptions({
options: {
styleIsolation: 'shared',
},
})
const emits = defineEmits(['change'])
const defValue = ref<string[]>([])
watch(
() => props.defaultValue,
(newV) => {
defValue.value = props.defaultValue
},
{ immediate: true },
)
const handleChange = (val: string[]) => {
emits('change', val)
}
</script>
<style lang="scss" scoped>
:deep(.checkbox-item-border) {
border: 2rpx solid #f7f8fa !important;
> .wd-icon-check-bold {
display: none !important;
}
}
:deep(.wd-checkbox.is-button.is-checked .wd-checkbox__label) {
border: 2rpx solid #1580ff !important;
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<wd-fab :draggable="true" :expandable="false" :gap="{ bottom: 100 }">
<template #trigger>
<view class="btn-wrapper" @click="handleClick">
<image
class="w-full h-full rounded-full"
src="/static/images/home/customerService.svg"
></image>
</view>
</template>
</wd-fab>
</template>
<script lang="ts" setup>
// import useNavbarWeixin from '@/hooks/useNavbarWeixin'
// const { safeAreaInsets } = useNavbarWeixin()
const handleClick = () => {
uni.navigateTo({
url: '/pages-sub/customerService/index/index',
})
}
</script>
<style lang="scss" scoped>
.btn-wrapper {
width: 128rpx;
height: 128rpx;
border-radius: 50%;
}
</style>

View File

@ -1,120 +0,0 @@
<template>
<view
class="fab-button"
@touchstart.stop="startDrag"
@touchmove.stop="onDrag"
@touchend.stop="endDrag"
:style="{ right: position.x + 'px', bottom: position.y + 'px' }"
>
<image
class="w-full h-full rounded-full"
src="https://api.static.ycymedu.com/src/images/home/customerService.svg"
></image>
</view>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const props = defineProps({
initialX: {
type: Number,
default: 0,
},
initialY: {
type: Number,
default: 0,
},
})
const systemInfo = uni.getWindowInfo()
const position = ref({ x: props.initialX, y: props.initialY })
const startPosition = ref({ x: 0, y: 0 })
const startTime = ref(0)
const longPressTimer = ref<number | null>(null)
const canDrag = ref(false)
const moveDistance = ref(0)
const startDrag = (event: TouchEvent) => {
startPosition.value = { x: event.touches[0].clientX, y: event.touches[0].clientY }
startTime.value = Date.now()
canDrag.value = false
moveDistance.value = 0
// 300ms
longPressTimer.value = setTimeout(() => {
if (!canDrag.value) {
canDrag.value = true
}
}, 300) as unknown as number
}
const onDrag = (event: TouchEvent) => {
const deltaX = event.touches[0].clientX - startPosition.value.x
const deltaY = event.touches[0].clientY - startPosition.value.y
//
moveDistance.value = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
//
if (moveDistance.value > 10 && !canDrag.value) {
canDrag.value = true
if (longPressTimer.value) {
clearTimeout(longPressTimer.value)
longPressTimer.value = null
}
}
if (!canDrag.value) return
position.value = { x: position.value.x - deltaX, y: position.value.y - deltaY }
startPosition.value = { x: event.touches[0].clientX, y: event.touches[0].clientY }
}
const endDrag = () => {
//
if (longPressTimer.value) {
clearTimeout(longPressTimer.value)
longPressTimer.value = null
}
// 300ms
if (!canDrag.value && moveDistance.value < 10 && Date.now() - startTime.value < 300) {
handleClick()
return
}
//
if (canDrag.value) {
const windowWidth = systemInfo.windowWidth
const windowHeight = systemInfo.windowHeight
const buttonWidth = 128 //
const buttonHeight = 128 //
if (position.value.x < 0) position.value.x = 0
if (position.value.y < 0) position.value.y = 0
if (position.value.x + buttonWidth > windowWidth) position.value.x = windowWidth - buttonWidth
if (position.value.y + buttonHeight > windowHeight)
position.value.y = windowHeight - buttonHeight
}
}
const handleClick = () => {
uni.navigateTo({
url: '/pages-sub/customerService/index/index',
})
}
</script>
<style scoped>
.fab-button {
position: fixed;
width: 128rpx;
height: 128rpx;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
</style>

View File

@ -1,62 +1,34 @@
<template> <template>
<view <view class="mx-5 rounded-lg bg-white px-[32rpx] py-[56rpx]">
:class="`mx-5 rounded-lg bg-white px-[32rpx] ${userStore.userInfo.openid ? 'py-[56rpx]' : 'py-[26rpx]'}`"
>
<view <view
class="flex items-center justify-between mx-[34rpx] py-[26rpx]" class="flex items-center justify-between mx-[34rpx] py-[30rpx]"
style="border-bottom: 2rpx solid #ededed" style="border-bottom: 2rpx solid #ededed"
@click="handleChange" @click="handleChange"
v-if="userStore.userInfo.openid"
> >
<text class="text-[44rpx] text-[#333]"> <text class="text-[40rpx] text-[#636363]">输入模考/高考成绩</text>
{{ <image class="w-[42rpx] h-[39rpx]" src="/static/images/home/pen.svg"></image>
userStore.userInfo.estimatedAchievement.expectedScore
? userStore.userInfo.estimatedAchievement.expectedScore
: '输入模考/高考成绩'
}}
</text>
<image
class="w-[42rpx] h-[39rpx]"
src="https://api.static.ycymedu.com/src/images/home/pen.svg"
></image>
</view> </view>
<view class="flex items-center justify-center" v-else> <view class="mt-[56rpx] flex items-center justify-between">
<image <wd-button
class="w-[74%] h-[50rpx]" custom-class="w-[240rpx]! h-[88rpx]! border-[#1580FF]! text-[#1580FF]! text-[28rpx]! font-normal! mr-[32rpx]"
mode="widthFix" :round="false"
src="https://api.static.ycymedu.com/pagefirstloginbg.png"
/>
</view>
<view class="mt-[56rpx] flex items-center justify-between" v-if="userStore.userInfo.openid">
<button
class="w-[240rpx]! h-[88rpx]! border-[#1580FF]! text-[#1580FF]! text-[30rpx]! font-normal! mr-[32rpx] flex! items-center! justify-center! rounded-[8rpx]!"
plain plain
@click="navigatorTo" @click="navigatorTo"
> >
一键填报 一键填报
</button> </wd-button>
<button <wd-button
class="w-[350rpx]! h-[88rpx]! text-[#fff]! text-[30rpx]! bg-[#1580FF]! font-normal flex! items-center! justify-center! rounded-[8rpx]!" :round="false"
@click="navigatorToAi" custom-class="w-[350rpx]! h-[88rpx]! text-[#fff]! text-[28rpx]! bg-[#1580FF]! font-normal"
> >
智能填报 智能填报
</button> </wd-button>
</view>
<view class="flex items-center justify-between mt-[26rpx]" v-else>
<button
class="h-[78rpx]! w-full! text-[#fff]! text-[30rpx]! bg-[#1580FF]! font-normal flex! items-center! justify-center! rounded-[8rpx]!"
@click="navigatorToLogin"
>
登录/注册
</button>
</view> </view>
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useUserStore } from '@/store/user' const value = ref('')
const userStore = useUserStore()
const handleChange = () => { const handleChange = () => {
uni.navigateTo({ uni.navigateTo({
@ -65,36 +37,8 @@ const handleChange = () => {
} }
const navigatorTo = () => { const navigatorTo = () => {
if (
Object.prototype.toString.call(userStore.userInfo.estimatedAchievement.expectedScore) ===
'[object Null]' ||
userStore.userInfo.estimatedAchievement.expectedScore === ''
) {
handleChange()
} else {
uni.navigateTo({
url: '/pages-sub/home/autoFill/index',
})
}
}
const navigatorToAi = () => {
if (
Object.prototype.toString.call(userStore.userInfo.estimatedAchievement.expectedScore) ===
'[object Null]' ||
userStore.userInfo.estimatedAchievement.expectedScore === ''
) {
handleChange()
} else {
uni.navigateTo({
url: '/pages-evaluation-sub/aiAutoFill/index',
})
}
}
const navigatorToLogin = () => {
uni.navigateTo({ uni.navigateTo({
url: '/login-sub/index', url: '/pages-sub/home/autoFill/index',
}) })
} }
</script> </script>

View File

@ -1,31 +1,31 @@
<template> <template>
<view class="mx-[36rpx] mt-[48rpx]"> <view class="mx-[36rpx] mt-[44rpx]">
<view <view
class="flex items-center justify-between" class="flex items-center justify-between mb-[30rpx]"
hover-class="none" hover-class="none"
:hover-stop-propagation="false" :hover-stop-propagation="false"
> >
<text class="text-[32rpx] text-[#333333] font-semibold">高考资讯</text> <text class="text-[32rpx] text-[#333333] font-semibold">高考资讯</text>
<image <image
class="w-[40rpx] h-[40rpx]" class="w-[40rpx] h-[40rpx]"
src="https://api.static.ycymedu.com/src/images/home/right.svg" src="/static/images/home/right.svg"
@click="toNewsPage" @click="toNewsPage"
></image> ></image>
</view> </view>
<view <view class="my-[30rpx]" hover-class="none" :hover-stop-propagation="false">
class="truncate flex flex-col py-[32rpx]" <view
style="border-bottom: 2rpx solid #eee" class="truncate flex flex-col py-[32rpx]"
hover-class="none" style="border-bottom: 2rpx solid #eee"
:hover-stop-propagation="false" v-for="item in newsList"
v-for="item in newsList" :key="item"
:key="item.id" @click="handleClick(item)"
@click="handleClick(item)" >
> <text class="truncate text-[28rpx] text-[#333333] font-normal mb-[16rpx] max-w-[80%]">
<text class="truncate text-[28rpx] text-[#333333] font-normal mb-[16rpx] max-w-full"> {{ item.title }}
{{ item.title }} </text>
</text> <text class="text-[24rpx] color-[#999999] font-normal">{{ item.createTime }}</text>
<text class="text-[24rpx] color-[#999999] font-normal">{{ item.createTime }}</text> </view>
</view> </view>
</view> </view>
</template> </template>

View File

@ -1,48 +1,25 @@
<template> <template>
<view class="mt-[44rpx]" hover-class="none" :hover-stop-propagation="false"> <view class="mx-[36rpx] mt-[44rpx]" hover-class="none" :hover-stop-propagation="false">
<view <view
class="flex items-center justify-between mb-[30rpx] mx-[36rpx]" class="flex items-center justify-between mb-[30rpx]"
hover-class="none" hover-class="none"
:hover-stop-propagation="false" :hover-stop-propagation="false"
> >
<text class="text-[32rpx] text-[#333333] font-semibold">热门排行榜</text> <text class="text-[32rpx] text-[#333333] font-semibold">热门排行榜</text>
<image <image
class="w-[40rpx] h-[40rpx]" class="w-[40rpx] h-[40rpx]"
src="https://api.static.ycymedu.com/src/images/home/right.svg" src="/static/images/home/right.svg"
@click="toSchool('0')" @click="toSchool('0')"
></image> ></image>
</view> </view>
<view <view
class="flex items-center overflow-x-auto hot-rank-outer gap-[16rpx] h-[462rpx] px-[32rpx]" class="flex items-center w-full overflow-auto gap-[16rpx] hot-rank-outer"
hover-class="none" hover-class="none"
:hover-stop-propagation="false" :hover-stop-propagation="false"
> >
<!-- 骨架屏 -->
<view <view
v-if="isLoading" class="hot-rank-item flex-none pt-[32rpx] pb-[38rpx] px-[32rpx]"
v-for="(_skeleton, index) in skeletonItems"
:key="'skeleton-' + index"
:class="`hot-rank-item flex-none skeleton-item`"
hover-class="none"
:hover-stop-propagation="false"
>
<view class="skeleton-text mx-[32rpx] mt-[32rpx] h-[40rpx] w-[120rpx] rounded"></view>
<view class="flex items-center justify-left mt-[30rpx] mx-[32rpx]" v-for="i in 3" :key="i">
<view class="skeleton-text w-[20rpx] h-[28rpx] mr-[10rpx] rounded"></view>
<view class="skeleton-image w-[80rpx] h-[80rpx] rounded-full flex-none mr-[16rpx]"></view>
<view class="flex flex-col w-full">
<view class="skeleton-text h-[28rpx] w-[120rpx] rounded"></view>
<view class="skeleton-text h-[22rpx] w-[100rpx] mt-[10rpx] rounded"></view>
</view>
</view>
</view>
<!-- 真实数据 -->
<view
v-else
:class="`hot-rank-item flex-none`"
hover-class="none" hover-class="none"
:hover-stop-propagation="false" :hover-stop-propagation="false"
v-for="typeWrap in universityTypeRankList" v-for="typeWrap in universityTypeRankList"
@ -50,12 +27,12 @@
@click="toSchool(typeWrap.type)" @click="toSchool(typeWrap.type)"
v-show="typeWrap.rows.length > 0" v-show="typeWrap.rows.length > 0"
> >
<text class="font-semibold text-[#303030] text-[32rpx] inline-block mx-[32rpx] mt-[32rpx]"> <text class="font-semibold text-[#303030] text-[32rpx] inline-block">
{{ typeWrap.name }} {{ typeWrap.name }}
</text> </text>
<view <view
class="flex items-center justify-left mt-[30rpx] mx-[32rpx]" class="flex items-center justify-left mt-[30rpx]"
v-for="(item, index) in typeWrap.rows" v-for="(item, index) in typeWrap.rows"
:key="index" :key="index"
> >
@ -92,132 +69,99 @@ const toSchool = (id: string) => {
const { unSortTypeList } = useUnSortType() const { unSortTypeList } = useUnSortType()
let universityTypeRankList = ref([]) let universityTypeRankList = ref([])
const isLoading = ref(true)
//
const skeletonItems = ref([
{ type: 'skeleton-1', name: '综合排名', rows: [] },
{ type: 'skeleton-2', name: '理工排名', rows: [] },
{ type: 'skeleton-3', name: '文科排名', rows: [] },
{ type: 'skeleton-4', name: '医科排名', rows: [] },
])
watch( watch(
() => unSortTypeList.value, () => unSortTypeList.value,
(newVal) => { (newVal) => {
if (newVal && newVal.length > 0) { Promise.all(
Promise.all( newVal.map((item) =>
newVal.map((item) => getUniversityRank({
getUniversityRank({ Year: 2023,
Year: 2023, Type: item.type,
Type: item.type, PageIndex: 1,
PageIndex: 1, PageSize: 3,
PageSize: 3, }),
}), ),
), ).then((res) => {
) res.forEach((item, index) => {
.then((res) => { universityTypeRankList.value.push({
universityTypeRankList.value = [] ...newVal[index],
res.forEach((item, index) => { rows: (item.result as { rows: any[] }).rows,
universityTypeRankList.value.push({
...newVal[index],
rows: (item.result as { rows: any[] }).rows,
loaded: true,
})
})
isLoading.value = false
}) })
.catch(() => { })
isLoading.value = false })
})
}
}, },
{ immediate: true },
) )
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.hot-rank-item { .hot-rank-item {
width: 356rpx; width: 292rpx;
height: 452rpx; border: 2rpx solid;
position: relative;
background: #fff;
border-radius: 8px;
}
.hot-rank-item::before {
content: '';
width: 360rpx;
height: 456rpx;
position: absolute;
border-radius: 8px;
top: -2rpx;
left: -2rpx;
z-index: -1;
} }
.hot-rank-outer .hot-rank-item:nth-child(1) { .hot-rank-outer .hot-rank-item:nth-child(1) {
background: linear-gradient(180deg, #caddff 0%, #eaf1ff 23%, #fff 100%);
}
.hot-rank-outer .hot-rank-item:nth-child(1)::before {
background: linear-gradient( background: linear-gradient(
180deg, 180deg,
rgba(201.8750050663948, 221.00000202655792, 255, 1), #dee7f8 0%,
rgba(233.7500050663948, 241.39999777078629, 255, 1) rgba(239, 244, 251, 0) 46%,
rgba(239, 244, 251, 0) 100%
); );
border-image: linear-gradient(
180deg,
rgba(201.8750050663948, 221.00000202655792, 255, 1),
rgba(233.7500050663948, 241.39999777078629, 255, 1)
)
2 2;
} }
.hot-rank-outer .hot-rank-item:nth-child(2) { .hot-rank-outer .hot-rank-item:nth-child(2) {
background: linear-gradient(180deg, #cef5e1 0%, #ddf7ea 23%, #fff 100%);
}
.hot-rank-outer .hot-rank-item:nth-child(2)::before {
background: linear-gradient( background: linear-gradient(
180deg, 180deg,
rgba(205.5883178114891, 245.07227271795273, 225.3302800655365, 1), #ddf7ea 0%,
rgba(221.00000202655792, 247.00000047683716, 234.00000125169754, 1) rgba(234, 250, 241, 0) 46%,
rgba(234, 250, 241, 0) 100%
); );
border-image: linear-gradient(
180deg,
rgba(205.5883178114891, 245.07227271795273, 225.3302800655365, 1),
rgba(221.00000202655792, 247.00000047683716, 234.00000125169754, 1)
)
2 2;
} }
.hot-rank-outer .hot-rank-item:nth-child(3)::before {
background: linear-gradient(180deg, rgba(245, 237, 255, 1), rgba(245, 237, 255, 1));
}
.hot-rank-outer .hot-rank-item:nth-child(3) { .hot-rank-outer .hot-rank-item:nth-child(3) {
background: linear-gradient(180deg, #f7e7ff 0%, rgba(245, 237, 255, 0) 23%, #fff 100%); background: linear-gradient(
180deg,
#f7e7ff 0%,
rgba(245, 237, 255, 0) 46%,
rgba(245, 237, 255, 0) 100%
);
border-image: linear-gradient(180deg, rgba(245, 237, 255, 1), rgba(245, 237, 255, 1)) 2 2;
} }
.hot-rank-outer .hot-rank-item:nth-child(4)::before {
background: linear-gradient(180deg, rgba(255, 228, 196, 1), rgba(255, 228, 196, 1));
}
.hot-rank-outer .hot-rank-item:nth-child(4) { .hot-rank-outer .hot-rank-item:nth-child(4) {
background: linear-gradient(180deg, #ffe4c4 0%, rgba(255, 228, 196, 0) 23%, #fff 100%); background: linear-gradient(
180deg,
#ffe4c4 0%,
rgba(255, 228, 196, 0) 46%,
rgba(255, 228, 196, 0) 100%
);
border-image: linear-gradient(180deg, rgba(255, 228, 196, 1), rgba(255, 228, 196, 1)) 2 2;
} }
.hot-rank-outer .hot-rank-item:nth-child(5)::before {
background: linear-gradient(180deg, rgba(213, 255, 196, 0), rgba(213, 255, 196, 0));
}
.hot-rank-outer .hot-rank-item:nth-child(5) { .hot-rank-outer .hot-rank-item:nth-child(5) {
background: linear-gradient(180deg, #e5ffc4 0%, rgba(213, 255, 196, 0) 23%, #fff 100%); background: linear-gradient(
} 180deg,
#e5ffc4 0%,
rgba(213, 255, 196, 0) 46%,
rgba(213, 255, 196, 0) 100%
);
/* 骨架屏样式 */ border-image: linear-gradient(180deg, rgba(213, 255, 196, 0), rgba(213, 255, 196, 0)) 2 2;
.skeleton-text,
.skeleton-image {
background-color: #e0e0e0;
animation: pulse 1.5s infinite;
}
.skeleton-item {
background: linear-gradient(180deg, #eaeaea 0%, #f5f5f5 23%, #fff 100%);
}
@keyframes pulse {
0% {
opacity: 0.5;
}
50% {
opacity: 1;
}
100% {
opacity: 0.5;
}
} }
</style> </style>

View File

@ -4,132 +4,75 @@
v-for="item in subMenus" v-for="item in subMenus"
:key="item.id" :key="item.id"
class="flex items-center justify-center flex-col" class="flex items-center justify-center flex-col"
@click="goPath(item.path, item.isTab)" @click="goPath(item.path)"
> >
<view class="relative w-[88rpx] h-[88rpx]"> <image :src="item.icon" class="w-[88rpx] h-[88rpx]" mode="widthFix"></image>
<image <view class="text-[22rpx] text-[#303030] mt-[8rpx]">{{ item.name }}</view>
class="skeleton w-[88rpx] h-[88rpx] rounded-full absolute"
:class="{ hidden: item.loaded }"
></image>
<image
:src="item.icon"
class="w-[88rpx] h-[88rpx] absolute"
:class="{ 'opacity-0': !item.loaded }"
mode="widthFix"
@load="handleLoad(item)"
></image>
</view>
<view class="text-[24rpx] text-[#303030] mt-[8rpx]">{{ item.name }}</view>
</view> </view>
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const subMenus = ref([ const subMenus = [
{ {
id: 1, id: 1,
name: '找大学', name: '找大学',
path: '/pages-sub/home/college/index', path: '/pages-sub/home/college/index',
icon: 'https://api.static.ycymedu.com/src/images/home/college.svg', icon: '/static/images/home/college.svg',
isTab: false,
loaded: false,
}, },
{ {
id: 2, id: 2,
name: '查专业', name: '查专业',
path: '/pages-sub/home/major/index', path: '/pages-sub/home/major/index',
icon: 'https://api.static.ycymedu.com/src/images/home/major.svg', icon: '/static/images/home/major.svg',
isTab: false,
loaded: false,
}, },
// //
{ {
id: 3, id: 3,
name: '看职业', name: '看职业',
path: '/pages-sub/home/career/index', path: '/pages-sub/home/career/index',
icon: 'https://api.static.ycymedu.com/src/images/home/career.svg', icon: '/static/images/home/career.svg',
isTab: false,
loaded: false,
}, },
// 线 // 线
{ {
id: 4, id: 4,
name: '批次线', name: '批次线',
path: '/pages-sub/home/line/index', path: '/pages-sub/home/line/index',
icon: 'https://api.static.ycymedu.com/src/images/home/line.svg', icon: '/static/images/home/line.svg',
isTab: false,
loaded: false,
}, },
// //
{ {
id: 5, id: 5,
name: '查位次', name: '查位次',
path: '/pages-evaluation-sub/rank/index', path: '/pages-sub/home/rank/index',
icon: 'https://api.static.ycymedu.com/src/images/home/rank.svg', icon: '/static/images/home/rank.svg',
isTab: false,
loaded: false,
}, },
// //
{ {
id: 6, id: 6,
name: '查扩缩招', name: '查扩缩招',
path: '/pages-sub/home/expand/index', path: '/pages-sub/home/expand/index',
icon: 'https://api.static.ycymedu.com/src/images/home/expand.svg', icon: '/static/images/home/expand.svg',
isTab: false,
loaded: false,
}, },
// //
{ {
id: 7, id: 7,
name: '专业测评', name: '专业测评',
path: '/pages/evaluation/index/index', path: '/pages-sub/home/evaluation/index',
icon: 'https://api.static.ycymedu.com/src/images/home/evaluation.svg', icon: '/static/images/home/evaluation.svg',
isTab: true,
loaded: false,
}, },
// //
{ {
id: 8, id: 8,
name: '大学甄别', name: '大学甄别',
path: '/pages-sub/home/distinguish/index', path: '/pages-sub/home/distinguish/index',
icon: 'https://api.static.ycymedu.com/src/images/home/distinguish.svg', icon: '/static/images/home/distinguish.svg',
isTab: false,
loaded: false,
}, },
]) ]
const goPath = (path: string, isTab: boolean) => { const goPath = (path: string) => {
if (isTab) { uni.navigateTo({
uni.switchTab({ url: path,
url: path, })
})
} else {
uni.navigateTo({
url: path,
})
}
}
const handleLoad = (item: any) => {
item.loaded = true
} }
</script> </script>
<style>
.skeleton {
background-color: #e0e0e0; /* 骨架屏的背景色 */
animation: pulse 1.5s infinite; /* 添加动画效果 */
}
@keyframes pulse {
0% {
opacity: 0.5;
}
50% {
opacity: 1;
}
100% {
opacity: 0.5;
}
}
</style>

View File

@ -1,209 +0,0 @@
<template>
<view class="navbar">
<!-- 状态栏占位 -->
<view
v-if="safeAreaInsetTop"
class="status-bar"
:style="{ height: statusBarHeight + 'px', backgroundColor: bgColor }"
></view>
<!-- 导航栏主体 -->
<view
class="navbar-content"
:class="[contentClass, fixed ? 'navbar-fixed' : '', bordered ? 'navbar-border' : '']"
:style="{
backgroundColor: bgColor,
height: navHeight + 'px',
top: fixed ? (safeAreaInsetTop ? statusBarHeight : 0) + 'px' : '0',
}"
>
<!-- 左侧区域 -->
<view class="navbar-left" @click="handleClickLeft">
<view v-if="leftArrow" class="back-icon">
<view class="i-carbon-chevron-left text-[40rpx] text-[#333] font-semibold" />
</view>
<slot name="left"></slot>
</view>
<!-- 中间标题区域 -->
<view class="navbar-title">
<slot name="title">
<text class="title-text">{{ title }}</text>
</slot>
</view>
<!-- 右侧区域 -->
<view class="navbar-right">
<slot name="right"></slot>
</view>
</view>
<!-- 占位元素 -->
<view
v-if="placeholder && fixed"
:style="{
height: `${navHeight}px`,
backgroundColor: bgColor,
}"
></view>
<slot name="background"></slot>
</view>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
defineProps({
title: {
type: String,
default: '',
},
leftArrow: {
type: Boolean,
default: false,
},
fixed: {
type: Boolean,
default: false,
},
placeholder: {
type: Boolean,
default: false,
},
bordered: {
type: Boolean,
default: true,
},
safeAreaInsetTop: {
type: Boolean,
default: true,
},
bgColor: {
type: String,
default: '#ffffff',
},
contentClass: {
type: String,
default: 'justify-between',
},
})
const emit = defineEmits(['clickLeft'])
//
const systemInfo = uni.getWindowInfo()
const deviceInfo = uni.getDeviceInfo()
const statusBarHeight = systemInfo.statusBarHeight || 0
//
const navHeight = computed(() => {
//
const { screenWidth } = systemInfo
const { platform } = deviceInfo
// pxrpx
const ratio = 750 / screenWidth
//
if (platform === 'ios') {
return 88 / ratio // iOS 44ptpx
} else if (platform === 'android') {
return 96 / ratio // Android 48dppx
} else {
return 88 / ratio //
}
})
const handleClickLeft = () => {
emit('clickLeft')
}
</script>
<style scoped>
.navbar {
width: 100%;
}
.status-bar {
width: 100%;
background-color: inherit;
}
.navbar-content {
width: 100%;
display: flex;
align-items: center;
/* justify-content: space-between; */
padding: 0 16rpx;
box-sizing: border-box;
background-color: #fff;
}
.navbar-fixed {
position: fixed;
left: 0;
width: 100%;
z-index: 999;
}
.navbar-border {
border-bottom: 1rpx solid #eee;
}
.navbar-left {
display: flex;
align-items: center;
height: 100%;
min-width: 100rpx;
}
.back-icon {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.navbar-title {
/* flex: 1; */
text-align: center;
overflow: hidden;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.title-text {
font-size: 34rpx;
color: #333;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.navbar-right {
display: flex;
align-items: center;
min-width: 52rpx;
justify-content: flex-end;
height: 100%;
}
@font-face {
font-family: 'iconfont';
src: url('data:font/woff2;charset=utf-8;base64,d09GMgABAAAAAAKYAAsAAAAABlAAAAJMAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACCcApcdgE2AiQDCAsGAAQgBYRnBzYbmQXIHpIkBQQKkYCABBEPz2/t/XN3twEbowBkQTxQEQ1RKaKSxEOi0agkJKF5Qvj/f037IFKwlZ2dWU2tJu0EhPwHkBwgOVAclKcvAQpI/v/fz/08XECy+YBymmPQiwIcSmhAY4uSFcgJ+IaxC1zCYwLtRjWSnZ2rGgQWBowLxCPrVBBYllQqNTQ0VISaBXEHtTRNUwW4jb4f/xYEC0kqMzDx6CGrQuKXxKc6Zf7POYQgQHs5kIwjYwEoxK3G/DpRwbi0dlNwKKjAL4lf6vw/R2zVWvTPIwuiCnp2wCRUZ3yJX5pJFVDfByyAFR2AblMAX/OR3t7+zOJi8GyyfzC1uQXLZvtnk/0zyfTy+PvH0/Xp5OzR98/H797/+/fDu3d/3739+/fd+/+nmxvLc5vrS+sry2vz84tLs9Mzc4vzs9NTM/Ozc1OzM3MzU/Mz0wvTU4vTk0tTE8uTEyuT4yv/G0E3XUxv7wwNbu/s9G8fbO9v7+3sb+3ubW4dbO4dbO3vbu4dbO3JzqPFtRE4gEGAX0NBkL+hpCZALkEp5FKUQqE0NHlXJIGrDNAOcEQBCHU+kXT5QNblC7kEv1EK9Y9SB/8o7YYu2m0YXrJLouNIjQJhH+QbVkVZrUQ+YuqzUJdzxPMHhdIj0+hg4o0D8ogj5r5bSoQUxjADz+A8hBDQFEYwh3mommXTul7Vm5ZtqAqJHIdoKCDYDyQ3mCqUG1YKn5+C0s0yiJ/qKVAQedKAhg6Y3mEHJBQaWKnvLVMiiEIxGAY8Aw6HIAhAJmEIzIIOUjLTTAB1taL1QvNq+fYN7QDjcc2okeioaOmy5LFXt3QAAAAA')
format('woff2');
}
.back-text {
font-family: 'iconfont' !important;
font-size: 48rpx;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #333;
}
</style>

View File

@ -0,0 +1,170 @@
<template>
<view class="content">
<!-- 使用 scroll-view 组件来实现滚动 -->
<scroll-view
ref="list"
:scroll-y="true"
class="list-container"
@scroll="handleScroll"
:scroll-top="state.startOffset"
>
<view class="list-phantom" :style="{ height: `${listHeight}${itemSizeUnit}` }"></view>
<view class="list" :style="{ transform: getTransform }">
<view
v-for="(item, index) in visibleData"
class="list-item"
:key="index"
:ref="setItemRef"
:style="`height:${state.itemHeights[index]}${itemSizeUnit}`"
>
<!-- <slot name="cell" :item="item" :index="index"></slot> -->
<text class="">
{{ item.name }}
</text>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="ts">
import { reactive, onMounted, computed } from 'vue'
const state = reactive({
listHeight: 0,
screenHeight: 0, //
startOffset: 0, //
startIndex: 0, //
endIndex: 0, //
itemHeights: [] as number[], //
})
const props = defineProps({
listData: {
type: Array<{ name: string; id: number }>,
default: () => [],
},
//
itemSize: {
type: Number,
default: 200,
},
itemSizeUnit: {
type: String,
default: 'px',
},
})
// const listHeight = computed(() => {
// return props.listData.length * props.itemSize
// })
const listHeight = computed(() => {
//
return state.itemHeights.reduce((sum, height) => sum + height, 0) || 0
})
const visibleCount = computed(() => {
return Math.ceil(state.screenHeight / props.itemSize) || 0
})
const getTransform = computed(() => {
return `translate3d(0,${state.startOffset}${props.itemSizeUnit},0)`
})
const visibleData = computed(() => {
return props.listData.slice(state.startIndex, Math.min(state.endIndex, props.listData.length))
})
onMounted(() => {
init()
})
const init = () => {
getScreenHeight()
// state.startIndex = 0 num state.startIndex = num state.startOffset = num * props.itemSize
// state.startIndex = 0
state.startIndex = 0
state.startOffset = 0
state.endIndex = state.startIndex + visibleCount.value
}
//
const getScreenHeight = () => {
uni.getSystemInfo({
success: function (res) {
state.screenHeight = res.screenHeight
},
})
}
// debounce
const debounce = (fn, delay, _this) => {
var delay = delay || 200
var timer = null
return function () {
let self = _this
let args = arguments
timer && clearTimeout(timer)
timer = setTimeout(function () {
timer = null
fn.apply(self, args)
}, delay)
}
}
const handleScroll = debounce(
(e) => {
//
let scrollTop = e.detail.scrollTop
//
state.startIndex = Math.floor(scrollTop / props.itemSize)
//
state.endIndex = state.startIndex + visibleCount.value
//
state.startOffset = scrollTop - (scrollTop % props.itemSize)
},
10,
'',
)
const itemRefs = ref([])
const setItemRef = (el) => {
if (el) {
itemRefs.value.push(el)
}
}
//
const calculateItemHeights = () => {
state.itemHeights = props.listData.map((_, index) => {
const refItem = itemRefs.value[index]
return refItem && refItem.$el ? refItem.$el.offsetHeight : props.itemSize // 使
})
}
watch(itemRefs.value, () => {
calculateItemHeights()
})
//
</script>
<style lang="scss" scoped>
.content {
height: 100%;
}
.list-container {
height: 100%;
overflow: auto;
position: relative;
.list-phantom {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.list {
left: 0;
right: 0;
top: 0;
position: absolute;
.list-item {
text-align: center;
border-bottom: 1px solid #ccc;
}
}
}
</style>

View File

@ -1,216 +0,0 @@
<template>
<view class="tab-container">
<!-- tab标题栏 -->
<scroll-view
scroll-x
class="tab-scroll-view"
:scroll-left="scrollLeft"
scroll-with-animation
show-scrollbar="false"
:id="tabScrollId"
>
<view class="tab-items-container">
<view
v-for="(item, index) in tabs"
:key="index"
class="tab-item"
:class="{ active: currentIndex === index }"
@click="handleTabClick(index)"
:id="`tab-item-${index}`"
>
<text class="tab-text">{{ item.title }}</text>
</view>
<!-- 独立的滑块元素 -->
<view
class="tab-line"
:style="{
transform: `translateX(${lineLeft}px)`,
width: `${lineWidth}rpx`,
backgroundColor: props.themeColor,
}"
></view>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, watch, nextTick, onMounted } from 'vue'
// IDTab
const tabScrollId = `tab-scroll-${Date.now()}`
//
const props = defineProps({
// tabs[{title: '1'}, {title: '2'}]
tabs: {
type: Array,
default: () => [],
},
//
modelValue: {
type: Number,
default: 0,
},
//
themeColor: {
type: String,
default: '#3C9CFD',
},
//
lineWidth: {
type: [Number, String],
default: 48,
},
})
//
const emit = defineEmits(['update:modelValue', 'change'])
//
const currentIndex = ref(props.modelValue)
//
const scrollLeft = ref(0)
//
const lineLeft = ref(0)
// props
watch(
() => props.modelValue,
(newVal) => {
if (currentIndex.value !== newVal) {
currentIndex.value = newVal
updateTabPosition()
}
},
)
// currentIndex
watch(
() => currentIndex.value,
(newVal, oldVal) => {
if (newVal !== oldVal) {
updateTabPosition()
//
emit('update:modelValue', newVal)
emit('change', {
index: newVal,
item: props.tabs[newVal] || {},
})
}
},
)
// tabs
watch(
() => props.tabs,
() => {
nextTick(() => {
updateTabPosition()
})
},
{ deep: true },
)
//
onMounted(() => {
nextTick(() => {
updateTabPosition()
})
})
const instance = getCurrentInstance()
// -
const updateTabPosition = () => {
nextTick(() => {
//
const query = uni.createSelectorQuery().in(instance)
//
query.select(`#${tabScrollId}`).boundingClientRect()
query.select(`#tab-item-${currentIndex.value}`).boundingClientRect()
query.exec((res) => {
if (res && res[0] && res[1]) {
const scrollView = res[0]
const currentTab = res[1]
// 1. - 使
const tabCenter = currentTab.left + currentTab.width / 2 - scrollView.left
// 2.
const lineWidthPx = uni.upx2px(Number(props.lineWidth))
lineLeft.value = tabCenter - lineWidthPx / 2
// 3. 使
const offsetLeft = currentTab.left - scrollView.left
scrollLeft.value = offsetLeft - scrollView.width / 2 + currentTab.width / 2
}
})
})
}
//
const handleTabClick = (index) => {
if (currentIndex.value !== index) {
currentIndex.value = index
}
}
</script>
<style scoped>
.tab-container {
width: 100%;
}
.tab-scroll-view {
white-space: nowrap;
width: 100%;
height: 88rpx;
background-color: #ffffff;
border-bottom: 1rpx solid #f5f5f5;
position: relative;
}
.tab-items-container {
display: inline-flex;
height: 100%;
position: relative;
width: 100%;
justify-content: space-around;
}
.tab-item {
display: inline-flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 32rpx;
position: relative;
height: 100%;
}
.tab-text {
font-size: 28rpx;
color: #333333;
transition: all 0.3s;
}
.tab-item.active .tab-text {
color: v-bind('props.themeColor');
}
.tab-line {
position: absolute;
height: 6rpx;
border-radius: 6rpx;
bottom: 0;
left: 0;
/* 平滑过渡效果 */
transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
</style>

View File

@ -1,4 +1,9 @@
import { getNewsTop, getProvinceInitialization, getNewsDetailInfo } from '@/service/index/api' import {
getNewsTop,
getVolunteerInitialization,
getNewsDetailInfo,
getNewsList,
} from '@/service/index/api'
import { useCityStore } from '@/store/city' import { useCityStore } from '@/store/city'
import { useUserStore } from '@/store/user' import { useUserStore } from '@/store/user'
import { City, News, NewsDetail } from '@/types/app-type' import { City, News, NewsDetail } from '@/types/app-type'
@ -13,7 +18,7 @@ const userStore = useUserStore()
export const cities = [] export const cities = []
export const useCityInfo = () => { export const useCityInfo = () => {
getProvinceInitialization().then((res) => { getVolunteerInitialization().then((res) => {
if (res.result) { if (res.result) {
const list = res.result as Province[] const list = res.result as Province[]
const li = groupByFirstLetter(list) const li = groupByFirstLetter(list)
@ -51,7 +56,7 @@ const groupByFirstLetter = (lis: Province[]): { letter: string; provinces: Provi
export const newsList = ref([]) export const newsList = ref([])
export const useCityNewTop = () => { export const useCityNewTop = () => {
const fetchNewTopFun = (provinceCode) => { const fetchNewTopFun = (provinceCode) => {
getNewsTop({ Top: 4, CategoryId: 1, provinceCode }).then((res) => { getNewsTop({ Top: 2, CategoryId: 1, provinceCode }).then((res) => {
if (res.code === 200) { if (res.code === 200) {
newsList.value = res.result as { title: string }[] newsList.value = res.result as { title: string }[]
} }

View File

@ -1,4 +1,20 @@
import { getUniversityType, getRegionInfo, getNature } from '@/service/index/api' import {
getUniversityType,
getRegionInfo,
getUniversityLevel,
getNature,
} from '@/service/index/api'
export const useUniversityLevel = () => {
const phaseList = ref([])
getUniversityLevel().then((res) => {
if (res.code === 200) {
phaseList.value = res.result as { code: number; name: string }[]
}
})
return { phaseList }
}
interface Region { interface Region {
code: string code: string

View File

@ -9,7 +9,7 @@ export default () => {
// 页面滚动到底部时的操作,通常用于加载更多数据 // 页面滚动到底部时的操作,通常用于加载更多数据
const onScrollToLower = () => {} const onScrollToLower = () => {}
// 获取屏幕边界到安全区域距离 // 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getWindowInfo() const { safeAreaInsets } = uni.getSystemInfoSync()
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
// 基于小程序的 Page 类型扩展 uni-app 的 Page // 基于小程序的 Page 类型扩展 uni-app 的 Page

View File

@ -1,8 +1,9 @@
import { getCountryRules } from '@/service/index/api' import { getCountryRules } from '@/service/index/api'
import { useRulesStore } from '@/store/rules'
import { useUserStore } from '@/store/user' import { useUserStore } from '@/store/user'
import { RuleResult } from '@/types/app-type' import { RuleResult } from '@/types/app-type'
const rulesStore = useRulesStore()
const userStore = useUserStore() const userStore = useUserStore()
export const requireSubjectList = ref([]) export const requireSubjectList = ref([])
@ -12,35 +13,15 @@ export const requireSubject = ref('')
// 任意选择科目 // 任意选择科目
export const optionalSubject = ref([]) export const optionalSubject = ref([])
export const useRules = (callback?: any) => { export const useRules = () => {
getCountryRules().then((res) => { getCountryRules().then((res) => {
if (res.code === 200) { if (res.code === 200) {
const results = res.result as RuleResult[] const results = res.result as RuleResult[]
rulesStore.setRules(results)
const matchRule = results.filter((item) => item.p === userStore.userInfo.city.policy) const matchRule = results.filter((item) => item.p === userStore.userInfo.city.policy)
const matchRules = matchRule.length > 0 ? matchRule[0].rule : [] const matchRules = matchRule.length > 0 ? matchRule[0].rule : []
requireSubjectList.value = matchRules.filter((item) => item?.isfirst === 'true') requireSubjectList.value = matchRules.filter((item) => item?.isfirst === 'true')
optionalSubjectList.value = matchRules.filter((item) => !(item?.isfirst === 'true')) optionalSubjectList.value = matchRules.filter((item) => !(item?.isfirst === 'true'))
if (userStore.userInfo.city.code !== userStore.userInfo.estimatedAchievement.provinceCode) {
return
}
splitSubject(requireSubjectList.value, optionalSubjectList.value)
callback ? callback() : false
} }
}) })
} }
// 分离学科,然后将学科分类存储到用户的期望数据上
const splitSubject = (requireSubjectList: any[], optionalSubjectList: any[]) => {
const subjectGroup = userStore.userInfo.estimatedAchievement.subjectGroup
const splitRule = subjectGroup.split(',')
const requireSubject = requireSubjectList.filter((item) => splitRule.includes(item.simplename))
const optionalSubject = optionalSubjectList.filter((item) => splitRule.includes(item.simplename))
userStore.setEstimatedAchievement({
requireSubject,
optionalSubject,
})
}

View File

@ -1,9 +1,8 @@
import { TabesItem } from '@/service/app' import { TabesItem } from '@/service/app'
import { sysDictType } from '@/service/index/api' import { sysDictType } from '@/service/index/api'
import { useUserStore } from '@/store'
const tabbarList = ref<TabesItem[]>([]) const tabbarList = ref<TabesItem[]>([])
const userStore = useUserStore() const app = getApp()
sysDictType({ id: 619330547859525 }).then((res) => { sysDictType({ id: 619330547859525 }).then((res) => {
const { code, result } = res const { code, result } = res
@ -26,12 +25,11 @@ sysDictType({ id: 619330547859525 }).then((res) => {
}, },
{ {
id: 2, id: 2,
path: '/aiService-sub/index/index', path: '/pages/aiService/index/index',
icon: '/static/tabBar/ai.png', icon: '/static/tabBar/ai.png',
selectIcon: '/static/tabBar/ai-active.png', selectIcon: '/static/tabBar/ai-active.png',
text: '', text: '',
centerItem: true, centerItem: true,
navigatorItem: true,
}, },
{ {
id: 1, id: 1,
@ -54,10 +52,8 @@ sysDictType({ id: 619330547859525 }).then((res) => {
if (code === 200) { if (code === 200) {
if (status === 1) { if (status === 1) {
tabbarList.value = _tabbarList.filter((item) => item.id !== 2) tabbarList.value = _tabbarList.filter((item) => item.id !== 2)
userStore.setIsShowAi(false)
} else { } else {
tabbarList.value = _tabbarList tabbarList.value = _tabbarList
userStore.setIsShowAi(true)
} }
} }
}) })

View File

@ -33,9 +33,7 @@ const httpInterceptor = {
// 3. 添加 token 请求头标识 // 3. 添加 token 请求头标识
const userStore = useUserStore() const userStore = useUserStore()
const { token } = userStore.userInfo as unknown as IUserInfo const { token } = userStore.userInfo as unknown as IUserInfo
if (options.url.includes('coze.cn')) { if (token) {
options.header.Authorization = `Bearer pat_NhhZGW7sxkuyP4mJrPrVyZx20b3m6lymg0y2Ln9EyM0CV9q2f9t3rlGbtzppLQua`
} else if (token) {
options.header.Authorization = `Bearer ${token}` options.header.Authorization = `Bearer ${token}`
} }
}, },

View File

@ -8,7 +8,7 @@ import { useUserStore } from '@/store'
import { needLoginPages as _needLoginPages, getNeedLoginPages } from '@/utils' import { needLoginPages as _needLoginPages, getNeedLoginPages } from '@/utils'
// TODO Check // TODO Check
const loginRoute = '/login-sub/index' const loginRoute = '/pages/login/index'
const isLogined = () => { const isLogined = () => {
const userStore = useUserStore() const userStore = useUserStore()

17
src/layouts/default.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<wd-config-provider :themeVars="themeVars">
<slot />
<wd-toast />
<wd-message-box />
</wd-config-provider>
</template>
<script lang="ts" setup>
import type { ConfigProviderThemeVars } from 'wot-design-uni'
const themeVars: ConfigProviderThemeVars = {
// colorTheme: 'red',
// buttonPrimaryBgColor: '#07c160',
// buttonPrimaryColor: '#07c160',
}
</script>

View File

@ -1,216 +0,0 @@
<template>
<Overlay :show="show" @update:show="handleClose">
<view
class="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center bg-white p-[40rpx] rounded-[32rpx]"
@click.stop
>
<image
class="w-[200rpx] h-[200rpx]"
src="https://api.static.ycymedu.com/images/logo.png"
mode="aspectFit"
></image>
<view class="flex flex-col items-center">
<text class="text-[26rpx] mt-[20rpx] mb-[40rpx]" :selectable="false">
{{ phone ? '申请使用您的手机号' : '申请获取您的个人信息' }}
</text>
<button
class="w-[493rpx]! mb-[40rpx] h-[88rpx]! rounded-[44rpx] text-[32rpx] text-white flex items-center justify-center"
:class="checked.length > 0 ? 'bg-[#1580FF]' : 'bg-[#BFBFBF]'"
@click.stop="handleClick"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
:disabled="checked.length === 0"
>
手机号快捷登录
</button>
<view class="flex items-center flex-nowrap">
<CheckboxGroup v-model="checked" class="check-class mr-[10rpx]">
<Checkbox name="1" cell shape="button" class="custom-checkbox"></Checkbox>
</CheckboxGroup>
<view class="flex items-center">
<text class="text-[24rpx] whitespace-nowrap">
已阅读并同意
<text class="text-[#1580FF]" @click.stop="handleClickUserAgreement">
<text>用户协议</text>
</text>
<text class="text-[#1580FF]" @click.stop="handleClickPrivacyPolicy">
<text>隐私条款</text>
</text>
</text>
</view>
</view>
</view>
</view>
</Overlay>
</template>
<script lang="ts" setup>
import { useLogin } from '@/login-sub/hooks/useUserInfo'
import Overlay from './Overlay.vue'
import Checkbox from './check-group/Checkbox.vue'
import CheckboxGroup from './check-group/CheckboxGroup.vue'
import {
getSessionKey,
getVolunteerInitialization,
getWxUserInfo,
setWxInfo,
} from '@/service/index/api'
import { useUserStore } from '@/store/user'
import { City } from '@/types/app-type'
defineProps({
show: {
type: Boolean,
default: false,
},
})
defineOptions({
options: {
styleIsolation: 'shared',
},
})
const emits = defineEmits(['update:show', 'authReady'])
const userStore = useUserStore()
const handleClose = () => {
emits('update:show', false)
}
const phone = ref(true) //
const checked = ref([]) //
const getPhoneInfo = ref(null)
const handleClickUserAgreement = () => {
uni.navigateTo({
url: '/login-sub/userAgreement',
})
}
const handleClickPrivacyPolicy = () => {
uni.navigateTo({
url: '/login-sub/privacyPolicy',
})
}
const getPhoneNumber = async (e: any) => {
if (e.detail.errMsg == 'getPhoneNumber:ok') {
const detail = e.detail
let _getPhoneInfo = {
iv: detail.iv,
encryptedData: detail.encryptedData,
code: detail.code,
}
getPhoneInfo.value = _getPhoneInfo
await getUserInfo(detail.code)
} else if (e.detail.errMsg == 'getPhoneNumber:fail not login') {
uni.showToast({
title: '请先登录',
icon: 'none',
})
} else {
uni.showToast({
title: '获取手机号失败',
icon: 'none',
})
}
}
const handleClick = () => {
if (!checked.value) {
uni.showToast({
title: '您需先同意《服务条款》和《隐私条款》',
icon: 'none',
})
return
}
}
const getUserInfo = async (_code: string) => {
let userInfo = (await useLogin()) as { code: string; errMsg: string }
if (userInfo.errMsg == 'login:ok') {
const resp = await getSessionKey({ JsCode: userInfo.code })
if (resp.code == 200) {
const result = resp.result as { accessToken: string; openId: string }
userStore.setUserToken(result.accessToken)
userStore.setUserOpenId(result.openId)
setWxInfo({ code: _code, openId: result.openId })
//
getWxUserInfo().then((resp) => {
const infoData = resp.result as unknown as {
userExtend: { provinceCode: string }
zyBatches: any[]
batchDataUrl: string
batchName: string
avatar: string
nickName: string
}
userStore.setEstimatedAchievement(infoData.userExtend)
userStore.setZyBatches(infoData.zyBatches)
userStore.setBatchDataUrl(infoData.batchDataUrl)
userStore.setBatchName(infoData.batchName)
userStore.setUserAvatar(infoData.avatar)
userStore.setUserNickName(infoData.nickName)
if (resp.code === 200) {
//
getVolunteerInitialization().then((res) => {
let list = res.result as any[]
let code = infoData.userExtend ? infoData.userExtend.provinceCode : ''
let addressItem: City
if (code !== '') {
for (let i = 0; i < list.length; i++) {
if (list[i].code == code) {
addressItem = list[i]
}
}
}
userStore.setUserCity(addressItem)
handleClose()
emits('authReady')
})
}
})
}
} else {
uni.showToast({
title: '您需先授权',
icon: 'none',
})
}
}
</script>
<style lang="scss" scoped>
:deep(.custom-checkbox) {
display: flex;
align-items: center;
justify-content: center;
.checkbox__icon {
border-radius: 50%;
height: 32rpx;
width: 32rpx;
margin: 0;
}
.custom-box {
width: 32rpx;
height: 32rpx;
border: 1px solid #ddd;
border-radius: 50%;
}
}
:deep(.checkbox-active) {
border-color: #fff !important;
background-color: #fff !important;
}
</style>

View File

@ -1,54 +0,0 @@
<template>
<view
v-if="show"
class="overlay"
:class="{ 'overlay-show': show }"
@click="handleClick"
:style="{ zIndex }"
>
<slot></slot>
</view>
</template>
<script lang="ts" setup>
const props = defineProps({
show: {
type: Boolean,
default: false,
},
zIndex: {
type: Number,
default: 10,
},
closeOnClickOverlay: {
type: Boolean,
default: true,
},
})
const emit = defineEmits(['click', 'update:show'])
const handleClick = (event: Event) => {
emit('click', event)
if (props.closeOnClickOverlay) {
emit('update:show', false)
}
}
</script>
<style scoped>
.overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.7);
transition: all 0.3s ease;
}
.overlay-show {
opacity: 1;
visibility: visible;
}
</style>

View File

@ -1,133 +0,0 @@
<template>
<view
class="checkbox"
:class="{
'checkbox--disabled': isDisabled,
'checkbox-active': isChecked,
'checkbox-disabled': isDisabled,
}"
@click="handleClick"
>
<view class="checkbox__icon" :class="{ 'checkbox__icon--checked': isChecked }">
<text v-show="isChecked" class="i-carbon-checkmark checkbox__icon-check"></text>
</view>
<view class="checkbox__label">
<slot>{{ label }}</slot>
</view>
</view>
</template>
<script lang="ts" setup>
import { computed, inject } from 'vue'
const props = defineProps({
name: {
type: [String, Number],
required: true,
},
label: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['change'])
interface CheckboxGroupContext {
modelValue: ComputedRef<any[]>
disabled: ComputedRef<boolean>
max: ComputedRef<number>
selectedCount: ComputedRef<number>
toggleOption: (option: { value: string | number }) => void
}
// checkbox group
const checkboxGroup = inject<CheckboxGroupContext>('checkboxGroup', {
modelValue: computed(() => []),
disabled: computed(() => false),
max: computed(() => 0),
selectedCount: computed(() => 0),
toggleOption: () => {},
})
//
const isChecked = computed(() => {
const modelValue = checkboxGroup.modelValue.value
return modelValue.includes(props.name)
})
//
const isDisabled = computed(() => {
const max = checkboxGroup.max.value
const selectedCount = checkboxGroup.selectedCount.value
// group
return (
props.disabled ||
checkboxGroup.disabled.value ||
(max > 1 && !isChecked.value && selectedCount >= max)
)
})
//
const handleClick = () => {
if (isDisabled.value) return
checkboxGroup.toggleOption({
value: props.name,
})
}
</script>
<style scoped>
.checkbox {
display: inline-flex;
align-items: center;
cursor: pointer;
font-size: 28rpx;
}
.checkbox--disabled {
cursor: not-allowed;
opacity: 0.5;
}
.checkbox__icon {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #dcdfe6;
border-radius: 4rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 8rpx;
transition: all 0.2s;
}
.checkbox__icon--checked {
background-color: #0083ff;
border-color: #0083ff;
}
.checkbox__icon-check {
color: #fff;
font-size: 32rpx;
}
.checkbox__label {
line-height: 1;
}
.checkbox-active {
background-color: #0083ff;
border-color: #0083ff;
}
.checkbox-disabled {
opacity: 0.5;
cursor: not-allowed !important;
}
</style>

View File

@ -1,72 +0,0 @@
<template>
<view class="checkbox-group">
<slot></slot>
</view>
</template>
<script lang="ts" setup>
import { provide, computed } from 'vue'
const props = defineProps({
modelValue: {
type: Array,
default: () => [],
},
max: {
type: Number,
default: 0,
},
disabled: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue', 'change'])
//
const innerValue = computed(() => props.modelValue)
//
const toggleOption = (option: { label: string; value: string | number }) => {
const currentValue = innerValue.value
const index = currentValue.indexOf(option.value)
let newValue = [...currentValue]
if (index === -1) {
if (props.max === 1) {
newValue = [option.value]
} else if (props.max && currentValue.length >= props.max) {
uni.showToast({
title: `最多只能选择${props.max}`,
icon: 'none',
})
return
} else {
newValue.push(option.value)
}
} else {
newValue.splice(index, 1)
}
emit('update:modelValue', newValue)
emit('change', newValue)
}
// checkbox
provide('checkboxGroup', {
modelValue: computed(() => props.modelValue),
disabled: computed(() => props.disabled),
max: computed(() => props.max),
selectedCount: computed(() => props.modelValue.length),
toggleOption,
})
</script>
<style scoped lang="scss">
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
</style>

View File

@ -1,209 +0,0 @@
<template>
<view class="navbar">
<!-- 状态栏占位 -->
<view
v-if="safeAreaInsetTop"
class="status-bar"
:style="{ height: statusBarHeight + 'px', backgroundColor: bgColor }"
></view>
<!-- 导航栏主体 -->
<view
class="navbar-content"
:class="[contentClass, fixed ? 'navbar-fixed' : '', bordered ? 'navbar-border' : '']"
:style="{
backgroundColor: bgColor,
height: navHeight + 'px',
top: fixed ? (safeAreaInsetTop ? statusBarHeight : 0) + 'px' : '0',
}"
>
<!-- 左侧区域 -->
<view class="navbar-left" @click="handleClickLeft">
<view v-if="leftArrow" class="back-icon">
<view class="i-carbon-chevron-left text-[40rpx] text-[#333] font-semibold" />
</view>
<slot name="left"></slot>
</view>
<!-- 中间标题区域 -->
<view class="navbar-title">
<slot name="title">
<text class="title-text">{{ title }}</text>
</slot>
</view>
<!-- 右侧区域 -->
<view class="navbar-right">
<slot name="right"></slot>
</view>
</view>
<!-- 占位元素 -->
<view
v-if="placeholder && fixed"
:style="{
height: `${navHeight}px`,
backgroundColor: bgColor,
}"
></view>
<slot name="background"></slot>
</view>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
defineProps({
title: {
type: String,
default: '',
},
leftArrow: {
type: Boolean,
default: false,
},
fixed: {
type: Boolean,
default: false,
},
placeholder: {
type: Boolean,
default: false,
},
bordered: {
type: Boolean,
default: true,
},
safeAreaInsetTop: {
type: Boolean,
default: true,
},
bgColor: {
type: String,
default: '#ffffff',
},
contentClass: {
type: String,
default: 'justify-between',
},
})
const emit = defineEmits(['clickLeft'])
//
const systemInfo = uni.getWindowInfo()
const deviceInfo = uni.getDeviceInfo()
const statusBarHeight = systemInfo.statusBarHeight || 0
//
const navHeight = computed(() => {
//
const { screenWidth } = systemInfo
const { platform } = deviceInfo
// pxrpx
const ratio = 750 / screenWidth
//
if (platform === 'ios') {
return 88 / ratio // iOS 44ptpx
} else if (platform === 'android') {
return 96 / ratio // Android 48dppx
} else {
return 88 / ratio //
}
})
const handleClickLeft = () => {
emit('clickLeft')
}
</script>
<style scoped>
.navbar {
width: 100%;
}
.status-bar {
width: 100%;
background-color: inherit;
}
.navbar-content {
width: 100%;
display: flex;
align-items: center;
/* justify-content: space-between; */
padding: 0 16rpx;
box-sizing: border-box;
background-color: #fff;
}
.navbar-fixed {
position: fixed;
left: 0;
width: 100%;
z-index: 999;
}
.navbar-border {
border-bottom: 1rpx solid #eee;
}
.navbar-left {
display: flex;
align-items: center;
height: 100%;
min-width: 100rpx;
}
.back-icon {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.navbar-title {
/* flex: 1; */
text-align: center;
overflow: hidden;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.title-text {
font-size: 34rpx;
color: #333;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.navbar-right {
display: flex;
align-items: center;
min-width: 52rpx;
justify-content: flex-end;
height: 100%;
}
@font-face {
font-family: 'iconfont';
src: url('data:font/woff2;charset=utf-8;base64,d09GMgABAAAAAAKYAAsAAAAABlAAAAJMAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACCcApcdgE2AiQDCAsGAAQgBYRnBzYbmQXIHpIkBQQKkYCABBEPz2/t/XN3twEbowBkQTxQEQ1RKaKSxEOi0agkJKF5Qvj/f037IFKwlZ2dWU2tJu0EhPwHkBwgOVAclKcvAQpI/v/fz/08XECy+YBymmPQiwIcSmhAY4uSFcgJ+IaxC1zCYwLtRjWSnZ2rGgQWBowLxCPrVBBYllQqNTQ0VISaBXEHtTRNUwW4jb4f/xYEC0kqMzDx6CGrQuKXxKc6Zf7POYQgQHs5kIwjYwEoxK3G/DpRwbi0dlNwKKjAL4lf6vw/R2zVWvTPIwuiCnp2wCRUZ3yJX5pJFVDfByyAFR2AblMAX/OR3t7+zOJi8GyyfzC1uQXLZvtnk/0zyfTy+PvH0/Xp5OzR98/H797/+/fDu3d/3739+/fd+/+nmxvLc5vrS+sry2vz84tLs9Mzc4vzs9NTM/Ozc1OzM3MzU/Mz0wvTU4vTk0tTE8uTEyuT4yv/G0E3XUxv7wwNbu/s9G8fbO9v7+3sb+3ubW4dbO4dbO3vbu4dbO3JzqPFtRE4gEGAX0NBkL+hpCZALkEp5FKUQqE0NHlXJIGrDNAOcEQBCHU+kXT5QNblC7kEv1EK9Y9SB/8o7YYu2m0YXrJLouNIjQJhH+QbVkVZrUQ+YuqzUJdzxPMHhdIj0+hg4o0D8ogj5r5bSoQUxjADz+A8hBDQFEYwh3mommXTul7Vm5ZtqAqJHIdoKCDYDyQ3mCqUG1YKn5+C0s0yiJ/qKVAQedKAhg6Y3mEHJBQaWKnvLVMiiEIxGAY8Aw6HIAhAJmEIzIIOUjLTTAB1taL1QvNq+fYN7QDjcc2okeioaOmy5LFXt3QAAAAA')
format('woff2');
}
.back-text {
font-family: 'iconfont' !important;
font-size: 48rpx;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #333;
}
</style>

View File

@ -1,89 +0,0 @@
<template>
<label
class="radio-wrapper"
:class="{ 'radio-wrapper--disabled': isDisabled }"
@click.stop="handleClick"
>
<radio
class="radio"
:value="String(name)"
:checked="isChecked"
:disabled="isDisabled"
:color="isChecked ? '#0083ff' : ''"
:name="String(name)"
/>
<view class="radio-label" :class="{ 'radio-label--active': isChecked }">
<slot>{{ label }}</slot>
</view>
</label>
</template>
<script lang="ts" setup>
import { computed, inject } from 'vue'
const props = defineProps({
name: {
type: [String, Number],
required: true,
},
label: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
})
interface RadioGroupContext {
modelValue: ComputedRef<string | number>
disabled: ComputedRef<boolean>
toggleOption: (value: string | number) => void
}
// radio group
const radioGroup = inject<RadioGroupContext>('radioGroup', {
modelValue: computed(() => ''),
disabled: computed(() => false),
toggleOption: () => {},
})
//
const isChecked = computed(() => {
return radioGroup.modelValue.value === props.name
})
//
const isDisabled = computed(() => {
return props.disabled || radioGroup.disabled.value
})
//
const handleClick = () => {
if (isDisabled.value) return
radioGroup.toggleOption(props.name)
}
</script>
<style scoped lang="scss">
.radio-wrapper {
display: inline-flex;
align-items: center;
font-size: 28rpx;
padding: 8rpx 0;
&--disabled {
opacity: 0.5;
}
}
.radio-label {
margin-left: 10rpx;
line-height: 1;
&--active {
color: #0083ff;
}
}
</style>

View File

@ -1,50 +0,0 @@
<template>
<radio-group class="radio-group" :value="modelValue" @change="handleChange">
<slot></slot>
</radio-group>
</template>
<script lang="ts" setup>
import { provide, computed } from 'vue'
const props = defineProps({
modelValue: {
type: [String, Number],
default: '',
},
disabled: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue', 'change'])
//
const handleChange = (e: any) => {
const value = e.detail.value
emit('update:modelValue', value)
emit('change', value)
}
//
const toggleOption = (value: string | number) => {
emit('update:modelValue', value)
emit('change', value)
}
// radio
provide('radioGroup', {
modelValue: computed(() => props.modelValue),
disabled: computed(() => props.disabled),
toggleOption,
})
</script>
<style scoped lang="scss">
.radio-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
</style>

View File

@ -1,27 +0,0 @@
import { setWxInfo } from '@/service/index/api'
//uniapp 登陆获取用户信息
export const useLogin = () => {
return new Promise(function (resolve, reject) {
uni.login({
success: function (res) {
if (res.code) {
resolve(res)
} else {
reject(res)
}
},
fail: function (err) {
reject(err)
},
})
})
}
export const useWxInfo = ({ code, openId }) => {
setWxInfo({ code, openId }).then((res) => {
if (res.code === 200) {
console.log(res.result)
}
})
}

View File

@ -1,243 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="h-screen flex flex-col">
<Navbar
safeAreaInsetTop
:bordered="false"
:fixed="true"
:placeholder="true"
left-arrow
bgColor="transparent"
@click-left="handleClickLeft"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium">授权登录</text>
</template>
</Navbar>
<view class="flex flex-col justify-center items-center flex-1 pb-safe mt-[-100px]">
<image
class="w-[424rpx] h-[424rpx]"
src="https://api.static.ycymedu.com/images/logo.png"
mode="aspectFit"
></image>
<button
class="w-[493rpx]! mb-[40rpx] h-[88rpx]! rounded-[44rpx] text-[32rpx] text-white flex items-center justify-center"
:class="checked.length > 0 ? 'bg-[#1580FF]' : 'bg-[#BFBFBF]'"
@click.stop="handleClick"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
:disabled="checked.length === 0"
>
一键登录
</button>
<view class="flex items-center flex-nowrap">
<CheckboxGroup v-model="checked" class="check-class mr-[10rpx]">
<Checkbox name="1" cell shape="button" class="custom-checkbox"></Checkbox>
</CheckboxGroup>
<view class="flex items-center">
<text class="text-[24rpx] whitespace-nowrap">
已阅读并同意
<text class="text-[#1580FF]" @click.stop="handleClickUserAgreement">
<text>用户协议</text>
</text>
<text class="text-[#1580FF]" @click.stop="handleClickPrivacyPolicy">
<text>隐私条款</text>
</text>
</text>
</view>
</view>
</view>
<LoginMask v-model:show="show" @auth-ready="handleAuthReady" />
</view>
</template>
<script setup lang="ts">
import LoginMask from './components/LoginMask.vue'
import Navbar from './components/navbar/Navbar.vue'
import { useUserStore } from '@/store/user'
import {
getSessionKey,
getVolunteerInitialization,
getWxUserInfo,
setWxInfo,
} from '@/service/index/api'
import { City } from '@/types/app-type'
import Checkbox from './components/check-group/Checkbox.vue'
import CheckboxGroup from './components/check-group/CheckboxGroup.vue'
import { useLogin } from '@/login-sub/hooks/useUserInfo'
const show = ref(false)
const checked = ref([]) //
const getPhoneInfo = ref(null)
const scene = ref('')
const getPhoneNumber = async (e: any) => {
if (e.detail.errMsg == 'getPhoneNumber:ok') {
const detail = e.detail
let _getPhoneInfo = {
iv: detail.iv,
encryptedData: detail.encryptedData,
code: detail.code,
}
getPhoneInfo.value = _getPhoneInfo
await getUserInfo(detail.code)
} else if (e.detail.errMsg == 'getPhoneNumber:fail not login') {
uni.showToast({
title: '请先登录',
icon: 'none',
})
} else {
uni.showToast({
title: '获取手机号失败',
icon: 'none',
})
}
}
const handleClick = () => {
if (!checked.value) {
uni.showToast({
title: '您需先同意《服务条款》和《隐私条款》',
icon: 'none',
})
return
}
}
//
const handleAuthReady = () => {
uni.navigateBack()
}
const handleClickLeft = () => {
uni.navigateBack()
}
const handleClickUserAgreement = () => {
uni.navigateTo({
url: '/login-sub/userAgreement',
})
}
const handleClickPrivacyPolicy = () => {
uni.navigateTo({
url: '/login-sub/privacyPolicy',
})
}
const userStore = useUserStore()
const getUserInfo = async (_code: string) => {
let userInfo = (await useLogin()) as { code: string; errMsg: string }
if (userInfo.errMsg == 'login:ok') {
const resp = await getSessionKey({ JsCode: userInfo.code })
if (resp.code == 200) {
const result = resp.result as { accessToken: string; openId: string }
userStore.setUserToken(result.accessToken)
userStore.setUserOpenId(result.openId)
setWxInfo({ code: _code, openId: result.openId })
//
getWxUserInfo().then((resp) => {
const infoData = resp.result as unknown as {
userExtend: { provinceCode: string; init: boolean }
zyBatches: any[]
batchDataUrl: string
batchName: string
avatar: string
nickName: string
mobile: string
sex: number
}
userStore.setEstimatedAchievement(infoData.userExtend)
userStore.setZyBatches(infoData.zyBatches)
userStore.setBatchDataUrl(infoData.batchDataUrl)
userStore.setBatchName(infoData.batchName)
userStore.setUserAvatar(infoData.avatar)
userStore.setUserNickName(infoData.nickName)
userStore.setUserBaseInfo({ mobile: infoData.mobile, sex: infoData.sex })
if (resp.code === 200) {
//
getVolunteerInitialization()
.then((res) => {
let list = res.result as any[]
let code = infoData.userExtend ? infoData.userExtend.provinceCode : ''
let addressItem: City
if (code !== '') {
for (let i = 0; i < list.length; i++) {
if (list[i].code == code) {
addressItem = list[i]
}
}
}
userStore.setUserCity(addressItem)
})
.then(() => {
//
if (infoData.userExtend && !infoData.userExtend.init) {
uni.navigateTo({ url: '/login-sub/inviteCode' })
} else if (scene.value !== '') {
uni.navigateTo({ url: `/pages/index/index?scene=${scene.value}` })
} else {
uni.switchTab({
url: '/pages/home/index/index',
})
}
})
}
})
}
} else {
uni.showToast({
title: '您需先授权',
icon: 'none',
})
}
}
onLoad((options) => {
//
scene.value = options.scene || ''
})
</script>
<style lang="scss" scoped>
:deep(.custom-checkbox) {
display: flex;
align-items: center;
justify-content: center;
.checkbox__icon {
border-radius: 50%;
height: 32rpx;
width: 32rpx;
margin: 0;
}
.custom-box {
width: 32rpx;
height: 32rpx;
border: 1px solid #ddd;
border-radius: 50%;
}
}
:deep(.checkbox-active) {
border-color: #fff !important;
background-color: #fff !important;
}
</style>

View File

@ -1,230 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationBarTitleText: '基本信息',
},
}
</route>
<template>
<view class="flex flex-col bg-[#f8f8f8] h-screen">
<view class="flex-1 pb-safe">
<view class="mx-[32rpx] mt-[24rpx] bg-[#fff] rounded-[20rpx]">
<form>
<view
class="flex items-center justify-between h-[100rpx] mx-[24rpx] border-b-[2rpx] border-b-solid border-[#F3F3F3]"
>
<view class="flex items-center">
<view class="text-[28rpx] text-[#000] font-[500]">姓名</view>
<view class="text-[#FF5151] font-[500] leading-[1] h-[18rpx] ml-[8rpx]">*</view>
</view>
<view>
<input
v-model="formData.name"
placeholder="请输入姓名"
confirm-type="done"
placeholder-style="color:#BABABA;font-size:28rpx;text-align:right;"
class="text-right w-[140rpx]"
/>
</view>
</view>
<view
class="flex items-center justify-between h-[100rpx] mx-[24rpx] border-b-[2rpx] border-b-solid border-[#F3F3F3]"
>
<view class="flex items-center">
<view class="text-[28rpx] text-[#000] font-[500]">性别</view>
<view class="text-[#FF5151] font-[500] leading-[1] h-[18rpx] ml-[8rpx]">*</view>
</view>
<view>
<RadioGroup v-model="formData.gender" class="custom-radio-group">
<Radio :name="1" class="custom-radio"></Radio>
<Radio :name="2" class="custom-radio"></Radio>
</RadioGroup>
</view>
</view>
<view
class="flex items-center justify-between h-[100rpx] mx-[24rpx] border-b-[2rpx] border-b-solid border-[#F3F3F3]"
>
<view class="flex items-center">
<view class="text-[28rpx] text-[#000] font-[500]">手机号</view>
<view class="text-[#FF5151] font-[500] leading-[1] h-[18rpx] ml-[8rpx]">*</view>
</view>
<view class="text-[#333] text-[28rpx]">{{ userStore.userInfo.mobile }}</view>
</view>
<view class="flex items-center justify-between h-[100rpx] mx-[24rpx]">
<view class="flex items-center">
<view class="text-[28rpx] text-[#000] font-[500]">就读学校</view>
<view class="text-[#FF5151] font-[500] leading-[1] h-[18rpx] ml-[8rpx]">*</view>
</view>
<view class="">
<input
v-model="formData.school"
placeholder="请输入您的就读学校"
confirm-type="done"
placeholder-style="color:#BABABA;font-size:28rpx;text-align:right;"
class="text-right w-[252rpx]"
/>
</view>
</view>
</form>
</view>
<view class="p-[24rpx] bg-[#fff] mx-[32rpx] mt-[24rpx] rounded-[20rpx]">
<input
v-model="formData.invitedCode"
placeholder="大成联盟邀请码"
confirm-type="done"
:maxlength="4"
placeholder-style="color:#999;font-size:28rpx;"
class="text-center h-[86rpx] bg-[#F5F5F5] rounded-[16rpx]"
@input="handleInviteCode"
/>
<view class="text-[#666] text-[24rpx] text-center mt-[10rpx]">
输入邀请码获取免费AI报告解读
</view>
</view>
<button
class="w-[560rpx]! h-[88rpx]! rounded-[44rpx] font-500 text-[32rpx] text-white! flex items-center justify-center mt-[80rpx]"
:class="'bg-[#1580FF]!'"
@click="handleSubmit"
>
提交
</button>
</view>
</view>
</template>
<script lang="ts" setup>
import Radio from './components/radio-group/Radio.vue'
import RadioGroup from './components/radio-group/RadioGroup.vue'
import { useUserStore } from '@/store'
import { savePerfectInfo, verifyInviteCode } from '@/service/index/api'
const userStore = useUserStore()
const formData = ref({
name: userStore.userInfo.nickname,
gender: userStore.userInfo.sex || 1,
school: userStore.userInfo.estimatedAchievement.schoolName,
invitedCode: userStore.userInfo.estimatedAchievement.vipCode,
})
const invitedCodeFlag = ref(false)
const handleSubmit = () => {
if (!formData.value.name) {
uni.showToast({
title: '请输入昵称',
icon: 'error',
mask: true,
})
return
}
if (!formData.value.school) {
uni.showToast({
title: '请输入学校',
icon: 'error',
mask: true,
})
return
}
savePerfectInfo({
nickName: formData.value.name,
schoolName: formData.value.school,
sex: formData.value.gender,
inviteCode: formData.value.invitedCode,
}).then((resp) => {
if (resp.code === 200) {
userStore.setEstimatedAchievement({ init: true })
uni.switchTab({
url: '/pages/home/index/index',
})
} else {
uni.showToast({
title: resp.message,
icon: 'error',
mask: true,
})
}
})
}
const handleInviteCode = () => {
if (formData.value.invitedCode.length === 4) {
verifyInviteCode({ code: formData.value.invitedCode }).then((resp) => {
if (resp.code === 200) {
invitedCodeFlag.value = resp.result as boolean
}
})
} else {
invitedCodeFlag.value = false
}
}
const handleLogout = () => {
userStore.clearUserInfo()
uni.switchTab({
url: '/pages/home/index/index',
})
}
const instance = getCurrentInstance()
onUnload(() => {
if (!userStore.userInfo.estimatedAchievement.init) {
handleLogout()
}
}, instance)
</script>
<style lang="scss" scoped>
:deep(.custom-radio-group) {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
background-color: #fff;
justify-content: center;
}
:deep(.custom-radio) {
width: 108rpx;
height: 60rpx;
background-color: #fff;
border-radius: 32rpx;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid #ccc;
color: #999;
.radio-wrapper {
padding: 0;
width: 100%;
height: 100%;
}
.radio {
display: none;
}
.radio-label {
margin-left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.radio-label--active {
background-color: rgba(21, 128, 255, 0.1) !important;
border-color: #1580ff !important;
border: 2rpx solid #1580ff;
border-radius: 32rpx;
}
}
</style>

View File

@ -1,7 +0,0 @@
<template>
<web-view src="https://api.static.ycymedu.com/lwxy.html" />
</template>
<script lang="ts" setup></script>
<style scoped lang="scss"></style>

View File

@ -1,7 +0,0 @@
<template>
<web-view src="https://api.static.ycymedu.com/lwuser.html" />
</template>
<script lang="ts" setup></script>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,5 @@
{ {
"name": "六志愿", "name": "六志愿",
"appid": "H57F2ACE4", "appid": "H57F2ACE4",
"description": "", "description": "",
"versionName": "1.0.0", "versionName": "1.0.0",
@ -55,21 +55,18 @@
}, },
"quickapp": {}, "quickapp": {},
"mp-weixin": { "mp-weixin": {
"appid": "wx05e75004e657527c", "appid": "wxa2abb91f64032a2b",
"setting": { "setting": {
"urlCheck": false "urlCheck": false
}, },
"usingComponents": true, "usingComponents": true,
"optimization": { "optimization": {
"subPackages": true "subPackages": true
}, }
"requiredPrivateInfos": [
"getLocation"
],
"lazyCodeLoading": "requiredComponents"
}, },
"mp-alipay": { "mp-alipay": {
"usingComponents": true "usingComponents": true,
"styleIsolation": "shared"
}, },
"mp-baidu": { "mp-baidu": {
"usingComponents": true "usingComponents": true

View File

@ -1,83 +0,0 @@
export const renderEchart = ({ echart, echarts, pieChartData }) => {
const typeColorMap = {
: { color: '#EB5241', simpleName: '冲' },
: { color: '#F0BA16', simpleName: '稳' },
: { color: '#15C496', simpleName: '保' },
}
const formattedData = pieChartData.value.map((item) => ({
...item,
itemStyle: {
color: typeColorMap[item.name]?.color,
},
label: {
formatter: (params) => typeColorMap[params.name]?.simpleName || params.name,
},
}))
echart.value.init(echarts, (chart) => {
let option = {
tooltip: {
trigger: 'item',
formatter: '{b}: {c} ({d}%)',
},
legend: {
orient: 'horizontal',
bottom: 8,
left: 'center',
icon: 'circle',
itemWidth: 10,
itemHeight: 10,
itemGap: 20,
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
data: formattedData,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
label: {
formatter: (params) => typeColorMap[params.name]?.simpleName || params.name,
},
},
],
graphic: {
elements: [
{
type: 'text',
left: 'center',
top: '40%',
style: {
text: '适合的大学',
fontSize: 12,
fill: '#1F2329',
textAlign: 'center',
textVerticalAlign: 'middle',
},
},
{
type: 'text',
left: 'center',
top: '50%',
style: {
text: formattedData.reduce((acc, curr) => acc + curr.value, 0),
fontSize: 24,
fill: '#1F2329',
textAlign: 'center',
textVerticalAlign: 'middle',
fontWeight: 'bold',
},
},
],
},
}
chart.setOption(option)
})
}

View File

@ -1,118 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationBarTitleText: 'AI智能填报',
},
needLogin: true,
}
</route>
<template>
<view class="bg-[#FAFAFA] h-screen flex flex-col">
<view class="text-[#000] text-[24rpx] p-[32rpx]">
{{ userInfo.estimatedAchievement.expectedScore }} &nbsp;&nbsp;{{
userInfo.estimatedAchievement.subjectGroup.split(',').join('/')
}}
</view>
<view class="mx-[32rpx] h-[426rpx] bg-[#fff] rounded-[16rpx]">
<l-echart ref="echart"></l-echart>
</view>
<view class="mt-[32rpx] mx-[32rpx] bg-[#fff] rounded-[16rpx] p-[32rpx]">
<text class="text-[#000] text-[24rpx]">
{{ pieChartData.reduce((total, cur) => total + cur.value, 0) }}所适合我的大学
</text>
<view class="pl-[30rpx] mt-[22rpx] grid grid-cols-3 gap-x-[150rpx] gap-y-[30rpx]">
<view
class="flex flex-col items-center gap-[8rpx]"
v-for="item in universities"
:key="item.name"
>
<text class="text-[56rpx] text-[#1F2329] font-semibold">{{ item.count }}</text>
<text class="text-[24rpx] text-[#B6B6B6]">{{ item.name }}</text>
</view>
</view>
</view>
<view class="mt-[32rpx] mx-[32rpx] bg-[#FEF0F0] rounded-[16rpx] p-[32rpx]">
<view
class="text-[#F56C6C] text-[28rpx] flex items-center gap-[8rpx] mb-[16rpx] font-semibold"
>
<view class="i-carbon-volume-down text-[32rpx]"></view>
说明
</view>
<view class="text-[22rpx] text-[#F56C6C] flex flex-col leading-[1.5]">
<text>
1.
本平台基于历史分数及等效位次进行志愿推荐和风险评估由于志愿填报本身存在不确定性请谨慎参考
</text>
<text>
2.在正式填报时院校/专业名称及代码请务必与官方信息平台核对若发现差异则以官方数据为准本平台数据仅供参考
</text>
</view>
</view>
<view class="mt-auto bg-[#fff] p-[32rpx] box-shadow px-[32rpx] pt-[32rpx] pb-safe">
<view
class="text-[#fff] text-[32rpx] rounded-[8rpx] bg-[#1580FF] text-center h-[80rpx] flex items-center justify-center"
@click="navigatorTo"
>
智能选校
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { useUserStore } from '@/store/user'
import { aiPreview } from '@/service/index/api'
import lEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
import { renderEchart } from './echartRender'
const echarts = require('../uni_modules/lime-echart/static/echarts.min')
const userStore = useUserStore()
const userInfo = computed(() => userStore.userInfo)
const echart = ref(null)
const pieChartData = ref([])
const universities = ref([])
onLoad(() => {
aiPreview({
location: userInfo.value.estimatedAchievement.provinceCode,
p: userInfo.value.estimatedAchievement.sp,
score: userInfo.value.estimatedAchievement.expectedScore,
subjects: userInfo.value.estimatedAchievement.subjectGroup.split(','),
}).then((res) => {
let _result = res.result as {
pieChats: { name: string; value: number }[]
universities: { name: string; count: number }[]
}
pieChartData.value = _result.pieChats
universities.value = _result.universities
renderEchart({ echart, echarts, pieChartData })
})
})
const navigatorTo = () => {
uni.navigateTo({
url: '/pages-sub/home/wishesList/index?typeName=智能填报&editType=add',
})
}
onBeforeMount(() => {
if (echart.value) {
echart.value.dispose()
}
})
onShow(() => {
userStore.clearWishListId()
userStore.clearWishList()
})
</script>
<style lang="scss" scoped>
.box-shadow {
box-shadow: 0rpx -8rpx 8rpx 0rpx rgba(225, 225, 225, 0.2);
}
</style>

View File

@ -1,121 +0,0 @@
<template>
<CheckboxGroup v-model="defValue" checked-color="#1580FF" @change="handleChange" v-bind="$attrs">
<Checkbox
v-for="item in list"
:key="item[valueKey]"
:name="item[valueKey]"
cell
shape="button"
class="custom-checkbox"
:style="checkboxStyle"
>
{{ item[labelKey] }}
</Checkbox>
</CheckboxGroup>
</template>
<script lang="ts" setup>
import Checkbox from './Checkbox.vue'
import CheckboxGroup from './CheckboxGroup.vue'
const props = defineProps({
list: {
type: Array,
default: () => [],
},
labelKey: {
type: String,
default: 'name',
},
valueKey: {
type: String,
default: 'code',
},
defaultValue: {
type: Array<string>,
default: () => [],
},
width: {
type: [String, Number],
default: '216rpx',
},
height: {
type: [String, Number],
default: '60rpx',
},
})
defineOptions({
options: {
styleIsolation: 'shared',
},
})
const emits = defineEmits(['change'])
const defValue = ref<string[]>([])
//
onMounted(() => {
if (props.defaultValue?.length) {
defValue.value = [...props.defaultValue]
}
})
const handleChange = (val: unknown) => {
defValue.value = val as string[]
emits('change', val)
}
watch(
() => props.defaultValue,
(newVal) => {
defValue.value = [...newVal]
},
)
//
const checkboxStyle = computed(() => {
const width = typeof props.width === 'number' ? `${props.width}rpx` : props.width
const height = typeof props.height === 'number' ? `${props.height}rpx` : props.height
return {
'--checkbox-width': width,
'--checkbox-height': height,
}
})
</script>
<style lang="scss" scoped>
:deep(.custom-checkbox) {
//
--checkbox-width: 216rpx;
--checkbox-height: 60rpx;
--checkbox-bg: #f7f8fa;
--checkbox-radius: 8rpx;
.checkbox {
width: var(--checkbox-width);
height: var(--checkbox-height);
min-width: var(--checkbox-width);
background-color: var(--checkbox-bg);
border-radius: var(--checkbox-radius);
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid var(--checkbox-bg);
}
.checkbox__icon {
display: none;
}
}
:deep(.checkbox-group) {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
padding: 32rpx 16rpx 16rpx;
}
:deep(.checkbox-active) {
border-color: #1580ff !important;
.checkbox__label {
color: #1580ff !important;
}
}
</style>

View File

@ -1,133 +0,0 @@
<template>
<view
class="checkbox"
:class="{
'checkbox--disabled': isDisabled,
'checkbox-active': isChecked,
'checkbox-disabled': isDisabled,
}"
@click="handleClick"
>
<view class="checkbox__icon" :class="{ 'checkbox__icon--checked': isChecked }">
<text v-if="isChecked" class="i-carbon-checkmark checkbox__icon-check"></text>
</view>
<view class="checkbox__label">
<slot>{{ label }}</slot>
</view>
</view>
</template>
<script lang="ts" setup>
import { computed, inject } from 'vue'
const props = defineProps({
name: {
type: [String, Number],
required: true,
},
label: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['change'])
interface CheckboxGroupContext {
modelValue: ComputedRef<any[]>
disabled: ComputedRef<boolean>
max: ComputedRef<number>
selectedCount: ComputedRef<number>
toggleOption: (option: { value: string | number }) => void
}
// checkbox group
const checkboxGroup = inject<CheckboxGroupContext>('checkboxGroup', {
modelValue: computed(() => []),
disabled: computed(() => false),
max: computed(() => 0),
selectedCount: computed(() => 0),
toggleOption: () => {},
})
//
const isChecked = computed(() => {
const modelValue = checkboxGroup.modelValue.value
return modelValue.includes(props.name)
})
//
const isDisabled = computed(() => {
const max = checkboxGroup.max.value
const selectedCount = checkboxGroup.selectedCount.value
// group
return (
props.disabled ||
checkboxGroup.disabled.value ||
(max > 1 && !isChecked.value && selectedCount >= max)
)
})
//
const handleClick = () => {
if (isDisabled.value) return
checkboxGroup.toggleOption({
value: props.name,
})
}
</script>
<style scoped>
.checkbox {
display: inline-flex;
align-items: center;
cursor: pointer;
font-size: 28rpx;
}
.checkbox--disabled {
cursor: not-allowed;
opacity: 0.5;
}
.checkbox__icon {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #dcdfe6;
border-radius: 4rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 8rpx;
transition: all 0.2s;
}
.checkbox__icon--checked {
background-color: #0083ff;
border-color: #0083ff;
}
.checkbox__icon-check {
color: #fff;
font-size: 32rpx;
}
.checkbox__label {
line-height: 1;
}
.checkbox-active {
background-color: #0083ff;
border-color: #0083ff;
}
.checkbox-disabled {
opacity: 0.5;
cursor: not-allowed !important;
}
</style>

View File

@ -1,72 +0,0 @@
<template>
<view class="checkbox-group">
<slot></slot>
</view>
</template>
<script lang="ts" setup>
import { provide, computed } from 'vue'
const props = defineProps({
modelValue: {
type: Array,
default: () => [],
},
max: {
type: Number,
default: 0,
},
disabled: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue', 'change'])
//
const innerValue = computed(() => props.modelValue)
//
const toggleOption = (option: { label: string; value: string | number }) => {
const currentValue = innerValue.value
const index = currentValue.indexOf(option.value)
let newValue = [...currentValue]
if (index === -1) {
if (props.max === 1) {
newValue = [option.value]
} else if (props.max && currentValue.length >= props.max) {
uni.showToast({
title: `最多只能选择${props.max}`,
icon: 'none',
})
return
} else {
newValue.push(option.value)
}
} else {
newValue.splice(index, 1)
}
emit('update:modelValue', newValue)
emit('change', newValue)
}
// checkbox
provide('checkboxGroup', {
modelValue: computed(() => props.modelValue),
disabled: computed(() => props.disabled),
max: computed(() => props.max),
selectedCount: computed(() => props.modelValue.length),
toggleOption,
})
</script>
<style scoped lang="scss">
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
</style>

View File

@ -1,172 +0,0 @@
<template>
<view class="drop-menu" ref="dropMenuRef">
<view class="drop-menu__bar">
<view
v-for="(item, index) in titles"
:key="index"
class="drop-menu__item"
:class="{
'drop-menu__item--active': index === activeIndex || item.activation,
'drop-menu__disable': item.disabled,
}"
@click="handleTitleClick(index)"
>
<text class="drop-menu__title">{{ item.title }}</text>
<text
class="drop-menu__arrow i-carbon-chevron-down"
:class="{ 'drop-menu__arrow--active': index === activeIndex }"
></text>
</view>
</view>
<view class="drop-menu__content-wrapper">
<slot></slot>
</view>
<view
v-if="activeIndex !== -1"
class="drop-menu__mask"
:style="{ top: maskTop }"
@click="closeDropMenu"
></view>
</view>
</template>
<script lang="ts" setup>
import { ref, provide } from 'vue'
const props = defineProps({
zIndex: {
type: Number,
default: 10,
},
duration: {
type: Number,
default: 200,
},
direction: {
type: String,
default: 'down',
},
})
//
const titles = ref<any[]>([])
//
const activeIndex = ref(-1)
const maskTop = ref('88px')
//
const addTitle = (options) => {
titles.value.push({ ...options })
}
const instance = getCurrentInstance()
const dropMenuRef = ref()
//
const handleTitleClick = (index: number) => {
if (titles.value[index].disabled) {
return
}
//
if (activeIndex.value === index) {
activeIndex.value = -1
} else {
//
activeIndex.value = index
}
const query = uni.createSelectorQuery().in(instance.proxy)
query
.select('.drop-menu')
.boundingClientRect((data: { top: number }) => {
maskTop.value = `${data.top}px`
})
.exec()
}
//
const closeDropMenu = () => {
activeIndex.value = -1
}
//
provide('dropMenu', {
activeIndex,
addTitle,
closeDropMenu,
zIndex: props.zIndex,
duration: props.duration,
direction: props.direction,
titles, // titles
})
defineExpose({
closeDropMenu,
})
</script>
<style scoped lang="scss">
.drop-menu {
position: relative;
background: #fff;
z-index: 10;
}
.drop-menu__bar {
position: relative;
display: flex;
height: 88rpx;
background: #fff;
z-index: 12;
}
.drop-menu__item {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.drop-menu__item--active {
color: #0083ff;
}
.drop-menu__title {
font-size: 28rpx;
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.drop-menu__arrow {
font-size: 20rpx;
margin-left: 8rpx;
transition: transform 0.2s;
}
.drop-menu__arrow--active {
transform: rotate(180deg);
}
.drop-menu__content-wrapper {
position: relative;
width: 100%;
}
.drop-menu__mask {
position: fixed;
width: 100%;
left: 0;
right: 0;
top: 88rpx;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
z-index: 9;
}
.drop-menu__disable {
color: #999;
}
</style>

View File

@ -1,217 +0,0 @@
<template>
<view
class="drop-menu-item"
:class="[customClass, { 'drop-menu-item--show': isShow }]"
:style="{
'z-index': zIndex,
'transition-duration': `${duration}ms`,
}"
>
<view class="drop-menu-item__wrapper" :class="{ 'drop-menu-item__wrapper--show': isShow }">
<!-- 默认选项列表 -->
<scroll-view v-if="!$slots.default" scroll-y class="drop-menu-item__content">
<view class="drop-menu-item__option-list">
<view
v-for="(option, index) in options"
:key="index"
class="drop-menu-item__option"
:class="{ 'drop-menu-item__option--active': isOptionActive(option) }"
@click="handleOptionClick(option)"
>
<text class="drop-menu-item__text">{{ getOptionText(option) }}</text>
<text v-if="isOptionActive(option)" class="drop-menu-item__icon"></text>
</view>
</view>
</scroll-view>
<!-- 自定义内容插槽 -->
<view v-else class="drop-menu-item__custom-content">
<slot></slot>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { ref, inject, onMounted, computed, watch } from 'vue'
const props = defineProps({
modelValue: {
type: [String, Number, Object],
default: '',
},
title: {
type: String,
required: true,
},
options: {
type: Array,
default: () => [],
},
labelKey: {
type: String,
default: 'text',
},
valueKey: {
type: String,
default: 'value',
},
customClass: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
activation: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue', 'change', 'open'])
//
const { activeIndex, addTitle, closeDropMenu, zIndex, duration, direction, titles } = inject(
'dropMenu',
) as any
//
const itemIndex = ref(-1)
//
const isShow = computed(() => activeIndex.value === itemIndex.value)
//
watch(isShow, (newVal) => {
if (newVal) {
emit('open')
}
})
//
const getOptionText = (option: any) => {
if (typeof option === 'object' && props.labelKey) {
return option[props.labelKey]
}
return option
}
//
const getOptionValue = (option: any) => {
if (typeof option === 'object' && props.valueKey) {
return option[props.valueKey]
}
return option
}
//
const isOptionActive = (option: any) => {
const optionValue = getOptionValue(option)
return props.modelValue === optionValue
}
//
const handleOptionClick = (option: any) => {
const value = getOptionValue(option)
emit('update:modelValue', value)
emit('change', value)
closeDropMenu()
}
//
onMounted(() => {
//
itemIndex.value = titles.value.length
//
addTitle({ title: props.title, disabled: props.disabled, activation: props.activation })
})
//
watch(
() => props.title,
(newTitle) => {
//
if (titles.value[itemIndex.value].title !== newTitle) {
titles.value[itemIndex.value].title = newTitle
}
},
{ immediate: false },
)
watch(
() => props.activation,
(newVal) => {
titles.value[itemIndex.value].activation = newVal
},
)
</script>
<style scoped>
.drop-menu-item {
position: relative;
width: 100%;
}
.drop-menu-item__wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
background: #fff;
transform: translateY(-5px);
transition: all 0.25s ease;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
opacity: 0;
visibility: hidden;
z-index: 11;
}
.drop-menu-item__wrapper--show {
transform: translateY(0);
opacity: 1;
visibility: visible;
}
.drop-menu-item__content {
max-height: 400rpx;
}
.drop-menu-item__custom-content {
width: 100%;
background: #fff;
transform-origin: top;
}
.drop-menu-item__option-list {
padding: 12rpx 0;
}
.drop-menu-item__option {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 32rpx;
line-height: 1.2;
cursor: pointer;
}
.drop-menu-item__option:active {
background-color: #f2f2f2;
}
.drop-menu-item__option--active {
color: #0083ff;
}
.drop-menu-item__text {
font-size: 28rpx;
}
.drop-menu-item__icon {
font-size: 32rpx;
color: #0083ff;
}
</style>

View File

@ -1,200 +0,0 @@
<template>
<view class="navbar">
<!-- 状态栏占位 -->
<view
v-if="safeAreaInsetTop"
class="status-bar"
:style="{ height: statusBarHeight + 'px', backgroundColor: bgColor }"
></view>
<!-- 导航栏主体 -->
<view
class="navbar-content"
:class="[contentClass, fixed ? 'navbar-fixed' : '', bordered ? 'navbar-border' : '']"
:style="{
backgroundColor: bgColor,
height: navHeight + 'px',
top: fixed ? (safeAreaInsetTop ? statusBarHeight : 0) + 'px' : '0',
}"
>
<!-- 左侧区域 -->
<view class="navbar-left" @click="handleClickLeft">
<view v-if="leftArrow" class="back-icon">
<view class="i-carbon-chevron-left text-[40rpx] text-[#333] font-semibold icon-class" />
</view>
<slot name="left"></slot>
</view>
<!-- 中间标题区域 -->
<view class="navbar-title">
<slot name="title">
<text class="title-text">{{ title }}</text>
</slot>
</view>
<!-- 右侧区域 -->
<view class="navbar-right">
<slot name="right"></slot>
</view>
</view>
<!-- 占位元素 -->
<view
v-if="placeholder && fixed"
:style="{
height: `${navHeight}px`,
backgroundColor: bgColor,
}"
></view>
<slot name="background"></slot>
</view>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
const props = defineProps({
title: {
type: String,
default: '',
},
leftArrow: {
type: Boolean,
default: false,
},
fixed: {
type: Boolean,
default: false,
},
placeholder: {
type: Boolean,
default: false,
},
bordered: {
type: Boolean,
default: true,
},
safeAreaInsetTop: {
type: Boolean,
default: true,
},
bgColor: {
type: String,
default: '#ffffff',
},
contentClass: {
type: String,
default: 'justify-between',
},
})
const emit = defineEmits(['clickLeft'])
//
const systemInfo = uni.getWindowInfo()
const deviceInfo = uni.getDeviceInfo()
const statusBarHeight = systemInfo.statusBarHeight || 0
//
const navHeight = computed(() => {
//
const { screenWidth } = systemInfo
const { platform } = deviceInfo
// pxrpx
const ratio = 750 / screenWidth
//
if (platform === 'ios') {
return 88 / ratio // iOS 44ptpx
} else if (platform === 'android') {
return 96 / ratio // Android 48dppx
} else {
return 88 / ratio //
}
})
const handleClickLeft = () => {
emit('clickLeft')
}
</script>
<style scoped>
.navbar {
width: 100%;
}
.status-bar {
width: 100%;
background-color: inherit;
}
.navbar-content {
width: 100%;
display: flex;
align-items: center;
/* justify-content: space-between; */
padding: 0 16rpx;
box-sizing: border-box;
background-color: #fff;
}
.navbar-fixed {
position: fixed;
left: 0;
width: 100%;
z-index: 99;
}
.navbar-border {
border-bottom: 1rpx solid #eee;
}
.navbar-left {
display: flex;
align-items: center;
height: 100%;
}
.back-icon {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.navbar-title {
/* flex: 1; */
text-align: center;
overflow: hidden;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.title-text {
font-size: 34rpx;
color: #333;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.navbar-right {
display: flex;
align-items: center;
min-width: 52rpx;
justify-content: flex-end;
height: 100%;
}
.back-text {
font-size: 48rpx;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #333;
}
</style>

View File

@ -1,195 +0,0 @@
<template>
<view class="custom-picker">
<view class="picker-mask" @touchmove.stop.prevent></view>
<picker-view
:immediate-change="true"
:value="currentIndex"
:indicator-style="indicatorStyle"
:style="{
border: 'none',
'border-top': 'none',
'border-bottom': 'none',
}"
@change="handleChange"
class="picker-view"
:mask-class="'picker-mask'"
:indicator-class="'picker-indicator'"
>
<picker-view-column class="border-none">
<view
v-for="(item, index) in formattedList"
:key="index"
class="picker-item"
:class="{ 'picker-item-selected': currentIndex[0] === index }"
>
{{ item }}
</view>
</picker-view-column>
</picker-view>
<!-- <view class="picker-indicator-line"></view> -->
</view>
</template>
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
const props = defineProps({
modelValue: {
type: [String, Number, Object],
default: '',
},
list: {
type: Array,
required: true,
default: () => [],
},
valueKey: {
type: String,
default: '',
},
labelKey: {
type: String,
default: '',
},
indicatorStyle: {
type: String,
default: 'height: 50px;',
},
})
const emit = defineEmits(['update:modelValue', 'change'])
//
const formattedList = computed(() => {
if (!props.list.length) return []
// ['123', '456']
if (typeof props.list[0] !== 'object') {
return props.list
}
// 使labelKey
if (props.labelKey) {
return props.list.map((item) => item[props.labelKey])
}
// 使valueKey
if (props.valueKey) {
return props.list.map((item) => item[props.valueKey])
}
//
return props.list
})
//
const currentIndex = computed(() => {
if (!props.modelValue || !props.list.length) return [0]
let targetValue = props.modelValue
if (typeof props.list[0] === 'object' && props.valueKey) {
targetValue = props.modelValue[props.valueKey]
}
const index = props.list.findIndex((item) => {
if (typeof item === 'object' && props.valueKey) {
return item[props.valueKey] === targetValue
}
return item === targetValue
})
return [index > -1 ? index : 0]
})
//
const handleChange = (e: any) => {
const index = e.detail.value[0]
const selectedItem = props.list[index]
let value = selectedItem
if (typeof selectedItem === 'object' && props.valueKey) {
value = selectedItem[props.valueKey]
}
emit('update:modelValue', value)
emit('change', {
value,
index,
item: selectedItem,
})
}
</script>
<style scoped>
.custom-picker {
width: 100%;
height: 400rpx;
position: relative;
background-color: #fff;
}
.picker-view {
width: 100%;
height: 100%;
}
/* 覆盖picker-view的默认边框 */
.picker-view :deep(.uni-picker-view-indicator),
.picker-view :deep(.uni-picker-view-column),
.picker-view :deep(.uni-picker-view-group) {
border: none !important;
border-top: none !important;
border-bottom: none !important;
}
.picker-mask {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
pointer-events: none;
z-index: 2;
}
.picker-indicator {
height: 112rpx;
}
.picker-indicator-line {
position: absolute;
left: 0;
right: 0;
top: 50%;
margin-top: -40rpx;
height: 112rpx;
pointer-events: none;
z-index: 1;
}
.picker-item {
text-align: center;
font-size: 34rpx;
color: #7c7c7c;
transition: all 0.2s;
display: flex;
justify-content: center;
align-items: center;
}
.picker-item-selected {
color: #000;
font-weight: 500;
transform: scale(1.05);
}
/* 添加触摸反馈 */
.picker-view :deep(.uni-picker-view-wrapper) {
-webkit-overflow-scrolling: touch;
}
.picker-view :deep(.uni-picker-view-content) {
touch-action: pan-y;
}
</style>

View File

@ -1,132 +0,0 @@
export const initRankAreaEchart = ({
echart,
echarts,
xAxisData,
yAxisData,
Score,
currentCount,
areaIndex,
}) => {
echart.value.init(echarts, (chart) => {
let option = {
xAxis: {
type: 'category',
data: xAxisData,
axisLine: {
lineStyle: {
color: '#E5E5E5',
},
},
axisLabel: {
color: '#999999',
},
},
yAxis: {
type: 'value',
show: false,
},
grid: {
left: '16',
right: '16',
containLabel: false,
},
series: [
{
data: yAxisData,
type: 'line',
smooth: 0.6,
smoothMonotone: 'x',
symbol: 'none',
lineStyle: {
width: 2,
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
{
offset: 0,
color: 'rgba(30, 231, 255, 1)',
},
{
offset: 0.33,
color: 'rgba(36, 154, 255, 1)',
},
{
offset: 0.66,
color: 'rgba(111, 66, 251, 1)',
},
{
offset: 1,
color: 'rgba(111, 66, 251, 1)',
},
]),
},
areaStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(17,126,255,0.16)',
},
{
offset: 1,
color: 'rgba(17,128,255,0)',
},
]),
},
markPoint: {
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#4080FF',
borderColor: '#259BFF',
borderWidth: 2,
},
data: [
{
xAxis: `${Score}`,
yAxis: `${currentCount}`,
label: {
show: true,
position: 'top',
color: '#4080FF',
fontSize: 12,
},
},
],
},
markArea: {
itemStyle: {
color: 'rgba(64, 128, 255, 0.1)',
},
data: [
[
{
xAxis: areaIndex + 30,
},
{
xAxis: areaIndex - 30,
},
],
],
},
markLine: {
symbol: ['none', 'none'],
lineStyle: {
type: 'dashed',
color: '#4080FF',
width: 1,
opacity: 0.5,
},
data: [
{
xAxis: `${Score}`,
label: {
show: false,
},
},
],
},
},
],
}
chart.setOption(option)
})
}

View File

@ -1,126 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">能力测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative mt-[40rpx] flex flex-col">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view
class="flex flex-col pt-[32rpx] mx-[24rpx] bg-[#fff] px-[30rpx] pt-[30rpx] border-class"
>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2 font-700">你的弱势能力为</text>
<text class="text-[#117CFC] text-[36rpx] z-2">
{{ studyRecord.title.replace('你的弱势能力:', '') }}
</text>
</view>
<!-- 雷达图占位 -->
<LineReport :echart-data="studyRecord.linChart" :description="studyRecord.description" />
<AbilityDimension :report-items="studyRecord.reportItems" />
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import LineReport from '../components/interestChart/LineReport.vue'
import AbilityDimension from '../components/AbilityDimension.vue'
import AiFooter from '../components/AiFooter.vue'
import { handleBack } from '../hooks/useEvaluateBack'
import { getAbilityDimension } from '@/service/index/api'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
linChart: [],
reportItems: [],
hTag: '',
})
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getAbilityDimension({ ScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
linChart: any[]
reportItems: any[]
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
.border-class {
border-radius: 20rpx 20rpx 0 0;
padding-bottom: 42rpx;
margin-bottom: -14rpx;
}
</style>

View File

@ -1,125 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">性格测评报告</text>
</template>
</Navbar>
<view class="flex-1 flex flex-col overflow-auto">
<view class="overflow-auto relative mt-[40rpx] flex-1 pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-116rpx] font-700">
<image
src="https://api.static.ycymedu.com/src/images/evaluate/bg.png"
class="header-bg"
/>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的性格类型为</text>
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
</view>
<!-- 雷达图占位 -->
<CharacterChart :linChart="studyRecord.linChart" :description="studyRecord.description" />
<DependenciesChart
:mainDomain="studyRecord.reportItem.mainDomain"
:major="studyRecord.reportItem.major"
:occupation="studyRecord.reportItem.occupation"
/>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import CharacterChart from '../components/interestChart/CharacterChart.vue'
import DependenciesChart from '../components/interestChart/DependenciesChart.vue'
import AiFooter from '../components/AiFooter.vue'
import { getMBTIDimension } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
linChart: {},
reportItem: { mainDomain: '', major: '', occupation: '' },
hTag: '',
})
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getMBTIDimension({ ScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
linChart: any
reportItem: { mainDomain: string; major: string; occupation: string }
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
</style>

View File

@ -1,123 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">兴趣测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative mt-[40rpx]">
<view class="overflow-auto relative mt-[40rpx] flex-1 pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-116rpx] font-700">
<image
src="https://api.static.ycymedu.com/src/images/evaluate/bg.png"
class="header-bg"
/>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的兴趣类型为</text>
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
</view>
<!-- 雷达图占位 -->
<InterestRadar :picData="studyRecord.picCharts" />
<!-- 类型说明 -->
<TypeDetail :reportItems="studyRecord.reportItems" />
<!-- 适合职业 -->
<IntroMajor :tag="studyRecord.hTag" />
<!-- 兴趣分析与代表人物 -->
<InterestingThings :tag="studyRecord.hTag" :description="studyRecord.description" />
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import TypeDetail from '../components/TypeDetail.vue'
import InterestRadar from '../components/interestChart/InterestRadar.vue'
import IntroMajor from '../components/IntroMajor.vue'
import { getHollandDimensionInfo } from '@/service/index/api'
import InterestingThings from '../components/InterestingThings.vue'
import AiFooter from '../components/AiFooter.vue'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({ description: '', title: '', picCharts: {}, reportItems: [], hTag: '' })
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getHollandDimensionInfo({ ScaleId: pageId.value.toString() }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
picCharts: any
reportItems: any[]
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
</style>

View File

@ -1,126 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">能力测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative mt-[40rpx] flex flex-col">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view
class="flex flex-col pt-[32rpx] mx-[24rpx] bg-[#fff] px-[30rpx] pt-[30rpx] border-class"
>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2 font-700">你的弱势能力为</text>
<text class="text-[#117CFC] text-[36rpx] z-2">
{{ studyRecord.title.replace('你的弱势能力:', '') }}
</text>
</view>
<!-- 雷达图占位 -->
<LineReport :echart-data="studyRecord.linChart" :description="studyRecord.description" />
<AbilityDimension :report-items="studyRecord.reportItems" />
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import LineReport from '../components/interestChart/LineReport.vue'
import AbilityDimension from '../components/AbilityDimension.vue'
import AiFooter from '../components/AiFooter.vue'
import { handleBack } from '../hooks/useEvaluateBack'
import { getAbilityDimension } from '@/service/index/api'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
linChart: [],
reportItems: [],
hTag: '',
})
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getAbilityDimension({ ScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
linChart: any[]
reportItems: any[]
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
.border-class {
border-radius: 20rpx 20rpx 0 0;
padding-bottom: 42rpx;
margin-bottom: -14rpx;
}
</style>

View File

@ -1,125 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">性格测评报告</text>
</template>
</Navbar>
<view class="flex-1 flex flex-col overflow-auto">
<view class="overflow-auto relative mt-[40rpx] flex-1 pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-116rpx] font-700">
<image
src="https://api.static.ycymedu.com/src/images/evaluate/bg.png"
class="header-bg"
/>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的性格类型为</text>
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
</view>
<!-- 雷达图占位 -->
<CharacterChart :linChart="studyRecord.linChart" :description="studyRecord.description" />
<DependenciesChart
:mainDomain="studyRecord.reportItem.mainDomain"
:major="studyRecord.reportItem.major"
:occupation="studyRecord.reportItem.occupation"
/>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import CharacterChart from '../components/interestChart/CharacterChart.vue'
import DependenciesChart from '../components/interestChart/DependenciesChart.vue'
import AiFooter from '../components/AiFooter.vue'
import { getMBTIDimension } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
linChart: {},
reportItem: { mainDomain: '', major: '', occupation: '' },
hTag: '',
})
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getMBTIDimension({ ScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
linChart: any
reportItem: { mainDomain: string; major: string; occupation: string }
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
</style>

View File

@ -1,123 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">兴趣测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative mt-[40rpx]">
<view class="overflow-auto relative mt-[40rpx] flex-1 pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-116rpx] font-700">
<image
src="https://api.static.ycymedu.com/src/images/evaluate/bg.png"
class="header-bg"
/>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的兴趣类型为</text>
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
</view>
<!-- 雷达图占位 -->
<InterestRadar :picData="studyRecord.picCharts" />
<!-- 类型说明 -->
<TypeDetail :reportItems="studyRecord.reportItems" />
<!-- 适合职业 -->
<IntroMajor :tag="studyRecord.hTag" />
<!-- 兴趣分析与代表人物 -->
<InterestingThings :tag="studyRecord.hTag" :description="studyRecord.description" />
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import TypeDetail from '../components/TypeDetail.vue'
import InterestRadar from '../components/interestChart/InterestRadar.vue'
import IntroMajor from '../components/IntroMajor.vue'
import { getHollandDimensionInfo } from '@/service/index/api'
import InterestingThings from '../components/InterestingThings.vue'
import AiFooter from '../components/AiFooter.vue'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({ description: '', title: '', picCharts: {}, reportItems: [], hTag: '' })
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getHollandDimensionInfo({ ScaleId: pageId.value.toString() }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
picCharts: any
reportItems: any[]
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
</style>

View File

@ -1,125 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">职业锚测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative mt-[40rpx]">
<view class="overflow-auto relative mt-[40rpx] flex-1 pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-116rpx] font-700">
<image
src="https://api.static.ycymedu.com/src/images/evaluate/bg.png"
class="header-bg"
/>
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的职业价值观</text>
<text class="text-[#117CFC] text-[40rpx] z-2">{{ studyRecord.tag }}</text>
</view>
<OpinionChart :pic-charts="studyRecord.picCharts" />
<AbilityDimension :report-items="studyRecord.reportItems" />
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import OpinionChart from '../components/interestChart/OpinionChart.vue'
import AbilityDimension from '../components/AbilityDimension.vue'
import AiFooter from '../components/AiFooter.vue'
import { handleBack } from '../hooks/useEvaluateBack'
import { getOpinionAbout } from '@/service/index/api'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
picCharts: { indicator: [], radars: [] },
reportItems: [],
tag: '',
})
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getOpinionAbout({ ScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
picCharts: { radars: any[]; indicator: any[] }
reportItems: any[]
tag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.header-bg {
width: calc(100% - 80rpx);
height: 244rpx;
position: absolute;
top: 0;
left: 40rpx;
z-index: 1;
}
.type-tag {
font-size: 24rpx;
min-width: 40rpx;
text-align: center;
}
.position-tag {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
font-size: 26rpx;
text-align: center;
}
.table-row {
align-items: center;
font-size: 26rpx;
color: #333;
}
.avatar-item image {
border: 4rpx solid #fff;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
.border-class {
border-radius: 20rpx 20rpx 0 0;
padding-bottom: 42rpx;
margin-bottom: -14rpx;
}
</style>

View File

@ -1,27 +0,0 @@
<template>
<view class="mx-[30rpx] mt-[30rpx] bg-white rounded-[20rpx] p-[30rpx]">
<TitleBar title="能力纬度详细介绍" />
<view class="flex flex-col gap-[40rpx]">
<view v-for="(item, index) in reportItems" :key="index">
<view class="text-[32rpx] text-[#000] font-700">{{ item.title }}</view>
<view class="text-[26rpx] text-[#666] mt-[6rpx]">
{{ item.resolving || item.description }}
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import TitleBar from './TitleBar.vue'
defineProps({
reportItems: {
type: Array<any>,
default: () => [],
},
})
</script>
<style lang="scss" scoped></style>

View File

@ -1,54 +0,0 @@
<template>
<!-- 底部AI智能顾问 -->
<view
class="pt-[16rpx] px-[32rpx] flex items-center justify-center bg-[#fff] pb-safe sticky bottom-0 z-999"
@click="toAiAssistant"
v-if="aiShow"
>
<view
class="rounded-[8rpx] border-[#1580FF] border-[2rpx] border-solid w-full py-[14rpx] flex items-center justify-center"
>
<image
src="https://api.static.ycymedu.com/images/btn-bottom.png"
class="w-[52rpx] h-[52rpx] mr-[10rpx]"
></image>
<text class="text-[#1580FF] text-[32rpx] font-700">智能AI顾问</text>
</view>
</view>
<view v-else class="pb-safe"></view>
</template>
<script setup lang="ts">
import { sysDictType } from '@/service/index/api'
const aiShow = ref(true)
sysDictType({ id: 619330547859525 }).then((res) => {
const { code, result } = res
const { status } = result as { status: number }
if (code === 200) {
if (status === 1) {
aiShow.value = false
} else {
aiShow.value = true
}
}
})
const props = defineProps({
pageId: {
type: Number,
default: 0,
},
pageType: {
type: Number,
default: 0,
},
})
const toAiAssistant = () => {
uni.navigateTo({
url: `/aiService-sub/index/index?id=${props.pageId}&type=${props.pageType}`,
})
}
</script>

View File

@ -1,37 +0,0 @@
<template>
<view
class="text-[26rpx] text-[#000] mx-[24rpx] bg-[#fff] flex flex-col px-[20rpx] gap-[10rpx] pb-[20rpx] custom-class"
>
<view class="flex gap-[10rpx] w-full">
<view class="w-[94rpx] py-[12rpx] bg-color text-center">类型</view>
<view class="py-[12rpx] text-center bg-color flex-1">详解</view>
</view>
<view class="flex gap-[10rpx] w-full" v-for="(item, index) in reportItems" :key="index">
<view class="w-[94rpx] py-[12rpx] bg-color text-center">
<view>{{ item.tag }}</view>
<view>{{ item.title }}</view>
</view>
<view class="py-[22rpx] px-[14rpx] text-start bg-color flex-1">{{ item.resolving }}</view>
</view>
</view>
</template>
<script setup lang="ts">
const props = defineProps({
reportItems: {
type: Array<any>,
default: () => [],
},
})
</script>
<style lang="scss" scoped>
.bg-color {
background-color: #f5faff;
border-radius: 8rpx;
}
.custom-class {
border-radius: 0 0 20rpx 20rpx;
}
</style>

View File

@ -1,60 +0,0 @@
<template>
<view class="interest-analysis mx-[30rpx] mt-[30rpx] bg-white rounded-[20rpx] p-[30rpx]">
<TitleBar title="兴趣分析与代表人物" />
<text class="text-[26rpx] text-[#666] leading-[40rpx] mb-[30rpx] block">
{{ description }}
</text>
<view class="flex items-center gap-[10rpx] mb-[16rpx]">
<view class="w-[5rpx] h-[30rpx] bg-[#1580FF]"></view>
<text class="text-[#1580FF] text-[32rpx]">代表人物</text>
<text class="text-[#999] text-[24rpx]">以下代表人物仅作为参考</text>
</view>
<view class="avatars-list grid grid-cols-4 gap-x-[52rpx] gap-y-[18rpx]">
<view
class="avatar-item flex flex-col items-center"
v-for="(person, index) in personList"
:key="index"
>
<image
:src="person.avatarUrl"
class="w-[120rpx] h-[120rpx] rounded-full"
mode="aspectFill"
></image>
<text class="mt-[10rpx] text-[26rpx] text-[28rpx] font-normal text-center">
{{ person.nickName }}
</text>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { getTagMapPerson } from '@/service/index/api'
import TitleBar from './TitleBar.vue'
const props = defineProps({
tag: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
})
const personList = ref([])
watch(
() => props.tag,
(newV) => {
getTagMapPerson({ tag: newV }).then((resp) => {
if (resp.code === 200) {
personList.value = resp.result as any[]
}
})
},
)
</script>

View File

@ -1,53 +0,0 @@
<template>
<view class="mx-[30rpx] mt-[30rpx] bg-white rounded-[20rpx] p-[30rpx]">
<TitleBar title="推荐专业" />
<text class="text-[24rpx] text-[#999]">以下专业仅作为参考</text>
<view class="w-full">
<view class="flex py-[15rpx] px-[36rpx] bg-[#F5FAFF]">
<text class="w-[129rpx] text-center font-bold">专业大类</text>
<text class="flex-1 text-center font-bold">专业类</text>
<text class="flex-1 text-center font-bold">专业名称</text>
</view>
<view
:class="`flex py-[15rpx] text-[#333] text-[24rpx] px-[36rpx] ${index % 2 === 0 ? 'bg-[#fff]' : 'bg-[#F5FAFF]'}`"
v-for="(major, index) in majorList"
:key="index"
>
<text class="w-[129rpx] text-center">{{ major.tradeName }}</text>
<text class="flex-1 text-center">{{ major.categoryName }}</text>
<text class="flex-1 text-center">{{ major.name }}</text>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { getTagMapPro } from '@/service/index/api'
import TitleBar from './TitleBar.vue'
const props = defineProps({
tag: {
type: String,
default: '',
},
})
const majorList = ref([])
watch(
() => props.tag,
(newV) => {
getTagMapPro({ tag: newV }).then((resp) => {
if (resp.code === 200) {
majorList.value = resp.result as any[]
}
})
},
)
</script>
<style lang="scss" scoped>
@import '@/pages-evaluation-sub/styles/parallelogram.scss';
</style>

View File

@ -1,48 +0,0 @@
<template>
<view class="mt-[30rpx] bg-white rounded-[20rpx] p-[30rpx]">
<TitleBar :title="title" />
<view v-for="(item, index) in items" :key="index" class="suggestion-item">
<view class="text-[32rpx] font-700">{{ item.title }}</view>
<view class="mt-[20rpx] text-left" v-for="sonItem in item.items">
<view class="text-[#000] text-[26rpx] font-700">{{ sonItem.title }}</view>
<view class="mt-[10rpx] text-[26rpx] text-[#666]">
{{ sonItem.description }}
</view>
</view>
<view class="text-[26rpx] font-400 mt-[10rpx] text-[#666]">
{{ item.description instanceof Array ? item.description.join(',') : item.description }}
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import TitleBar from './TitleBar.vue'
defineProps({
items: {
type: Array<{
title: string
description?: string | []
items?: { title: string; description?: string }[]
}>,
default: () => [],
},
title: {
type: String,
default: '',
},
})
</script>
<style lang="scss" scoped>
.suggestion-item {
&:not(:last-child) {
margin-bottom: 50rpx;
}
&:first-child {
margin-top: 30rpx;
}
}
</style>

View File

@ -1,37 +0,0 @@
<template>
<view class="mt-[30rpx] bg-white rounded-[20rpx] p-[30rpx]">
<TitleBar :title="title" />
<view class="text-[26rpx] text-[#666] mt-[10rpx] text-left">
<text
class="text-[22rpx] px-[12rpx] py-[4rpx] rounded-[20rpx] bg-[rgba(250,142,35,0.15)] text-[#FA8E23]"
>
{{ item.notes }}
</text>
<view class="mt-[20rpx] text-left">
<view class="text-[#000] text-[26rpx] font-700">学习风格表现</view>
<view class="mt-[10rpx]" v-for="(sonItem, index) in item.learning_performance" :key="index">
{{ sonItem }}
</view>
</view>
<view class="mt-[20rpx] text-left">
<view class="text-[#000] text-[26rpx] font-700">学习风格特点</view>
<view class="mt-[10rpx]" v-for="(sonItem, index) in item.features" :key="index">
{{ sonItem }}
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import TitleBar from './TitleBar.vue'
defineProps({
item: {
type: Object,
default: () => {},
},
title: {
type: String,
default: '',
},
})
</script>

View File

@ -1,63 +0,0 @@
<template>
<view class="relative pt-[40rpx]">
<Dashboard class="absolute right-[38rpx] top-0" :score="score" :color="rules[level].color" />
<view class="bg-[#fff] rounded-[24rpx] p-[22rpx]">
<view class="mt-[30rpx]">
<text class="text-[48rpx] text-[#000] font-600">{{ tagName }}</text>
<!-- <view class="flex items-center text-[#999] text-[24rpx] mt-[20rpx]">
<view class="i-carbon-warning w-[24rpx] h-[24rpx]"></view>
<text class="text-[#999] ml-[10rpx]">状态很好哦继续保持轻松迎接高考吧</text>
</view> -->
<view class="mt-[58rpx]">
<ScoreCard :current-position="level" :rules="rules" />
</view>
<view class="relative mt-[68rpx] bg-[#F5FAFF]">
<image
src="https://api.static.ycymedu.com/src/images/home/test-icon.png"
mode="scaleToFill"
class="w-[180rpx] h-[52rpx] absolute top-[-9rpx] left-[20rpx]"
/>
<view class="px-[20rpx] pb-[20rpx] pt-[58rpx] text-[#333] text-[26rpx]">
{{ description }}
</view>
</view>
<view class="text-[#999] text-[24rpx] mt-[10rpx]">
{{ tip }}
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import Dashboard from '@/pages-evaluation-sub/evaluate/components/psychologicalReportItem/Dashboard.vue'
import ScoreCard from './psychologicalReportItem/ScoreCard.vue'
defineProps({
score: {
type: Number,
default: 0,
},
rules: {
type: Array<{ label: string; range: string; color: string }>,
default: () => [],
},
tip: {
type: String,
default: '结果只做参考,不能准确判断是否有焦虑症。',
},
level: {
type: Number,
default: 0,
},
description: {
type: String,
default: '',
},
tagName: {
type: String,
default: '',
},
})
</script>

View File

@ -1,18 +0,0 @@
<template>
<view class="flex flex-col bg-white rounded-[24rpx] p-[30rpx] gap-[40rpx]">
<view class="flex flex-col gap-[12rpx]">
<view class="flex items-center gap-[10rpx]">
<image
src="https://api.static.ycymedu.com/src/images/home/life-icon.png"
mode="scaleToFill"
class="w-[38rpx] h-[38rpx]"
/>
<text class="text-[32rpx] text-[#000] font-700">生活建议</text>
</view>
<view class="text-[26rpx] text-[#666] font-400">
保持规律作息早睡早起避免熬夜 每天适当运动如散步跑步保持精力充沛
避免过度放松保持适度的学习节奏
</view>
</view>
</view>
</template>

View File

@ -1,25 +0,0 @@
<template>
<view class="text-center mb-[24rpx]">
<view class="text-[32rpx] font-bold relative inline-flex pb-[10rpx] items-center">
<view class="i-carbon-flash-filled h-[23rpx] w-[17rpx] text-[#1880FC]"></view>
<text class="text-[#1880FC] text-[36rpx] font-bold">{{ title }}</text>
<view class="i-carbon-flash-filled h-[23rpx] w-[17rpx] text-[#1880FC]"></view>
<view
class="absolute bottom-0 left-1/2 transform -translate-x-1/2 w-full h-[10rpx] bg-[#cce3fc] rounded-full title-bar"
></view>
</view>
</view>
</template>
<script lang="ts" setup>
defineProps({
title: {
type: String,
default: '',
},
})
</script>
<style lang="scss" scoped>
@import '@/pages-evaluation-sub/styles/parallelogram.scss';
</style>

View File

@ -1,39 +0,0 @@
<template>
<view
class="text-[26rpx] text-[#000] mx-[24rpx] bg-[#fff] flex flex-col px-[20rpx] gap-[10rpx] pb-[20rpx] custom-class"
>
<view class="flex gap-[10rpx] w-full">
<view class="w-[94rpx] py-[12rpx] bg-color text-center">类型</view>
<view class="py-[12rpx] text-center bg-color flex-1">性格特点</view>
</view>
<view class="flex gap-[10rpx] w-full" v-for="(item, index) in reportItems" :key="index">
<view
class="w-[94rpx] py-[12rpx] bg-color text-center flex flex-col justify-center items-center text-[#333] font-700"
>
<view>{{ item.tag }}</view>
<view>{{ item.title }}</view>
</view>
<view class="py-[22rpx] px-[14rpx] text-start bg-color flex-1">{{ item.resolving }}</view>
</view>
</view>
</template>
<script setup lang="ts">
const props = defineProps({
reportItems: {
type: Array<any>,
default: () => [],
},
})
</script>
<style lang="scss" scoped>
.bg-color {
background-color: #f5faff;
border-radius: 8rpx;
}
.custom-class {
border-radius: 0 0 20rpx 20rpx;
}
</style>

View File

@ -1,115 +0,0 @@
<template>
<view
class="radar-chart-placeholder mx-[24rpx] bg-white chart-class h-[630rpx] flex flex-col justify-center px-[24rpx] pt-[62rpx] pb-[20rpx]"
>
<view class="w-full z-1 flex flex-col gap-[40rpx]">
<view
class="w-full flex items-center gap-[16rpx] text-[30rpx] text-[#A8A8A8]"
v-for="(item, index) in characterData"
:style="`--start-color:${colors[index].startColor};--end-color:${colors[index].endColor};--active-color:${colors[index].activeColor}`"
:key="index"
>
<view
:class="`w-110rpx ${item.leftData.value > item.rightData.value ? 'left-active' : ''}`"
>
{{ item.leftData.name }}
</view>
<view class="flex-1 h-[28rpx] bg-[#F1F2F4] rounded-[16rpx]">
<view
class="w-[60%] rounded-[16rpx] bar-color h-[28rpx]"
:style="`transform:translateX(${(item.rightData.value / (item.rightData.value + item.leftData.value)) * 100}%);`"
></view>
</view>
<view
:class="`w-110rpx ${item.leftData.value > item.rightData.value ? '' : 'right-active'}`"
>
{{ item.rightData.name }}
</view>
</view>
</view>
<view class="px-[16rpx] py-[20rpx] flex flex-col bg-[#F5FAFF] mt-[32rpx]">
<text class="text-[30rpx] text-[#000] mb-[10rpx] font-700">性格介绍</text>
<text class="text-[26rpx] text-[#333]">{{ description }}</text>
</view>
</view>
</template>
<script lang="ts" setup>
const props = defineProps({
linChart: {
type: Object,
default: () => ({
name: [],
value: [],
}),
},
description: {
type: String,
default: '',
},
})
const colors = [
{ startColor: '#97FBCD', endColor: '#00BAAD', activeColor: '#00BAAD' },
{ startColor: '#FF5940', endColor: '#FAA896', activeColor: '#FF4117' },
{ startColor: '#FFBF5E', endColor: '#F59300', activeColor: '#EB8D00' },
{ startColor: '#96E4FA', endColor: '#117CFC', activeColor: '#117CFC' },
]
const transformData = (names: string[], values: number[]) => {
const result = []
const pairMap = new Map()
const pairData = { E: 'I', S: 'N', T: 'F', J: 'P' }
//
names.forEach((name, index) => {
const match = name.match(/\((.*?)\)(\w+)/)
if (match) {
const letter = match[2]
pairMap.set(letter, { name, value: values[index] })
}
})
// pairData
Object.entries(pairData).forEach(([left, right]) => {
const leftData = pairMap.get(left)
const rightData = pairMap.get(right)
if (leftData && rightData) {
result.push({
leftData,
rightData,
})
}
})
return result
}
const characterData = ref([])
watch(
() => props.linChart,
(newV) => {
let data = transformData(newV.name, newV.value)
characterData.value = data
},
)
</script>
<style lang="scss" scoped>
.chart-class {
border-radius: 20rpx;
}
.bar-color {
background: linear-gradient(90deg, var(--start-color) 0%, var(--end-color) 100%);
}
.left-active {
color: var(--active-color);
font-weight: 700;
}
.right-active {
color: var(--active-color);
font-weight: 700;
}
</style>

View File

@ -1,181 +0,0 @@
<template>
<view
class="suitable-positions mx-[30rpx] mt-[30rpx] bg-white rounded-[20rpx] p-[30rpx] flex flex-col"
>
<TitleBar title="适合的岗位领域" />
<view class="flex justify-center items-center">
<view class="h-[146px] w-[265px] z-1">
<LEchart ref="echart" :is-disable-scroll="true"></LEchart>
</view>
</view>
<view class="flex items-center gap-[10rpx] mb-[10rpx]">
<view class="w-[5rpx] h-[30rpx] bg-[#1580FF]"></view>
<text class="text-[#1580FF] text-[32rpx] font-bold">适合职业</text>
<text class="text-[#999] text-[24rpx]">以下数据仅作为参考</text>
</view>
<text class="text-[#666] text-[28rpx]">{{ major }}</text>
<view class="flex items-center gap-[10rpx] mb-[10rpx] mt-[40rpx]">
<view class="w-[5rpx] h-[30rpx] bg-[#1580FF]"></view>
<text class="text-[#1580FF] text-[32rpx] font-bold">适合专业</text>
<text class="text-[#999] text-[24rpx]">以下数据仅作为参考</text>
</view>
<text class="text-[#666] text-[28rpx]">{{ occupation }}</text>
</view>
</template>
<script lang="ts" setup>
import LEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
import TitleBar from '../TitleBar.vue'
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
const echart = ref(null)
const props = defineProps({
mainDomain: {
type: String,
default: '',
},
major: {
type: String,
default: '',
},
occupation: {
type: String,
default: '',
},
})
//
const styleConfig = [
{ bg: '#FDF0F0', text: '#F58C8C', size: 45, x: 2, y: 38 },
{ bg: '#ECF5FF', text: '#3B9DFF', size: 77, x: 52, y: 64 },
{ bg: '#F6F4FD', text: '#7E5EFF', size: 63, x: 136, y: 48 },
{ bg: '#FFF8E5', text: '#FFC832', size: 62, x: 116, y: 104 },
{ bg: '#E6FBF0', text: '#37D480', size: 45, x: 0, y: 110 },
{ bg: '#FDF0F0', text: '#F58C8C', size: 45, x: 166, y: 118 },
]
const chartData = ref([])
//
const selectStylesByLength = (items: string[]) => {
const usedIndices = new Set<number>()
const result: Array<{ style: any; text: string }> = []
//
const processItems = (items: string[], targetSize: number) => {
items.forEach((item) => {
// 使
const availableIndices = styleConfig
.map((style, index) => ({ index, style }))
.filter(({ style, index }) => style.size === targetSize && !usedIndices.has(index))
if (availableIndices.length > 0) {
const { index, style } = availableIndices[0]
usedIndices.add(index)
result.push({ style, text: item })
}
})
}
//
const bigItems = items.filter((item) => item.length >= 4)
const mediumItems = items.filter((item) => item.length === 3)
const smallItems = items.filter((item) => item.length <= 2)
//
processItems(bigItems, 77)
processItems(mediumItems, 63)
processItems(smallItems, 45)
// 使
const remainingItems = items.filter((item) => !result.some((r) => r.text === item))
remainingItems.forEach((item) => {
// 使
for (let i = 0; i < styleConfig.length; i++) {
if (!usedIndices.has(i)) {
usedIndices.add(i)
result.push({ style: styleConfig[i], text: item })
break
}
}
})
return result
}
watch(
() => props.mainDomain,
(newV) => {
if (!newV) return
chartData.value = newV.split('、')
echart.value.init(echarts, (chart) => {
//
const selectedStyles = selectStylesByLength(chartData.value)
//
const data = selectedStyles.map(({ style, text }) => {
return {
name: text,
x: style.x,
y: style.y,
symbolSize: style.size,
itemStyle: {
color: style.bg,
},
label: {
show: true,
color: style.text,
fontSize: 14,
formatter: (params: any) => {
const text = params.name
if (text.length >= 5) {
const lines = []
for (let i = 0; i < text.length; i += 3) {
lines.push(text.slice(i, i + 3))
}
return lines.join('\n\n')
}
return text
},
rich: {
lineHeight: 20,
},
align: 'center',
verticalAlign: 'middle',
position: 'inside',
},
}
})
let option = {
tooltip: {},
animationDurationUpdate: 1500,
animationEasingUpdate: 'quinticInOut',
series: [
{
type: 'graph',
layout: 'none',
roam: true,
data,
links: [],
lineStyle: {
opacity: 0.9,
width: 2,
curveness: 0,
},
},
],
}
chart.setOption(option)
})
},
)
</script>
<style lang="scss" scoped></style>

View File

@ -1,108 +0,0 @@
<template>
<view class="mx-[24rpx] bg-white chart-class h-[500rpx] flex items-center justify-center">
<view class="h-[415rpx] w-full z-1">
<LEchart ref="echart"></LEchart>
</view>
</view>
</template>
<script lang="ts" setup>
import LEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
const echart = ref(null)
const props = defineProps({
picData: {
type: Object,
default: () => ({
indicator: [],
radars: [],
}),
},
})
//
const nameMap: Record<string, string> = {
A: '艺术型(A)',
R: '现实型(R)',
I: '研究型(I)',
S: '社会型(S)',
E: '企业型(E)',
C: '常规型(C)',
}
// indicator
const formatIndicator = computed(() => {
return props.picData.indicator.map((item) => ({
name: nameMap[item.name] || item.name,
max: item.max,
}))
})
watch(
() => props.picData,
(newV) => {
if (newV.radars.length > 0) {
echart.value.init(echarts, (chart) => {
let option = {
radar: {
center: ['50%', '50%'],
radius: '70%',
indicator: formatIndicator.value,
splitArea: {
show: false,
},
axisLine: {
lineStyle: {
color: '#e5e6eb',
},
},
splitLine: {
lineStyle: {
color: '#e5e6eb',
},
},
axisName: {
color: '#333',
},
},
series: [
{
name: '职业兴趣评测',
type: 'radar',
data: [
{
value: props.picData.radars,
name: '测评结果',
itemStyle: {
color: '#1580FF',
},
areaStyle: {
color: 'rgba(21,128,255,0.2)',
},
lineStyle: {
width: 2,
},
},
],
},
],
}
chart.setOption(option)
})
}
},
)
onBeforeMount(() => {
if (echart.value) {
echart.value.dispose()
}
})
</script>
<style lang="scss" scoped>
.chart-class {
border-radius: 20rpx 20rpx 0 0;
}
</style>

View File

@ -1,183 +0,0 @@
<template>
<view class="bg-white mx-[24rpx] rounded-[20rpx] pb-[20rpx]">
<view class="px-[24rpx] h-[368rpx] z-1">
<LEchart ref="echart" :customStyle="`z-index:1;`"></LEchart>
</view>
<view class="bg-[#F5FAFF] px-[16rpx] pt-[20rpx] mx-[34rpx] pb-[26rpx]">
<view class="text-[#000] text-[30rpx] mb-[10rpx] font-700">能力评测建议</view>
<view class="text-[26rpx] text-[#333]">{{ description }}</view>
</view>
</view>
</template>
<script lang="ts" setup>
import LEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
const echart = ref(null)
const props = defineProps({
echartData: {
type: Array,
default: () => [
{
name: [],
value: [],
},
{
name: [],
value: [],
},
],
},
description: {
type: String,
default: '',
},
})
onMounted(() => {
updateChart()
})
watch(
() => props.echartData,
(newVal) => {
if (newVal && newVal.length > 0) {
updateChart()
}
},
{ deep: true },
)
const updateChart = () => {
echart.value.init(echarts, (chart) => {
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
formatter: function (params) {
let result = params[0].name.split('\n').join('') + '\n'
params.forEach((param) => {
result += `${param.marker} ${param.seriesName}: ${param.value}\n`
})
return result
},
textStyle: {
fontSize: 12,
},
position: function (point, params, dom, rect, size) {
const tooltipWidth = dom._rect.width
const canvasWidth = size.viewSize[0]
if (point[0] + tooltipWidth > canvasWidth) {
return [point[0] - tooltipWidth, '10%']
}
return [point[0], '10%']
},
},
grid: {
top: 40,
left: 10,
right: 20,
bottom: 10,
containLabel: true,
},
legend: {
data: ['我的数据', '平均水平'],
right: 'auto',
left: 'center',
top: 0,
itemWidth: 15,
itemHeight: 10,
textStyle: {
fontSize: 12,
},
},
xAxis: [
{
type: 'category',
data: (props.echartData[1] as { name: string[] })?.name.map((item) =>
item.replace('智能', '').replace(/(.{2})/g, '$1\n'),
),
axisLine: {
lineStyle: {
color: '#E0E0E0',
},
},
axisLabel: {
color: '#666',
fontSize: 12,
interval: 0,
},
axisTick: {
show: false,
},
},
],
yAxis: [
{
type: 'value',
name: '分数',
min: 0,
max: 50,
interval: 10,
axisLine: {
show: true,
lineStyle: {
color: '#E0E0E0',
},
},
axisTick: {
show: false,
},
splitLine: {
lineStyle: {
color: '#E8E8E8',
type: 'solid',
},
},
axisLabel: {
color: '#999',
},
},
],
series: [
{
name: '我的数据',
type: 'bar',
barWidth: '20',
itemStyle: {
color: '#1580FF',
borderRadius: [4, 4, 0, 0],
},
data: (props.echartData[0] as { value: number[] })?.value,
},
{
name: '平均水平',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
color: '#F9AA5B',
width: 2,
},
itemStyle: {
color: '#F9AA5B',
borderWidth: 2,
borderColor: '#fff',
},
data: (props.echartData[1] as { value: number[] })?.value,
},
],
}
chart.setOption(option)
})
}
</script>
<style scoped></style>

View File

@ -1,162 +0,0 @@
<template>
<view class="bg-white mx-[24rpx] rounded-[20rpx] pb-[20rpx]">
<view class="px-[24rpx] h-[368rpx] z-1">
<LEchart ref="echart" :customStyle="`z-index:1;`"></LEchart>
</view>
</view>
</template>
<script lang="ts" setup>
import LEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
const echart = ref(null)
interface IndicatorItem {
name: string
max: number
}
interface PicChartsData {
indicator: IndicatorItem[]
radars: number[]
}
const props = defineProps({
picCharts: {
type: Object as () => PicChartsData,
default: () => ({
indicator: [],
radars: [],
}),
},
description: {
type: String,
default: '',
},
})
onMounted(() => {
updateChart()
})
watch(
() => props.picCharts,
(newVal) => {
if (newVal && newVal.indicator && newVal.indicator.length > 0) {
updateChart()
}
},
{ deep: true },
)
const updateChart = () => {
echart.value.init(echarts, (chart) => {
//
const categories = props.picCharts.indicator.map((item) => {
const match = item.name.match(/(.*?)\([^)]*\)/)
return match ? match[1].trim() : item.name
})
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
grid: {
top: 60,
left: 0,
right: 0,
bottom: 0,
containLabel: true,
},
xAxis: {
type: 'category',
data: categories,
axisLine: {
lineStyle: {
color: '#E0E0E0',
},
},
axisLabel: {
color: '#666',
fontSize: 12,
interval: 0,
rotate: 45,
formatter: function (value) {
//
if (value.length > 4) {
return value.substring(0, 4) + '...'
}
return value
},
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
name: '分数',
min: 0,
max: 30,
interval: 5,
axisLine: {
show: true,
lineStyle: {
color: '#E0E0E0',
},
},
axisTick: {
show: false,
},
splitLine: {
lineStyle: {
color: '#E8E8E8',
type: 'solid',
},
},
axisLabel: {
color: '#999',
},
},
series: [
{
name: '得分',
type: 'bar',
barWidth: '20',
itemStyle: {
color: function (params) {
//
const colorList = [
'#1580FF',
'#F9AA5B',
'#5470c6',
'#91cc75',
'#fac858',
'#ee6666',
'#73c0de',
'#3ba272',
]
return colorList[params.dataIndex % colorList.length]
},
borderRadius: [4, 4, 0, 0],
},
label: {
show: true,
position: 'top',
color: '#666',
fontSize: 12,
},
data: props.picCharts.radars,
},
],
}
chart.setOption(option)
})
}
</script>
<style scoped></style>

View File

@ -1,58 +0,0 @@
<template>
<view
class="rounded-full w-[162rpx] h-[162rpx] bg-[#fff] dashboard-wrapper flex items-center justify-center"
:style="{ '--current-color': color }"
>
<view class="w-[139rpx] h-[139rpx] custom-style flex items-center justify-center">
<view
v-for="i in 39"
:key="i"
class="tick"
:style="{
transform: `rotate(${i * 8 - 90}deg)`,
opacity: `${1 - Math.abs(i * 8 - 90) / 90}`,
}"
></view>
<view class="font-500 text-color w-full h-full flex items-center justify-center">
<view :class="`${score > 99 ? 'text-[50rpx]' : 'text-[62rpx]'}`">{{ score }}</view>
<view class="text-[28rpx] mt-[8rpx]"></view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
defineProps({
color: {
type: String,
default: '#00b281',
},
score: {
type: Number,
default: 0,
},
})
</script>
<style lang="scss" scoped>
.custom-style {
border-radius: 50%;
position: relative;
}
.text-color {
color: var(--current-color);
container-type: inline-size;
white-space: nowrap;
}
.tick {
position: absolute;
top: 0;
left: 50%;
width: 4rpx;
height: 10rpx;
background-color: var(--current-color);
transform-origin: 0 67rpx;
}
</style>

View File

@ -1,15 +0,0 @@
<template>
<view class="bg-white mx-[24rpx] rounded-[20rpx] pb-[20rpx]">
<view class="px-[24rpx] h-[368rpx] z-1">
<LEchart ref="echart" :customStyle="`z-index:1;`"></LEchart>
</view>
</view>
</template>
<script lang="ts" setup>
import LEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
const echart = ref(null)
</script>
<script lang="scss" scoped></script>

View File

@ -1,94 +0,0 @@
<template>
<view
class="grid grid-cols-4 items-end gap-[6rpx] relative"
:style="`grid-template-columns: repeat(${rules.length},minmax(0,1fr))`"
>
<view v-for="(item, index) in rules" :key="index" class="">
<view
:class="['common-rectangle']"
:style="`height: ${24 + index * 10}rpx;background-color:${item.color}`"
></view>
<view
class="flex flex-col text-[24rpx] text-center"
:style="{ color: currentPosition === index ? item.color : '#999' }"
>
<text :class="currentPosition === index ? 'font-500' : ''">{{ item.label }}</text>
<view v-html="item.range" class="whitespace-nowrap"></view>
</view>
</view>
<view
:style="{
left: `${(currentPosition + 1 / 2) * (100 / rules.length)}%`,
top: `${currentPosition * -8 - 10}rpx`,
}"
class="current-flag-wrapper"
>
<view class="current-flag">
<view class="flag-text">当前</view>
<view class="flag-triangle"></view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
defineProps<{
currentPosition: number // 0-3
rules: {
label: string
range: string
color: string
}[]
}>()
</script>
<style lang="scss" scoped>
.common-rectangle {
width: 100%;
position: relative;
border-radius: 8rpx;
clip-path: polygon(100% 0, 100% 0, 100% 100%, 0 100%, 0 10rpx);
margin-bottom: 6rpx;
}
.current-flag-wrapper {
position: absolute;
margin-bottom: 8rpx;
transition: left 0.3s ease;
transform: translateX(-50%);
}
.current-flag {
position: relative;
width: 82rpx;
height: 37rpx;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
}
.flag-text {
color: #fff;
font-size: 22rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
line-height: 2;
}
.flag-triangle {
position: absolute;
bottom: -8rpx;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 8rpx solid transparent;
border-right: 8rpx solid transparent;
border-top: 8rpx solid rgba(0, 0, 0, 0.6);
}
</style>

View File

@ -1,164 +0,0 @@
<template>
<view class="bg-white rounded-[20rpx] pb-[20rpx] custom-background">
<view class="h-[586rpx] z-1">
<LEchart ref="echart" :customStyle="`z-index:1;`"></LEchart>
</view>
<view class="relative mt-[68rpx] bg-[#F5FAFF] mx-[20rpx] px-[24rpx] pt-[58rpx] pb-[20rpx]">
<image
src="https://api.static.ycymedu.com/src/images/home/test-icon.png"
mode="scaleToFill"
class="w-[180rpx] h-[52rpx] absolute top-[-9rpx] left-[20rpx]"
/>
<view v-for="(item, index) in innerParsing" class="text-[26rpx] mb-[20rpx]" :key="index">
<text class="text-[#000] font-700">{{ item.title }}:&nbsp;</text>
<text class="text-[#3d3d3d] font-400">{{ item.desc }}</text>
</view>
<view class="text-[26rpx]">
<text class="text-[#000] font-700">策略偏好:</text>
<view class="flex gap-x-[20rpx] gap-y-[16rpx] text-[22rpx] flex-wrap mt-[16rpx]">
<view
v-for="(item, index) in policy.items"
:key="index"
class="text-[22rpx] px-[12rpx] py-[4rpx] rounded-[20rpx] bg-[rgba(250,142,35,0.15)] text-[#FA8E23]"
>
{{ item.title }}
</view>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import LEchart from '@/pages-evaluation-sub/uni_modules/lime-echart/components/l-echart/l-echart.vue'
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
const echart = ref(null)
const props = defineProps({
picData: {
type: Array,
default: () => [],
},
parsing: {
type: String,
default: '',
},
})
const innerParsing = ref([])
const policy = ref({ items: [] })
watch(
() => props.parsing,
(newV) => {
const _val = JSON.parse(newV) as {
tags: { title: string; items: { title: string; desc: string }[] }[]
}
_val.tags.forEach((item) => {
if (item.title === '策略偏好') {
policy.value = item
return
} else {
innerParsing.value.push(...item.items)
}
})
},
)
//
watch(
() => props.picData,
(newData) => {
if (!newData || newData.length === 0) return
if (echart.value) {
echart.value.init(echarts, (chart) => {
const option = {
radar: {
center: ['50%', '50%'],
radius: '60%',
indicator: newData.map((item: any) => ({
name: `${item.type},${item.desc}`,
})),
shape: 'polygon',
splitNumber: 4,
axisName: {
color: '#333',
fontSize: 12,
formatter: (value: string) => {
//
const maxLength = 4
const result = []
let _val = value.split(',')
for (let i = 0; i < _val[0].length; i += maxLength) {
result.push(value.slice(i, i + maxLength))
}
result.push(`(${_val[1]})`)
return result.join('\n')
},
},
splitArea: {
areaStyle: {
color: ['rgba(255,255,255,0.3)'],
},
},
axisLine: {
lineStyle: {
color: '#E5E6EB',
},
},
splitLine: {
lineStyle: {
color: '#E5E6EB',
},
},
},
series: [
{
type: 'radar',
data: [
{
value: newData.map((item: any) => item.value),
name: '学习风格',
areaStyle: {
color: 'rgba(64, 158, 255, 0.3)',
},
lineStyle: {
color: '#409EFF',
},
itemStyle: {
color: '#409EFF',
},
label: {
show: true,
formatter: (params: any) => {
return params.value
},
color: '#1580FF',
fontSize: 12,
},
},
],
},
],
}
chart.setOption(option)
})
}
},
{ immediate: true },
)
onBeforeMount(() => {
if (echart.value) {
echart.value.dispose()
}
})
</script>
<style scoped>
.custom-background {
background: linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, #ffffff 6%);
}
</style>

View File

@ -1,13 +0,0 @@
export const handleBack = () => {
const pages = getCurrentPages()
console.log(pages[pages.length - 2].route)
if (
pages.length > 1 &&
pages[pages.length - 2].route === 'pages-sub/ucenter/evaluate/evaluateList'
) {
uni.navigateBack()
} else {
uni.switchTab({ url: '/pages/evaluation/index/index' })
}
}

View File

@ -1,82 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">MHT心理健康自评</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative">
<!-- 顶部卡片 -->
<view class="mt-[30rpx] mx-[24rpx]">
<StatusCard />
</view>
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import StatusCard from '../components/StatusCard.vue'
import { handleBack } from '../hooks/useEvaluateBack'
import { getCustomScaleExplains } from '@/service/index/api'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
linChart: [],
reportItems: [],
hTag: '',
})
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
linChart: any[]
reportItems: any[]
hTag: string
}
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,136 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">SAS焦虑测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative flex flex-col">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[30rpx] mx-[24rpx]">
<StatusCard
:score="score"
:rules="anxietyRules"
tip="结果只做参考,不能准确判断是否有焦虑症。"
:level="level"
:description="studyRecord.description"
:tagName="studyRecord.tagName"
/>
</view>
<view class="mt-[30rpx] mx-[24rpx]">
<SuggestionCard />
</view>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import StatusCard from '../components/StatusCard.vue'
import SuggestionCard from '../components/SuggestionCard.vue'
import AiFooter from '../components/AiFooter.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const anxietyRules = [
{
label: '正常范围',
range: '<50分',
color: '#00B281',
},
{
label: '轻度焦虑',
range: '50-59分',
color: '#F8B801',
},
{
label: '中度焦虑',
range: '60-69分',
color: '#F79C33',
},
{
label: '重度焦虑',
range: '≥70分',
color: '#F5663E',
},
]
const score = ref(0)
const level = ref(0)
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
})
const calcLevel = (val: string) => {
let _s = JSON.parse(val)
if (_s[0].Total >= 70) {
return 3
} else if (_s[0].Total >= 60) {
return 2
} else if (_s[0].Total >= 50) {
return 1
} else {
return 0
}
}
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
}
level.value = calcLevel(studyRecord.value.result)
score.value = JSON.parse(studyRecord.value.result)[0].Total
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,140 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">SDS抑郁测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative flex flex-col">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[30rpx] mx-[24rpx]">
<StatusCard
:score="score"
:rules="depressionRules"
tip="结果只做参考,不能准确判断是否有抑郁症。"
:level="level"
:description="studyRecord.description"
:tagName="studyRecord.tagName"
/>
</view>
<view class="mt-[30rpx] mx-[24rpx]">
<SuggestionCard />
</view>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import StatusCard from '../components/StatusCard.vue'
import SuggestionCard from '../components/SuggestionCard.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import AiFooter from '../components/AiFooter.vue'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
// 2
const depressionRules = [
{
label: '正常范围',
range: '<52分',
color: '#00B281',
},
{
label: '轻度抑郁',
range: '53-61分',
color: '#F8B801',
},
{
label: '中度抑郁',
range: '62-71分',
color: '#F79C33',
},
{
label: '重度抑郁',
range: '≥72分',
color: '#F5663E',
},
]
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
total: '',
})
const calcLevel = (val: string) => {
let _s = +val
if (_s >= 72) {
return 3
} else if (_s >= 62) {
return 2
} else if (_s >= 53) {
return 1
} else {
return 0
}
}
const score = ref(0)
const level = ref(0)
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
total: string
}
level.value = calcLevel(studyRecord.value.total)
score.value = JSON.parse(studyRecord.value.total)
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,153 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">学习技能报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[60rpx] mx-[24rpx]">
<StatusCard
:score="score"
:rules="anxietyRules"
tip="测评结果只做参考。"
:level="level"
:description="studyRecord.description"
:tagName="studyRecord.tagName"
/>
</view>
<view class="mx-[24rpx]">
<LearnSkillSuggestion
v-for="(item, index) in suggestions"
:key="index"
:items="item.items"
:title="item.title"
></LearnSkillSuggestion>
</view>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import StatusCard from '../components/StatusCard.vue'
import LearnSkillSuggestion from '../components/LearnSkillSuggestion.vue'
import AiFooter from '../components/AiFooter.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const anxietyRules = [
{
label: '很差',
range: '≤80分',
color: '#F5663E',
},
{
label: '较差',
range: '81-104分',
color: '#F8B801',
},
{
label: '一般',
range: '105-136分',
color: '#F3A953',
},
{
label: '较好',
range: '137-160分',
color: '#55E5C5',
},
{
label: '优秀',
range: '≥161分',
color: '#00B281',
},
]
const score = ref(0)
const level = ref(0)
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
suggestions: '',
})
const calcLevel = (val: string) => {
let _s = JSON.parse(val)
if (_s[0].Total >= 161) {
return 4
} else if (_s[0].Total >= 137) {
return 3
} else if (_s[0].Total >= 105) {
return 2
} else if (_s[0].Total >= 81) {
return 1
} else {
return 0
}
}
const suggestions = ref([])
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
suggestions: string
}
level.value = calcLevel(studyRecord.value.result)
score.value = JSON.parse(studyRecord.value.result)[0].Total
suggestions.value = JSON.parse(studyRecord.value.suggestions).succestions
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,103 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">Solomon学习风格报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[60rpx] mx-[24rpx]">
<LearnStyleChart :pic-data="chartData" :parsing="parsing" />
</view>
<view class="mx-[24rpx]">
<LearnStudySuggestion
:title="item.name"
:item="item"
v-for="(item, index) in suggestions"
:key="index"
/>
</view>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import LearnStyleChart from '../components/studyChart/LearnStyleChart.vue'
import LearnStudySuggestion from '../components/LearnStudySuggestion.vue'
import AiFooter from '../components/AiFooter.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
suggestions: '',
})
const chartData = ref([])
const parsing = ref('')
const suggestions = ref([])
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
suggestions: string
}
chartData.value = JSON.parse(studyRecord.value.result)
parsing.value = studyRecord.value.suggestions
suggestions.value = JSON.parse(studyRecord.value.description)
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,138 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">考试焦虑测评报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto flex flex-col">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[60rpx] mx-[24rpx]">
<StatusCard
:score="score"
:rules="anxietyRules"
tip="测评结果只做参考。"
:level="level"
:description="studyRecord.description"
:tagName="studyRecord.tagName"
/>
</view>
<view class="mx-[24rpx]">
<LearnSkillSuggestion
v-for="(item, index) in suggestions"
:key="index"
:items="item.items"
:title="item.title"
></LearnSkillSuggestion>
</view>
</view>
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import StatusCard from '../components/StatusCard.vue'
import LearnSkillSuggestion from '../components/LearnSkillSuggestion.vue'
import AiFooter from '../components/AiFooter.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const anxietyRules = [
{
label: '较低水平',
range: '≤12分',
color: '#00B281',
},
{
label: '中等程度',
range: '12-20分',
color: '#F8B801',
},
{
label: '较高水平',
range: '≥21分',
color: '#F5663E',
},
]
const score = ref(0)
const level = ref(0)
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
suggestions: '',
})
const calcLevel = (val: string) => {
let _s = JSON.parse(val)
if (_s[0].Total >= 21) {
return 2
} else if (_s[0].Total >= 12) {
return 1
} else {
return 0
}
}
const suggestions = ref([])
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
suggestions: string
}
level.value = calcLevel(studyRecord.value.result)
score.value = JSON.parse(studyRecord.value.result)[0].Total
suggestions.value = JSON.parse(studyRecord.value.suggestions)
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,153 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">学习技能报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[60rpx] mx-[24rpx]">
<StatusCard
:score="score"
:rules="anxietyRules"
tip="测评结果只做参考。"
:level="level"
:description="studyRecord.description"
:tagName="studyRecord.tagName"
/>
</view>
<view class="mx-[24rpx]">
<LearnSkillSuggestion
v-for="(item, index) in suggestions"
:key="index"
:items="item.items"
:title="item.title"
></LearnSkillSuggestion>
</view>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import StatusCard from '../components/StatusCard.vue'
import LearnSkillSuggestion from '../components/LearnSkillSuggestion.vue'
import AiFooter from '../components/AiFooter.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const anxietyRules = [
{
label: '很差',
range: '≤80分',
color: '#F5663E',
},
{
label: '较差',
range: '81-104分',
color: '#F8B801',
},
{
label: '一般',
range: '105-136分',
color: '#F3A953',
},
{
label: '较好',
range: '137-160分',
color: '#55E5C5',
},
{
label: '优秀',
range: '≥161分',
color: '#00B281',
},
]
const score = ref(0)
const level = ref(0)
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
suggestions: '',
})
const calcLevel = (val: string) => {
let _s = JSON.parse(val)
if (_s[0].Total >= 161) {
return 4
} else if (_s[0].Total >= 137) {
return 3
} else if (_s[0].Total >= 105) {
return 2
} else if (_s[0].Total >= 81) {
return 1
} else {
return 0
}
}
const suggestions = ref([])
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
suggestions: string
}
level.value = calcLevel(studyRecord.value.result)
score.value = JSON.parse(studyRecord.value.result)[0].Total
suggestions.value = JSON.parse(studyRecord.value.suggestions).succestions
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,103 +0,0 @@
<route lang="json5" type="page">
{
style: {
navigationStyle: 'custom',
},
}
</route>
<template>
<view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
<Navbar
safeAreaInsetTop
:bordered="false"
leftArrow
@clickLeft="handleBack"
bg-color="transparent"
>
<template #title>
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">Solomon学习风格报告</text>
</template>
</Navbar>
<view class="flex-1 overflow-auto relative">
<view class="flex flex-col flex-1 overflow-auto pb-[20rpx]">
<!-- 顶部卡片 -->
<view class="mt-[60rpx] mx-[24rpx]">
<LearnStyleChart :pic-data="chartData" :parsing="parsing" />
</view>
<view class="mx-[24rpx]">
<LearnStudySuggestion
:title="item.name"
:item="item"
v-for="(item, index) in suggestions"
:key="index"
/>
</view>
</view>
<!-- 底部AI智能顾问 -->
<AiFooter :pageId="pageId" :pageType="pageType" />
</view>
</view>
</template>
<script setup lang="ts">
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
import LearnStyleChart from '../components/studyChart/LearnStyleChart.vue'
import LearnStudySuggestion from '../components/LearnStudySuggestion.vue'
import AiFooter from '../components/AiFooter.vue'
import { getCustomScaleExplains } from '@/service/index/api'
import { handleBack } from '../hooks/useEvaluateBack'
const pageType = ref(0)
const pageId = ref(0)
const studyRecord = ref({
description: '',
title: '',
result: '',
tagName: '',
suggestions: '',
})
const chartData = ref([])
const parsing = ref('')
const suggestions = ref([])
onLoad((options) => {
pageType.value = +options.type
pageId.value = options.id
getCustomScaleExplains({ CustomScaleId: pageId.value }).then((resp) => {
if (resp.code === 200) {
studyRecord.value = resp.result as {
description: string
title: string
result: string
tagName: string
suggestions: string
}
chartData.value = JSON.parse(studyRecord.value.result)
parsing.value = studyRecord.value.suggestions
suggestions.value = JSON.parse(studyRecord.value.description)
}
})
})
</script>
<style scoped lang="scss">
.custom-bg {
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
}
:deep(.icon-class) {
color: #fff !important;
}
.custom-border {
width: 162rpx;
height: 162rpx;
border-radius: 50%;
border: 6rpx dashed;
border-color: #05d69c transparent transparent transparent;
}
</style>

View File

@ -1,35 +0,0 @@
<template>
<CheckGroup :list="regionList" @change="handleChange" label-key="simplename" v-bind="$attrs" />
</template>
<script lang="ts" setup>
import { getRegionInfo } from '@/service/index/api'
import CheckGroup from '@/pages-evaluation-sub/components/check-group/CheckGroup.vue'
defineOptions({
options: {
styleIsolation: 'shared',
},
})
interface Region {
code: string
name: string
parentcode: string
simplename: string
pinyin: string
}
const regionList = ref([])
getRegionInfo().then((res) => {
if (res.code === 200) {
regionList.value = res.result as Region[]
}
})
const emits = defineEmits(['change', 'changeName'])
const handleChange = (val: any) => {
const names = regionList.value.filter((item) => val.includes(item.code)).map((item) => item.name)
emits('changeName', names)
emits('change', val)
}
</script>

View File

@ -1,31 +0,0 @@
<template>
<CheckGroup
:list="infoList"
@change="handleChange"
:default-value="defaultInfo"
value-key="id"
label-key="name"
/>
</template>
<script lang="ts" setup>
import { getUniversityType } from '@/service/index/api'
import CheckGroup from '@/pages-evaluation-sub/components/check-group/CheckGroup.vue'
const infoList = ref()
getUniversityType().then((res) => {
if (res.code === 200) {
infoList.value = res.result as { id: number; name: string }[]
}
})
const defaultInfo = ref<string[]>([])
const emits = defineEmits(['change', 'changeName'])
const handleChange = (val: any) => {
const names = infoList.value.filter((item) => val.includes(item.id)).map((item) => item.name)
emits('changeName', names)
emits('change', val)
}
</script>

File diff suppressed because one or more lines are too long

View File

@ -1,12 +0,0 @@
.custom-check-group {
:deep(.checkbox-group) {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16rpx;
padding: 24rpx 24rpx 36rpx;
}
:deep(.custom-checkbox) {
--checkbox-width: 100%;
}
}

View File

@ -1,13 +0,0 @@
.custom-background {
background-image: linear-gradient(
173deg,
rgb(177, 221, 250) 0,
rgb(177, 221, 250) 13%,
rgba(255, 255, 255, 1) 80%,
rgba(255, 255, 255, 1) 100%
);
background-position: 50% 50%;
background-origin: padding-box;
background-clip: border-box;
background-size: auto auto;
}

View File

@ -1,3 +0,0 @@
:deep(.z-tabs-bottom) {
border-bottom: 1px solid #f8f8f8;
}

Some files were not shown because too many files have changed in this diff Show More