fix
1
activities/.env.development
Normal file
@@ -0,0 +1 @@
|
||||
VITE_APP_URL = ''
|
||||
1
activities/.env.production
Normal file
@@ -0,0 +1 @@
|
||||
VITE_APP_URL = http://18.167.251.121:10096
|
||||
1
activities/.env.test
Normal file
@@ -0,0 +1 @@
|
||||
VITE_APP_URL = http://18.167.251.121:10095
|
||||
15
activities/.eslintrc.cjs
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript',
|
||||
'@vue/eslint-config-prettier/skip-formatting'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
||||
28
activities/.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
4
activities/.husky/pre-commit
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
8
activities/.prettierrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
3
activities/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||
}
|
||||
46
activities/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# vue3demo
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||
|
||||
1. Disable the built-in TypeScript Extension
|
||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
8
activities/auto-imports.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
|
||||
}
|
||||
23
activities/components.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
|
||||
IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
|
||||
IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']
|
||||
IconEcosystem: typeof import('./src/components/icons/IconEcosystem.vue')['default']
|
||||
IconSupport: typeof import('./src/components/icons/IconSupport.vue')['default']
|
||||
IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
TheWelcome: typeof import('./src/components/TheWelcome.vue')['default']
|
||||
WelcomeItem: typeof import('./src/components/WelcomeItem.vue')['default']
|
||||
}
|
||||
}
|
||||
1
activities/env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
15
activities/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
|
||||
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> -->
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
|
||||
<title>Activities</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
8955
activities/package-lock.json
generated
Normal file
54
activities/package.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "vue3demo",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"test": "vite --mode test",
|
||||
"build": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/",
|
||||
"postinstall": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.3.6",
|
||||
"element-plus": "^2.10.4",
|
||||
"gsap": "^3.13.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"pinia": "^2.0.32",
|
||||
"pinia-persistedstate-plugin": "^0.1.0",
|
||||
"pinia-plugin-persistedstate": "^3.1.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.2.0",
|
||||
"@types/node": "^18.16.0",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/eslint-config-prettier": "^7.1.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"husky": "^8.0.3",
|
||||
"less": "^4.3.0",
|
||||
"lint-staged": "^13.2.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.8.4",
|
||||
"typescript": "~4.8.4",
|
||||
"unplugin-auto-import": "^0.15.3",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"vite": "^4.1.4",
|
||||
"vue-tsc": "^1.2.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{vue,js}": [
|
||||
"npm run lint"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
activities/public/css/woff/Poppins/Poppins-Black.otf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Black.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-BlackItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Bold.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-BoldItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-ExtraBold.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-ExtraBoldItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-ExtraLight.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-ExtraLightItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Italic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Light.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-LightItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Medium.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-MediumItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Regular.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-SemiBold.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-SemiBoldItalic.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-Thin.ttf
Normal file
BIN
activities/public/css/woff/Poppins/Poppins-ThinItalic.ttf
Normal file
29
activities/public/css/woff/poppins.css
Normal file
@@ -0,0 +1,29 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'poppinsRegular';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url(./Poppins/Poppins-Regular.ttf) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'poppinsSemiBold';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url(./Poppins/Poppins-SemiBold.ttf) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'poppinsBold';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url(./Poppins/Poppins-Bold.ttf) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'poppinsMedium';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url(./Poppins/Poppins-Medium.ttf) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
BIN
activities/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
40
activities/src/App.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
#app{
|
||||
|
||||
font-size: 1.6rem;
|
||||
box-sizing: border-box;
|
||||
overscroll-behavior: none;
|
||||
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
*{
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
touch-action: pan-x pan-y; /* 允许单指平移(滚动)但禁用捏合缩放 */
|
||||
}
|
||||
|
||||
// touch-action: none; /* 完全禁用浏览器默认触摸行为 */
|
||||
// -webkit-user-select: none;
|
||||
// -moz-user-select: none;
|
||||
// -ms-user-select: none;
|
||||
// user-select: none;
|
||||
// -webkit-touch-callout: none;
|
||||
@media (min-width: 1024px) {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position:relative
|
||||
}
|
||||
/* touch-action: none; */
|
||||
}
|
||||
</style>
|
||||
39
activities/src/api/workshop.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import request from '@/utils/request'
|
||||
//创建用户
|
||||
export function userCreate(params: Object) {
|
||||
return request({
|
||||
url: '/api/user/create',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
//记录用户选择的信息
|
||||
export function userSave(params: Object) {
|
||||
return request({
|
||||
url: '/api/user/save',
|
||||
method: 'get',
|
||||
params,
|
||||
meta: {
|
||||
// responseAll: true // 返回所有的信息,包括状态码和message和data
|
||||
}
|
||||
} as any)
|
||||
}
|
||||
|
||||
//获取题目
|
||||
export function getQueryPage(data: Object) {
|
||||
return request({
|
||||
url: '/api/outfits/queryPage',
|
||||
method: 'post',
|
||||
data,
|
||||
// repeatRequest: true // 配置为true,则可以同一时间多次调用
|
||||
}as any)
|
||||
}
|
||||
|
||||
//查报告
|
||||
export function getCalculateReport() {
|
||||
return request({
|
||||
url: '/api/outfits/calculateReport',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
74
activities/src/assets/base.css
Normal file
@@ -0,0 +1,74 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
10
activities/src/assets/css/style.css
Normal file
@@ -0,0 +1,10 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
0
activities/src/assets/css/style.less
Normal file
BIN
activities/src/assets/images/workshop/11.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
activities/src/assets/images/workshop/22.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
3
activities/src/assets/images/workshop/back.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.77201 14.9283L8.9297 15.7417C8.57304 16.0861 7.99632 16.0861 7.64345 15.7417L0.267492 8.62285C-0.0891642 8.27845 -0.0891642 7.72155 0.267492 7.38081L7.64345 0.258301C8.00011 -0.0861003 8.57683 -0.0861003 8.9297 0.258301L9.77201 1.07167C10.1325 1.41974 10.1249 1.98763 9.75683 2.32837L5.1848 6.53446H16.0894C16.594 6.53446 17 6.92649 17 7.41378V8.58622C17 9.07351 16.594 9.46554 16.0894 9.46554H5.1848L9.75683 13.6716C10.1287 14.0124 10.1363 14.5803 9.77201 14.9283Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 597 B |
BIN
activities/src/assets/images/workshop/editHanger.png
Normal file
|
After Width: | Height: | Size: 483 B |
BIN
activities/src/assets/images/workshop/editLike.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
activities/src/assets/images/workshop/editNoLike.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
activities/src/assets/images/workshop/editOpenGroup.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
activities/src/assets/images/workshop/editProfile.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
activities/src/assets/images/workshop/editProfile1.jpg
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
activities/src/assets/images/workshop/loading.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
activities/src/assets/images/workshop/loadingPage.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
activities/src/assets/images/workshop/loginTitleImg.png
Normal file
|
After Width: | Height: | Size: 733 B |
BIN
activities/src/assets/images/workshop/success.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
activities/src/assets/images/workshop/successGoTo.png
Normal file
|
After Width: | Height: | Size: 577 B |
BIN
activities/src/assets/images/workshop/workshop2Back.png
Normal file
|
After Width: | Height: | Size: 249 B |
BIN
activities/src/assets/images/workshop/workshop2Bot.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
activities/src/assets/images/workshop/workshop2No.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
activities/src/assets/images/workshop/workshop2Ranking.png
Normal file
|
After Width: | Height: | Size: 664 B |
BIN
activities/src/assets/images/workshop/workshop2SuccessBg.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
activities/src/assets/images/workshop/workshop2Topic.png
Normal file
|
After Width: | Height: | Size: 461 B |
BIN
activities/src/assets/images/workshop/workshop2TopicList.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
activities/src/assets/images/workshop/workshop2TopicOne.png
Normal file
|
After Width: | Height: | Size: 880 B |
BIN
activities/src/assets/images/workshop/workshop2Yes.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
activities/src/assets/images/workshop/workshopRestart.png
Normal file
|
After Width: | Height: | Size: 398 B |
BIN
activities/src/assets/images/workshop/workshopRight.png
Normal file
|
After Width: | Height: | Size: 333 B |
BIN
activities/src/assets/images/workshop/workshopTopThree.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
1
activities/src/assets/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
|
After Width: | Height: | Size: 276 B |
31
activities/src/assets/main.css
Normal file
@@ -0,0 +1,31 @@
|
||||
@import './base.css';
|
||||
|
||||
#app {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
/* @media (min-width: 1024px) {
|
||||
body {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
} */
|
||||
40
activities/src/components/HelloWorld.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
msg: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="greetings">
|
||||
<h1 class="green">{{ msg }}</h1>
|
||||
<h3>
|
||||
You’ve successfully created a project with
|
||||
<a href="https://vitejs.dev/" target="_blank" rel="noopener">Vite</a> +
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>. What's next?
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
h1 {
|
||||
font-weight: 500;
|
||||
font-size: 2.6rem;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
86
activities/src/components/TheWelcome.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<script setup lang="ts">
|
||||
import WelcomeItem from './WelcomeItem.vue'
|
||||
import DocumentationIcon from './icons/IconDocumentation.vue'
|
||||
import ToolingIcon from './icons/IconTooling.vue'
|
||||
import EcosystemIcon from './icons/IconEcosystem.vue'
|
||||
import CommunityIcon from './icons/IconCommunity.vue'
|
||||
import SupportIcon from './icons/IconSupport.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<DocumentationIcon />
|
||||
</template>
|
||||
<template #heading>Documentation</template>
|
||||
|
||||
Vue’s
|
||||
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
|
||||
provides you with all information you need to get started.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<ToolingIcon />
|
||||
</template>
|
||||
<template #heading>Tooling</template>
|
||||
|
||||
This project is served and bundled with
|
||||
<a href="https://vitejs.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
|
||||
recommended IDE setup is
|
||||
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a> +
|
||||
<a href="https://github.com/johnsoncodehk/volar" target="_blank" rel="noopener">Volar</a>. If
|
||||
you need to test your components and web pages, check out
|
||||
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a> and
|
||||
<a href="https://on.cypress.io/component" target="_blank">Cypress Component Testing</a>.
|
||||
|
||||
<br />
|
||||
|
||||
More instructions are available in <code>README.md</code>.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<EcosystemIcon />
|
||||
</template>
|
||||
<template #heading>Ecosystem</template>
|
||||
|
||||
Get official tools and libraries for your project:
|
||||
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
|
||||
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
|
||||
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
|
||||
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
|
||||
you need more resources, we suggest paying
|
||||
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
|
||||
a visit.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<CommunityIcon />
|
||||
</template>
|
||||
<template #heading>Community</template>
|
||||
|
||||
Got stuck? Ask your question on
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>, our official
|
||||
Discord server, or
|
||||
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
|
||||
>StackOverflow</a
|
||||
>. You should also subscribe to
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">our mailing list</a> and follow
|
||||
the official
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
|
||||
twitter account for latest news in the Vue world.
|
||||
</WelcomeItem>
|
||||
|
||||
<WelcomeItem>
|
||||
<template #icon>
|
||||
<SupportIcon />
|
||||
</template>
|
||||
<template #heading>Support Vue</template>
|
||||
|
||||
As an independent project, Vue relies on community backing for its sustainability. You can help
|
||||
us by
|
||||
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
|
||||
</WelcomeItem>
|
||||
</template>
|
||||
86
activities/src/components/WelcomeItem.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="item">
|
||||
<i>
|
||||
<slot name="icon"></slot>
|
||||
</i>
|
||||
<div class="details">
|
||||
<h3>
|
||||
<slot name="heading"></slot>
|
||||
</h3>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.item {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.details {
|
||||
flex: 1;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.4rem;
|
||||
color: var(--color-heading);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.item {
|
||||
margin-top: 0;
|
||||
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
i {
|
||||
top: calc(50% - 25px);
|
||||
left: -26px;
|
||||
position: absolute;
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-background);
|
||||
border-radius: 8px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.item:before {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:after {
|
||||
content: ' ';
|
||||
border-left: 1px solid var(--color-border);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: calc(50% + 25px);
|
||||
height: calc(50% - 25px);
|
||||
}
|
||||
|
||||
.item:first-of-type:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.item:last-of-type:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
7
activities/src/components/icons/IconCommunity.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
activities/src/components/icons/IconDocumentation.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
activities/src/components/icons/IconEcosystem.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
7
activities/src/components/icons/IconSupport.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
19
activities/src/components/icons/IconTooling.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
5
activities/src/env.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
declare module '*.vue' {
|
||||
import { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
32
activities/src/main.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { createApp } from 'vue'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
// import ElementPlus from 'element-plus'
|
||||
import store from './stores/index'
|
||||
import 'normalize.css/normalize.css'
|
||||
import './assets/css/style.css'
|
||||
|
||||
import flexible from "./utils/flexible.js";
|
||||
|
||||
//引入element-plus相关样式
|
||||
import 'element-plus/dist/index.css'
|
||||
import './assets/main.css'
|
||||
import "./router/router-config" // 路由守卫,做动态路由的地方
|
||||
|
||||
var lastTouchEnd = 0;
|
||||
document.addEventListener('touchend', function(event) {
|
||||
var now = (new Date()).getTime();
|
||||
if (now - lastTouchEnd <= 300) {
|
||||
event.preventDefault();
|
||||
}
|
||||
lastTouchEnd = now;
|
||||
}, false);
|
||||
|
||||
const app = createApp(App)
|
||||
// app.use(ElementPlus)
|
||||
app.use(router)
|
||||
app.use(store)
|
||||
flexible();
|
||||
|
||||
app.mount('#app')
|
||||
80
activities/src/router/index.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
const router = createRouter({
|
||||
history: createWebHistory('/'),
|
||||
// history: createWebHistory(import.meta.env.VITE_APP_URL),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
redirect: "/activities",
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'about',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (About.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import('../views/AboutView.vue')
|
||||
},{
|
||||
path: '/activities',
|
||||
name: 'Activities',
|
||||
component: () => import('../views/Activities/index.vue'),
|
||||
children: [
|
||||
// {
|
||||
// path: '',
|
||||
// name: 'activitiesWorkshop',
|
||||
// redirect: "/activities/workshop",
|
||||
// },
|
||||
{
|
||||
path: "workshop",
|
||||
name: "Workshop",
|
||||
component: () => import('../views/Activities/workshop/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'adtivitiesWorkshopLogin',
|
||||
redirect: "/activities/workshop/login",
|
||||
},{
|
||||
path: "login",
|
||||
name: "login",
|
||||
component: () => import('../views/Activities/workshop/views/login.vue'),
|
||||
},{
|
||||
path: "edit",
|
||||
name: "edit",
|
||||
component: () => import('../views/Activities/workshop/views/edit.vue'),
|
||||
},{
|
||||
path: "success",
|
||||
name: "success",
|
||||
component: () => import('../views/Activities/workshop/views/success.vue'),
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "workshop2",
|
||||
name: "Workshop2",
|
||||
component: () => import('../views/Activities/workshop2/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'adtivitiesWorkshop2Login',
|
||||
redirect: "/activities/workshop2/login",
|
||||
},{
|
||||
path: "login",
|
||||
name: "login2",
|
||||
component: () => import('../views/Activities/workshop2/views/login.vue'),
|
||||
},{
|
||||
path: "edit",
|
||||
name: "edit2",
|
||||
component: () => import('../views/Activities/workshop2/views/edit.vue'),
|
||||
},{
|
||||
path: "success",
|
||||
name: "success2",
|
||||
component: () => import('../views/Activities/workshop2/views/success.vue'),
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
export default router
|
||||
14
activities/src/router/router-config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import router from './index'
|
||||
|
||||
// 白名单页面直接进入
|
||||
const whiteList = ['/login']
|
||||
console.log(whiteList)
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
router.afterEach(() => {
|
||||
// finish progress bar
|
||||
// NProgress.done()
|
||||
})
|
||||
7
activities/src/stores/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createPinia } from 'pinia'
|
||||
import { createPersistedState } from 'pinia-persistedstate-plugin'
|
||||
// 创建store实例
|
||||
const store = createPinia()
|
||||
// 使用持久化插件(全局持久化)
|
||||
store.use(createPersistedState())
|
||||
export default store
|
||||
26
activities/src/stores/modules/userInfo.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// 每一个存储的模块,命名规则use开头,store结尾
|
||||
import { defineStore } from 'pinia'
|
||||
export const useUserInfoStore = defineStore({
|
||||
id: 'userInfo', // 必须指明唯一的pinia仓库的id
|
||||
state: () => {
|
||||
return {
|
||||
num: 0,
|
||||
name: '张三',
|
||||
token: ''
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
doubleCount: (state) => state.num * 2
|
||||
},
|
||||
actions: {
|
||||
changeNum() {
|
||||
this.num++
|
||||
},
|
||||
loginOut() {
|
||||
// 处理退出登录的一些逻辑
|
||||
return new Promise((rez) => {
|
||||
rez('111')
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
31
activities/src/stores/modules/workshop.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// 每一个存储的模块,命名规则use开头,store结尾
|
||||
import { defineStore } from 'pinia'
|
||||
export const useWorkshopStore = defineStore({
|
||||
id: 'workshop', // 必须指明唯一的pinia仓库的id
|
||||
state: () => {
|
||||
return {
|
||||
userData:{
|
||||
title: '123123',
|
||||
name: '123123',
|
||||
describe: '',
|
||||
id:'',
|
||||
},
|
||||
queryList:[]
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
// doubleCount: (state) => state.num * 2
|
||||
},
|
||||
actions: {
|
||||
setLogin(data:any) {
|
||||
this.userData.title= data.title
|
||||
this.userData.name= data.name
|
||||
this.userData.describe= data.describe
|
||||
this.userData.id= data.id
|
||||
console.log(this.userData)
|
||||
},
|
||||
setQueryList(list:any) {
|
||||
this.queryList = list
|
||||
},
|
||||
}
|
||||
})
|
||||
48
activities/src/utils/flexible.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import { getUniversalZoomLevel } from '@/utils/tools'
|
||||
|
||||
let flexible = (designWidth, maxWidth,minWidth) =>{
|
||||
var doc = document, win = window, docEl = doc.documentElement, remStyle = document.createElement("style"), tid;
|
||||
designWidth = designWidth || 1920;
|
||||
// maxWidth = maxWidth || 1920;
|
||||
// minWidth = minWidth || 500;
|
||||
// minWidth = minWidth || 1024;
|
||||
function refreshRem() {
|
||||
var width = docEl.getBoundingClientRect().width;
|
||||
var height = docEl.getBoundingClientRect().height;
|
||||
width = getUniversalZoomLevel() * width
|
||||
height = getUniversalZoomLevel() * height
|
||||
// width > maxWidth && (width = maxWidth);
|
||||
// width < minWidth && (width = minWidth);
|
||||
if(width >= 1024){
|
||||
designWidth = 1920
|
||||
}else{
|
||||
designWidth = 375
|
||||
}
|
||||
var rem = Math.round(width * 10 / designWidth);
|
||||
docEl.style.fontSize = rem+'px'
|
||||
remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
|
||||
}
|
||||
//要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
|
||||
refreshRem();
|
||||
win.addEventListener("resize", function() {
|
||||
clearTimeout(tid); //防止执行两次
|
||||
tid = setTimeout(refreshRem, 300);
|
||||
}, false);
|
||||
|
||||
win.addEventListener("pageshow", function(e) {
|
||||
if (e.persisted) { // 浏览器后退的时候重新计算
|
||||
clearTimeout(tid);
|
||||
tid = setTimeout(refreshRem, 300);
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (doc.readyState === "complete") {
|
||||
doc.body.style.fontSize = "16px";
|
||||
} else {
|
||||
doc.addEventListener("DOMContentLoaded", function(e) {
|
||||
doc.body.style.fontSize = "16px";
|
||||
}, false);
|
||||
}
|
||||
};
|
||||
|
||||
export default flexible
|
||||
12
activities/src/utils/local.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
function getLocal(key = 'token') {
|
||||
return localStorage.getItem(key)
|
||||
}
|
||||
// 删除
|
||||
function removeLocal(key = 'token') {
|
||||
window.localStorage.removeItem(key)
|
||||
}
|
||||
// 保存
|
||||
function setLocal(value: any, key = 'token') {
|
||||
window.localStorage.setItem(key, value)
|
||||
}
|
||||
export { getLocal, removeLocal, setLocal }
|
||||
173
activities/src/utils/request.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import axios from 'axios'
|
||||
// import { Message, Loading, MessageBox } from 'element-ui'
|
||||
import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
|
||||
import { useUserInfoStore } from '@/stores/modules/userInfo'
|
||||
const store = useUserInfoStore()
|
||||
import { getLocal } from '@/utils/local'
|
||||
|
||||
// 创建axios实例
|
||||
console.log(import.meta.env.VITE_APP_URL)
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_URL, // api的base_url
|
||||
// baseURL: import.meta.env.VITE_APP_URL, // api的base_url
|
||||
timeout: 5000 // 请求超时时间
|
||||
})
|
||||
axios.defaults.headers.post["Content-Type"] = "application/json";
|
||||
axios.defaults.headers.post['lang'] = 'en'; //配置语言请求头
|
||||
axios.defaults.withCredentials = true; //跨域携带cookie
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
(config: any) => {
|
||||
removePending(config)
|
||||
// 如果repeatRequest不配置,那么默认该请求就取消重复接口请求
|
||||
!config.repeatRequest && addPending(config)
|
||||
// 打开loading
|
||||
if (config.loading) {
|
||||
LoadingInstance._count++
|
||||
if (LoadingInstance._count === 1) {
|
||||
openLoading(config.loadingDom)
|
||||
}
|
||||
}
|
||||
// 如果登录了,有token,则请求携带token
|
||||
// Do something before request is sent
|
||||
if (store.token) {
|
||||
config.headers.Authorization = getLocal('token') // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
|
||||
// config.headers['X-Token'] = getLocal('token') // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
// Do something with request error
|
||||
console.log(error) // for debug
|
||||
Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// respone拦截器
|
||||
service.interceptors.response.use(
|
||||
// response => response,
|
||||
/**
|
||||
* 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
|
||||
* 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
|
||||
*/
|
||||
(response: any) => {
|
||||
// 已完成请求的删除请求中数组
|
||||
removePending(response.config)
|
||||
// 关闭loading
|
||||
if (response.config.loading) {
|
||||
closeLoading()
|
||||
}
|
||||
|
||||
const res = response.data
|
||||
// 处理异常的情况
|
||||
if (res.errCode != 0) {
|
||||
ElMessage({
|
||||
message: res.errMsg,
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
// 403:非法的token; 50012:其他客户端登录了; 401:Token 过期了;
|
||||
if (res.errCode === 403 || res.errCode === 50012 || res.errCode === 401) {
|
||||
ElMessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
|
||||
confirmButtonText: '重新登录',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
store.loginOut().then(() => {
|
||||
location.reload() // 为了重新实例化vue-router对象 避免bug
|
||||
})
|
||||
})
|
||||
}
|
||||
return Promise.reject(new Error('error'))
|
||||
} else {
|
||||
// 默认只返回data,不返回状态码和message
|
||||
// 通过 meta 中的 responseAll 配置来取决后台是否返回所有数据(包括状态码,message和data)
|
||||
const isbackAll = response.config.meta && response.config.meta.responseAll
|
||||
if (isbackAll) {
|
||||
return res
|
||||
} else {
|
||||
return res.data
|
||||
}
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
error.config && removePending(error.config)
|
||||
// 关闭loading
|
||||
if (error.config?.loading) {
|
||||
closeLoading()
|
||||
}
|
||||
console.log('err' + error) // for debug
|
||||
ElMessage({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// --------------------------------取消接口重复请求的函数-----------------------------------
|
||||
// axios.js
|
||||
const pendingMap = new Map()
|
||||
/**
|
||||
* 生成每个请求唯一的键
|
||||
* @param {*} config
|
||||
* @returns string
|
||||
*/
|
||||
function getPendingKey(config: any) {
|
||||
const { url, method, params } = config
|
||||
let { data } = config
|
||||
if (typeof data === 'string') data = JSON.parse(data) // response里面返回的config.data是个字符串对象
|
||||
return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
|
||||
}
|
||||
|
||||
/**
|
||||
* 储存每个请求唯一值, 也就是cancel()方法, 用于取消请求
|
||||
* @param {*} config
|
||||
*/
|
||||
function addPending(config: any) {
|
||||
const pendingKey = getPendingKey(config)
|
||||
config.cancelToken =
|
||||
config.cancelToken ||
|
||||
new axios.CancelToken((cancel) => {
|
||||
if (!pendingMap.has(pendingKey)) {
|
||||
pendingMap.set(pendingKey, cancel)
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 删除重复的请求
|
||||
* @param {*} config
|
||||
*/
|
||||
function removePending(config: any) {
|
||||
const pendingKey = getPendingKey(config)
|
||||
if (pendingMap.has(pendingKey)) {
|
||||
const cancelToken = pendingMap.get(pendingKey)
|
||||
cancelToken(pendingKey)
|
||||
pendingMap.delete(pendingKey)
|
||||
}
|
||||
}
|
||||
// ----------------------------------loading的函数-------------------------------
|
||||
const LoadingInstance: { _target: any; _count: number } = {
|
||||
_target: null, // 保存Loading实例
|
||||
_count: 0
|
||||
}
|
||||
function openLoading(loadingDom: any) {
|
||||
LoadingInstance._target = ElLoading.service({
|
||||
lock: true,
|
||||
text: '数据正在加载中',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(25, 32, 53, 1)',
|
||||
target: loadingDom || 'body'
|
||||
})
|
||||
}
|
||||
function closeLoading() {
|
||||
if (LoadingInstance._count > 0) LoadingInstance._count--
|
||||
if (LoadingInstance._count === 0) {
|
||||
LoadingInstance._target.close()
|
||||
LoadingInstance._target = null
|
||||
}
|
||||
}
|
||||
|
||||
export default service
|
||||
48
activities/src/utils/tools.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
function getUniversalZoomLevel() {
|
||||
// 现代浏览器方案
|
||||
if (window.visualViewport) {
|
||||
return window.visualViewport.scale;
|
||||
}
|
||||
// 备用方案1
|
||||
if (window.devicePixelRatio) {
|
||||
return window.devicePixelRatio;
|
||||
}
|
||||
// 备用方案2(不精确)
|
||||
return window.outerWidth / window.innerWidth;
|
||||
}
|
||||
const getMousePosition = (e:any,bor:any) => {
|
||||
// if(e?.stopPropagation)e.stopPropagation()
|
||||
// if(e?.preventDefault)e.preventDefault();
|
||||
let event:any
|
||||
if(bor){
|
||||
const touch = e.changedTouches[0] as any;
|
||||
event = {
|
||||
offsetX:touch.clientX - e.target.getBoundingClientRect().left,
|
||||
offsetY: touch.clientY - e.target.getBoundingClientRect().top,
|
||||
clientX:touch.clientX,
|
||||
clientY:touch.clientY,
|
||||
screenX:touch.screenX,
|
||||
screenY:touch.screenY,
|
||||
target:e.target,
|
||||
}
|
||||
// if(dom){
|
||||
// event.offsetX = touch.clientX - dom.getBoundingClientRect().left
|
||||
// event.offsetY = touch.clientY - dom.getBoundingClientRect().top
|
||||
// }
|
||||
}else{
|
||||
event = {
|
||||
offsetX:e.offsetX,
|
||||
offsetY:e.offsetY,
|
||||
clientX:e.clientX,
|
||||
clientY:e.clientY,
|
||||
screenX:e.screenX,
|
||||
screenY:e.screenY,
|
||||
target:e.target,
|
||||
}
|
||||
}
|
||||
return event
|
||||
}
|
||||
export {
|
||||
getUniversalZoomLevel,
|
||||
getMousePosition,
|
||||
}
|
||||
15
activities/src/views/AboutView.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@media (min-width: 1024px) {
|
||||
.about {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
22
activities/src/views/Activities/index.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<!-- <script setup lang="ts">
|
||||
|
||||
</script> -->
|
||||
<template>
|
||||
<div class="activities">
|
||||
<RouterView />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.activities {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
font-family: poppinsMedium;
|
||||
}
|
||||
// @media (min-width: 1024px) {
|
||||
|
||||
// }
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import {getCalculateReport} from '@/api/workshop'
|
||||
|
||||
const props = defineProps({
|
||||
isSummaryReport:{
|
||||
type:Boolean,
|
||||
default:false,
|
||||
},
|
||||
calculateReport:{
|
||||
type:Object,
|
||||
default:()=>{},
|
||||
},
|
||||
})
|
||||
const emit = defineEmits([
|
||||
'update:isSummaryReport'
|
||||
])
|
||||
let data = reactive({
|
||||
})
|
||||
const goBack = ()=>{
|
||||
emit('update:isSummaryReport',false)
|
||||
}
|
||||
onMounted(()=>{
|
||||
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const {} = toRefs(data);
|
||||
</script>
|
||||
<template>
|
||||
<div class="summaryReport">
|
||||
<div class="header">
|
||||
Swipe Style
|
||||
<img @click="goBack" src="@/assets/images/workshop/back.svg" alt="">
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="text">
|
||||
<div class="title">Summary Report!</div>
|
||||
<div class="progress">Current progress: {{ calculateReport?.count }}/{{ calculateReport?.count + calculateReport?.answeringCount }} people</div>
|
||||
<!-- <div class="info">Based on the choice of the majority, system<br /> detected the most popular trends for you: <span>XXX</span>.</div> -->
|
||||
</div>
|
||||
<div class="popularChoices swiper">
|
||||
<div class="title">Popular Choices</div>
|
||||
<div class="imgBox">
|
||||
<div class="imgList">
|
||||
<div class="item" v-for="item in calculateReport?.mostLikeOutfits">
|
||||
<img :src="item?.outfitImagePath" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="text middle">
|
||||
<div class="info">System detected the most unpopular trends for you: <br /> <span>XXX/XXX/XXX</span>.</div>
|
||||
</div> -->
|
||||
<div class="unpopularChoices swiper">
|
||||
<div class="title">Unpopular Choices</div>
|
||||
<div class="imgBox">
|
||||
<div class="imgList">
|
||||
<div class="item" v-for="item in calculateReport?.leastLikeOutfits">
|
||||
<img :src="item?.outfitImagePath" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.summaryReport{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
> .header{
|
||||
padding: .9rem 0;
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
font-size: 2.2rem;
|
||||
text-align: center;
|
||||
font-family: poppinsBold;
|
||||
> img{
|
||||
position: absolute;
|
||||
left: 3rem;
|
||||
width: 1.7rem;
|
||||
height: 1.7rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
> .body{
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
> .text{
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
> .progress{
|
||||
font-size: 1rem;
|
||||
color: #cdcdcd;
|
||||
font-weight: 500;
|
||||
}
|
||||
> .title{
|
||||
font-weight: 500;
|
||||
font-size: 2rem;
|
||||
color: #4D52C3;
|
||||
}
|
||||
> .info{
|
||||
font-weight: 400;
|
||||
font-size: 1.2rem;
|
||||
color: #000;
|
||||
margin-top: 1.2rem;
|
||||
> span{
|
||||
font-weight: 600;
|
||||
color: #4d52c3;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .swiper{
|
||||
width: calc(100% - 3.2rem * 2);
|
||||
margin: 0 auto;
|
||||
margin-top: 2.4rem;
|
||||
> .title{
|
||||
font-weight: 500;
|
||||
font-size: 1.6rem;
|
||||
// margin-bottom: 1.2rem;
|
||||
}
|
||||
> .imgBox{
|
||||
margin-top: 1.6rem;
|
||||
> .imgList{
|
||||
width: auto;
|
||||
overflow-x: auto;
|
||||
display: flex;
|
||||
> .item{
|
||||
shrink: 0;
|
||||
padding-bottom: 1.2rem;
|
||||
padding-right: 1.2rem;
|
||||
> img{
|
||||
// margin-right: 1.2rem;
|
||||
|
||||
width: 12.8rem;
|
||||
height: 19.2rem;
|
||||
border-radius: 1rem;
|
||||
box-shadow: .7rem .4rem 1rem 0rem rgba(0,0,0,.2);
|
||||
object-fit: contain;
|
||||
&:last-child{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .popularChoices{
|
||||
> .imgBox{
|
||||
> .imgList{
|
||||
padding-bottom: calc(5.2rem - 2.4rem);
|
||||
}
|
||||
> .imgList::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .unpopularChoices{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
90
activities/src/views/Activities/workshop/index.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import {getQueryPage} from '@/api/workshop'
|
||||
import { useWorkshopStore } from '@/stores/modules/workshop'
|
||||
import { useRouter,useRoute, onBeforeRouteLeave } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const store = useWorkshopStore()
|
||||
let dataDom = reactive({
|
||||
loadingDom:null as any,
|
||||
})
|
||||
let data = reactive({
|
||||
|
||||
})
|
||||
const handleBeforeUnload = (e:any) => {
|
||||
if (window.location.pathname === '/activities/workshop/success') {
|
||||
localStorage.setItem('shouldRedirectAfterRefresh', 'true');
|
||||
// e.preventDefault();
|
||||
// e.returnValue = '刷新后将跳转到登录页';
|
||||
}
|
||||
|
||||
};
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
if (confirm('自定义提示:确定离开当前页面吗?')) {
|
||||
next();
|
||||
} else {
|
||||
next(false);
|
||||
}
|
||||
});
|
||||
onMounted(()=>{
|
||||
getQueryPage({page:1,size:200}).then((rv:any)=>{
|
||||
store.setQueryList(rv.content)
|
||||
})
|
||||
setTimeout(()=>{
|
||||
dataDom.loadingDom.style.opacity = '0';
|
||||
setTimeout(()=>{
|
||||
dataDom.loadingDom.style.display = 'none';
|
||||
},1000)
|
||||
},3000)
|
||||
|
||||
if (localStorage.getItem('shouldRedirectAfterRefresh') === 'true') {
|
||||
localStorage.removeItem('shouldRedirectAfterRefresh'); // 清除标记
|
||||
router.push('/activities/workshop/login'); // 跳转
|
||||
}
|
||||
window.addEventListener('pagehide', handleBeforeUnload)
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
window.removeEventListener('pagehide', handleBeforeUnload)
|
||||
})
|
||||
|
||||
const { loadingDom } = toRefs(dataDom);
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="workshop">
|
||||
<div class="loading" ref="loadingDom">
|
||||
<img src="@/assets/images/workshop/loadingPage.png" alt="">
|
||||
</div>
|
||||
<RouterView />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workshop {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
> .loading{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
transition: all 1s;
|
||||
background: #fff;
|
||||
img{
|
||||
width: 25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
332
activities/src/views/Activities/workshop/views/edit.vue
Normal file
@@ -0,0 +1,332 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs, computed, watch } from "vue";
|
||||
import { getMousePosition } from '@/utils/tools'
|
||||
import { useWorkshopStore } from '@/stores/modules/workshop'
|
||||
import { gsap, TweenMax } from "gsap";
|
||||
import {userSave} from '@/api/workshop'
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
const store = useWorkshopStore()
|
||||
const router = useRouter()
|
||||
|
||||
let data = reactive({
|
||||
imgEvent:{} as any,
|
||||
tlRight:gsap.timeline({ paused: true }),
|
||||
tlLeft:gsap.timeline({ paused: true }),
|
||||
editList:[
|
||||
{
|
||||
id:1,
|
||||
},
|
||||
{
|
||||
id:2,
|
||||
},
|
||||
],
|
||||
selectIndex:0 as any,
|
||||
maskShow:false,
|
||||
dressStyle:{},
|
||||
})
|
||||
let queryList = computed(()=>store.queryList) as any
|
||||
|
||||
let imgDom = ref()
|
||||
let editDom = ref()
|
||||
let noLikeDom = ref()
|
||||
let likeDom = ref()
|
||||
let maskDom = ref()
|
||||
const next = (moveSize:any)=>{
|
||||
editDom.value.style.transition = 'all .3s'
|
||||
editDom.value.style.opacity = '0'
|
||||
if(moveSize > 0){
|
||||
queryList.value[data.selectIndex].count = false
|
||||
}else{
|
||||
queryList.value[data.selectIndex].count = true
|
||||
}
|
||||
|
||||
setTimeout(()=>{
|
||||
data.selectIndex++
|
||||
editDom.value.style.transition = ''
|
||||
editDom.value.style.opacity = '1'
|
||||
data.tlLeft.progress(0)
|
||||
data.tlRight.progress(0)
|
||||
},300)
|
||||
|
||||
}
|
||||
const setLikeOrOnLike = (event:any)=>{
|
||||
imgDom.value.style.transition = ''
|
||||
data.imgEvent = event
|
||||
|
||||
// document.addEventListener('mousemove', sizeMouseMove);
|
||||
document.addEventListener('touchmove', sizeTouchmove);
|
||||
// document.addEventListener('mouseup', sizeMouseup);
|
||||
document.addEventListener('touchend', sizeMouseup);
|
||||
}
|
||||
const sizeTouchmove = (event:any)=>{
|
||||
let e:any = getMousePosition(event,true)
|
||||
let moveSize = data.imgEvent.screenX - e?.screenX
|
||||
let domWidth = e?.target.parentNode.parentNode.offsetWidth
|
||||
if(moveSize > 0){
|
||||
data.tlLeft.progress(Math.abs(moveSize) / domWidth)
|
||||
}else{
|
||||
data.tlRight.progress(Math.abs(moveSize) / domWidth)
|
||||
}
|
||||
}
|
||||
const sizeMouseup = (event:any)=>{
|
||||
let e:any = getMousePosition(event,true)
|
||||
let moveSize = data.imgEvent.screenX - e?.screenX
|
||||
let domWidth = e?.target.parentNode.parentNode.offsetWidth
|
||||
let moveScale = Math.abs(moveSize) / domWidth
|
||||
if(moveScale > .4){
|
||||
next(moveSize)
|
||||
// emit('setLikeOrOnLike',moveSize > 0?'onLike':'like')
|
||||
}else{
|
||||
imgDom.value.style.transition = 'all .3s'
|
||||
data.tlLeft.progress(0)
|
||||
data.tlRight.progress(0)
|
||||
}
|
||||
// document.removeEventListener('mousemove',this.sizeMouseMove)
|
||||
document.removeEventListener('touchmove',sizeTouchmove)
|
||||
// document.removeEventListener('mouseup',this.sizeMouseup)
|
||||
document.removeEventListener('touchend',sizeMouseup)
|
||||
}
|
||||
const openMask = ()=>{
|
||||
let imgDomStyle = imgDom.value.getBoundingClientRect()
|
||||
data.dressStyle = {
|
||||
top:imgDomStyle.top + 'px',
|
||||
left:imgDomStyle.left + 'px',
|
||||
width:imgDomStyle.width + 'px',
|
||||
height:imgDomStyle.height + 'px',
|
||||
}
|
||||
maskDom.value.style.opacity = '1'
|
||||
maskDom.value.style.display = 'block'
|
||||
document.addEventListener('touchend', touchendUp);
|
||||
}
|
||||
const touchendUp = ()=>{
|
||||
maskDom.value.style.opacity = '0'
|
||||
setTimeout(()=>{
|
||||
maskDom.value.style.display = 'none'
|
||||
}, 300)
|
||||
document.removeEventListener('touchend',touchendUp)
|
||||
}
|
||||
watch(()=>data.selectIndex,(newVal,oldVal)=>{
|
||||
console.log(newVal)
|
||||
let value = {
|
||||
userId:store.userData.id,
|
||||
questionNum:queryList.value[oldVal].id,
|
||||
isLike:queryList.value[oldVal].count,
|
||||
}
|
||||
userSave(value)
|
||||
if(newVal == 30){
|
||||
router.push({
|
||||
path:'/activities/workshop/success',
|
||||
})
|
||||
}
|
||||
})
|
||||
const cliSetNext = (num:number)=>{
|
||||
imgDom.value.style.transition = 'all .3s'
|
||||
if(num > 0){
|
||||
data.tlLeft.progress(1)
|
||||
}else{
|
||||
data.tlRight.progress(1)
|
||||
}
|
||||
setTimeout(()=>{
|
||||
imgDom.value.style.transition = 'all .0s'
|
||||
next(num)
|
||||
},300)
|
||||
}
|
||||
onMounted(()=>{
|
||||
data.tlRight.to(imgDom.value, { rotation: 20, duration: 1 }, 0) // 第 0 秒开始
|
||||
.to(likeDom.value, { scale:1.3, duration: 1 }, '-=1')
|
||||
data.tlLeft.to(imgDom.value, { rotation: -20, duration: 1 }, 0) // 第 0 秒开始
|
||||
.to(noLikeDom.value, { scale:1.3, duration: 1 }, '-=1')
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const { selectIndex, maskShow, dressStyle } = toRefs(data)
|
||||
</script>
|
||||
<template>
|
||||
<div class="workshopEdit">
|
||||
<div class="header">
|
||||
Swipe Style
|
||||
</div>
|
||||
<div class="user">
|
||||
<div class="header">
|
||||
<div class="profile">
|
||||
<img src="@/assets/images/workshop/editProfile.png" alt="">
|
||||
</div>
|
||||
<div class="text">
|
||||
<div class="info">{{ store.userData.title }}</div>
|
||||
<div class="info">{{ store.userData.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="icon">
|
||||
<img src="@/assets/images/workshop/editHanger.png" alt="">
|
||||
</div>
|
||||
<div class="text">{{ selectIndex + 1 }}/{{queryList.length}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit" ref="editDom">
|
||||
<img
|
||||
ref="imgDom"
|
||||
@mousedown.stop="setLikeOrOnLike(getMousePosition($event,false))"
|
||||
@touchstart.passive="setLikeOrOnLike(getMousePosition($event,true))"
|
||||
:src="queryList?.[selectIndex]?.itemImagePath" alt="">
|
||||
<div class="btnBox">
|
||||
<div class="likeOrNoLike">
|
||||
<img ref="noLikeDom" @click="cliSetNext(1)" src="@/assets/images/workshop/editNoLike.png" alt="">
|
||||
<img ref="likeDom" @click="cliSetNext(-1)" class="likeDom" src="@/assets/images/workshop/editLike.png" alt="">
|
||||
</div>
|
||||
<div class="tryOn" @touchstart.passive="openMask"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mask" ref="maskDom">
|
||||
<img :style="dressStyle" :src="queryList?.[selectIndex]?.outfitImagePath" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workshopEdit {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
|
||||
touch-action: none; /* 完全禁用浏览器默认触摸行为 */
|
||||
> .header{
|
||||
margin-top: .9rem;
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
font-size: 2.2rem;
|
||||
text-align: center;
|
||||
font-family: poppinsSemiBold;
|
||||
}
|
||||
> .user{
|
||||
margin-top: 1.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 3rem;
|
||||
> .header{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> .profile{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: .8rem;
|
||||
> img{
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
> .text{
|
||||
> .info{
|
||||
font-weight: 500;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .progress{
|
||||
border: 1px solid #cbcdf1;
|
||||
width: 7.2rem;
|
||||
height: 2.4rem;
|
||||
background: #f6f7ff;
|
||||
border-radius: 1rem;
|
||||
color: #4d52c3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> .icon{
|
||||
margin-right: .1rem;
|
||||
> img{
|
||||
transform: translateY(.2rem);
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
}
|
||||
> .text{
|
||||
font-weight: 700;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .edit{
|
||||
padding: 0 3rem;
|
||||
margin-top: 1.7rem;
|
||||
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
padding-bottom: 5rem;
|
||||
> img{
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
flex: 1;
|
||||
object-fit: contain;
|
||||
// height: 50rem;
|
||||
border-radius: 1.2rem;
|
||||
box-shadow: .7rem .4rem 1rem -0rem rgba(0,0,0,.2);
|
||||
transform-origin: center bottom;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
> .btnBox{
|
||||
margin-top: 4.7rem;
|
||||
padding: 0 1.1rem;
|
||||
width: 100%;
|
||||
> .likeOrNoLike{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> img{
|
||||
width: 6.6rem;
|
||||
height: 6.6rem
|
||||
}
|
||||
}
|
||||
> .tryOn{
|
||||
background:
|
||||
url('@/assets/images/workshop/editOpenGroup.png')
|
||||
center/contain /* 位置/尺寸 */
|
||||
no-repeat /* 不重复 */
|
||||
fixed; /* 背景色 */
|
||||
width: 7.4rem;
|
||||
height: 7.4rem;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .mask{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(255,255,255,.5);
|
||||
transition: all .3s;
|
||||
opacity: 0;
|
||||
display: none;
|
||||
img{
|
||||
position: fixed;
|
||||
border-radius: 1.2rem;
|
||||
box-shadow: .7rem .4rem 1rem -0rem rgba(0,0,0,.2);
|
||||
object-fit: contain;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
178
activities/src/views/Activities/workshop/views/login.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useWorkshopStore } from '@/stores/modules/workshop'
|
||||
import {userCreate} from '@/api/workshop'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const store = useWorkshopStore()
|
||||
const props = defineProps({
|
||||
})
|
||||
const emit = defineEmits([
|
||||
]);
|
||||
let data = reactive({
|
||||
describe:'',
|
||||
title:'',
|
||||
name:'',
|
||||
})
|
||||
const goEditWorkshop = ()=>{
|
||||
if(!data.title){
|
||||
return ElMessage({
|
||||
message: 'Please enter the title.',
|
||||
type: 'primary' as any,
|
||||
})
|
||||
}
|
||||
if(!data.name){
|
||||
return ElMessage({
|
||||
message: 'Please enter your name.',
|
||||
type: 'primary' as any,
|
||||
})
|
||||
}
|
||||
let value = {
|
||||
title:data.title,
|
||||
name:data.name,
|
||||
description:data.describe,
|
||||
}
|
||||
userCreate(value).then((rv:any)=>{
|
||||
store.setLogin({title:data.title,name:data.name,describe:data.describe,id:rv.id})
|
||||
router.push('/activities/workshop/edit')
|
||||
})
|
||||
}
|
||||
const textareaChange = (e:any)=>{
|
||||
if(e.target.value.length <= 1000){
|
||||
data.describe = e.target.value
|
||||
}else{
|
||||
e.target.value = data.describe
|
||||
}
|
||||
}
|
||||
onMounted(()=>{
|
||||
console.log(useWorkshopStore())
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const { describe, title, name } = toRefs(data);
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="workshopLogin">
|
||||
<div class="title">
|
||||
<p>Swipe Style</p>
|
||||
<img src="@/assets/images/workshop/loginTitleImg.png" alt="">
|
||||
</div>
|
||||
<div class="userInput">
|
||||
<label>
|
||||
<span>Job Title</span>
|
||||
<input type="text" v-model="title" placeholder="Your job title">
|
||||
</label>
|
||||
<label>
|
||||
<span>Name</span>
|
||||
<input type="text" v-model="name" placeholder="Your name">
|
||||
</label>
|
||||
<label>
|
||||
<span>Describe your favourite style in one sentence...</span>
|
||||
<div class="textarea">
|
||||
<textarea placeholder="Describe..." @input="textareaChange"></textarea>
|
||||
</div>
|
||||
<div class="textareaNum">{{ describe.length }}/300</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="enter" @click="goEditWorkshop">Enter</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workshopLogin {
|
||||
.title{
|
||||
padding-top: 3.3rem;
|
||||
margin: 0 auto;
|
||||
margin-top: 4rem;
|
||||
color: #4D52C3;
|
||||
position: relative;
|
||||
margin-bottom: 2rem;
|
||||
width: 31.3rem;
|
||||
> p{
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
font-size: 3rem;
|
||||
font-family: poppinsBold;
|
||||
}
|
||||
> img{
|
||||
width: 3.5rem;
|
||||
height: 3.5rem;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
margin-left: 11rem;
|
||||
}
|
||||
}
|
||||
> .userInput{
|
||||
width: 31.3rem;
|
||||
margin: 0 auto;
|
||||
> label{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: .8rem;
|
||||
> span{
|
||||
font-size: 1.2rem;
|
||||
color: #626262;
|
||||
margin-bottom: .8rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
input, textarea{
|
||||
font-size: 1.2rem;
|
||||
&:focus{
|
||||
outline: none; /* 清除默认焦点样式 */
|
||||
}
|
||||
}
|
||||
> input{
|
||||
border-radius: .87rem;
|
||||
padding: 1.7rem;
|
||||
background: #f1f4ff;
|
||||
border: 1.7px #4d52c3 solid;
|
||||
}
|
||||
> .textarea{
|
||||
background: #f1f4ff;
|
||||
border: none;
|
||||
height: 13rem;
|
||||
border-radius: .87rem;
|
||||
padding: 1.7rem;
|
||||
> textarea{
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
> .textareaNum{
|
||||
font-size: 1.2rem;
|
||||
color: #626262;
|
||||
margin-left: auto;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .enter{
|
||||
width: 31.3rem;
|
||||
margin: 0 auto;
|
||||
font-size: 1.74rem;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #4d52c3;
|
||||
border-radius: 1.3rem;
|
||||
height: 5.2rem;
|
||||
line-height: 5.2rem;
|
||||
box-shadow: 0px .8rem 1.7rem 0px #cbd6ff;
|
||||
cursor: pointer;
|
||||
font-family: poppinsSemiBold;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
186
activities/src/views/Activities/workshop/views/success.vue
Normal file
@@ -0,0 +1,186 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs, computed } from "vue";
|
||||
import { useRouter,useRoute } from 'vue-router'
|
||||
import SummaryReport from '../components/summaryReport/index.vue'
|
||||
import { useWorkshopStore } from '@/stores/modules/workshop'
|
||||
import {getCalculateReport} from '@/api/workshop'
|
||||
|
||||
const router = useRouter()
|
||||
const props = defineProps({
|
||||
})
|
||||
const emit = defineEmits({
|
||||
})
|
||||
const store = useWorkshopStore()
|
||||
let data = reactive({
|
||||
loadingSuccess:false,
|
||||
isSummaryReport:false,
|
||||
calculateReport:null as any,
|
||||
count:0,
|
||||
})
|
||||
let queryList = computed(()=>store.queryList) as any
|
||||
|
||||
const goSummaryReport = ()=>{
|
||||
// data.loadingSuccess = true
|
||||
if(!data.loadingSuccess)return
|
||||
data.isSummaryReport = true
|
||||
}
|
||||
let time = null as any;
|
||||
const getCalculate = ()=>{
|
||||
getCalculateReport().then((rv:any)=>{
|
||||
data.calculateReport = rv
|
||||
if(rv.count < 3){
|
||||
data.loadingSuccess = false
|
||||
}else{
|
||||
data.loadingSuccess = true
|
||||
}
|
||||
if(rv.answeringCount > 0){
|
||||
time = setTimeout(()=>{
|
||||
getCalculate()
|
||||
},1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(()=>{
|
||||
getCalculate()
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
clearTimeout(time)
|
||||
})
|
||||
const { loadingSuccess, isSummaryReport, calculateReport } = toRefs(data);
|
||||
</script>
|
||||
<template>
|
||||
<div class="workshopSuccess">
|
||||
<div class="loadingSuccess" v-show="!isSummaryReport">
|
||||
<div class="congratulations">
|
||||
<div class="icon">🎉</div>
|
||||
<div class="text">
|
||||
<div class="title">Congratulations!</div>
|
||||
<div class="info">You have completed all your selections!</div>
|
||||
<div class="describe">Your Result: Like: <span>{{ queryList.filter((item:any)=>item?.count).length }}</span> sets, Dislike: <span>{{ queryList.filter((item:any)=>!item.count).length }}</span> sets.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="botderBottom"></div>
|
||||
<div class="statusBox">
|
||||
<div class="title" @click="goSummaryReport">Check Report</div>
|
||||
<div class="icon">
|
||||
<img src="@/assets/images/workshop/successGoTo.png" alt="">
|
||||
</div>
|
||||
<div class="status" @click="goSummaryReport">
|
||||
<img v-show="!loadingSuccess" src="@/assets/images/workshop/loading.png" alt="">
|
||||
<img v-show="loadingSuccess" src="@/assets/images/workshop/success.png" alt="">
|
||||
</div>
|
||||
<div class="info" v-show="!loadingSuccess">Current progress: {{calculateReport?.count}}/{{ calculateReport?.count + calculateReport?.answeringCount }} people</div>
|
||||
<div class="info" v-show="loadingSuccess">Done!</div>
|
||||
<!-- <div class="goSummaryReport" @click="goSummaryReport" v-show="loadingSuccess">
|
||||
Load More >
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="summaryReport" v-show="isSummaryReport">
|
||||
<SummaryReport v-model:isSummaryReport="isSummaryReport" :calculateReport="calculateReport" ref="summaryReport"></SummaryReport>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.workshopSuccess{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
> .loadingSuccess{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
> .congratulations{
|
||||
margin: 0 auto;
|
||||
// margin-top: 11.7rem;
|
||||
width: 27rem;
|
||||
margin-bottom: 4rem;
|
||||
> img{
|
||||
margin: 0 auto;
|
||||
width: 15.4rem;
|
||||
height: 15.4rem;
|
||||
}
|
||||
> div{
|
||||
text-align: center;
|
||||
}
|
||||
> .icon{
|
||||
font-size: 12.8rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
> .text{
|
||||
> .title{
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
color: #4d52c3;
|
||||
font-family: poppinsBold;
|
||||
}
|
||||
> .info{
|
||||
margin: 1.2rem 1.8rem;
|
||||
font-weight: 500;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
> .describe{
|
||||
font-weight: 500;
|
||||
font-size: 1.2rem;
|
||||
> span{
|
||||
color: #4D52C3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
> .botderBottom{
|
||||
width: 31rem;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
margin: 0 auto;
|
||||
}
|
||||
> .statusBox{
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
> .title{
|
||||
font-size: 1.6rem;
|
||||
font-weight: 600;
|
||||
color: #4d52c3;
|
||||
font-family: poppinsBold;
|
||||
}
|
||||
> .status{
|
||||
margin-top: 1rem;
|
||||
> img{
|
||||
width: 9rem;
|
||||
height: 9rem
|
||||
}
|
||||
}
|
||||
> .info{
|
||||
color: #cdcdcd;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
> .goSummaryReport{
|
||||
margin-top: 2rem;
|
||||
cursor: pointer;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 600;
|
||||
color: #4d52c3;
|
||||
border-radius: 3.4rem;
|
||||
line-height: 3rem;
|
||||
width: 11rem;
|
||||
text-align: center;
|
||||
border: .6px solid #e3e3e3;
|
||||
box-shadow: 0 .4rem 1.5rem -.5rem rgba(0,0,0,.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
> .summaryReport{
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import { getMousePosition } from '@/utils/tools'
|
||||
import { gsap, TweenMax } from "gsap";
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
})
|
||||
const emit = defineEmits([
|
||||
'result',
|
||||
])
|
||||
let data = reactive({
|
||||
tlRight:gsap.timeline({ paused: true }),
|
||||
tlLeft:gsap.timeline({ paused: true }),
|
||||
imgEvent:{} as any,
|
||||
})
|
||||
|
||||
let imgDom = ref()
|
||||
const submit = (index:number)=>{
|
||||
emit('result',index)
|
||||
}
|
||||
onMounted(()=>{
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const {} = toRefs(data);
|
||||
defineExpose({
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="judge">
|
||||
<div class="edit">
|
||||
<div class="title">Whose style do you think this is?</div>
|
||||
<img
|
||||
ref="imgDom"
|
||||
:src="item.itemImagePath" alt="">
|
||||
<div class="btnBox">
|
||||
<div class="select">
|
||||
<div class="item" @click="submit(1)">123</div>
|
||||
<div class="item" @click="submit(2)">123</div>
|
||||
<div class="item" @click="submit(3)">123</div>
|
||||
<div class="item" @click="submit(4)">123</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.judge{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
> .edit{
|
||||
padding: 0 3rem;
|
||||
padding-bottom: 1.6rem;
|
||||
margin-top: 1.7rem;
|
||||
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
padding-bottom: 7rem;
|
||||
> .title{
|
||||
font-weight: 500;
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
margin-bottom: .8rem;
|
||||
}
|
||||
> img{
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 1.2rem;
|
||||
box-shadow: .7rem .4rem 1rem -0rem rgba(0,0,0,.2);
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
> .btnBox{
|
||||
// margin-top: 1.6rem;
|
||||
margin-top: 1.6rem;
|
||||
width: 100%;
|
||||
> .select{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 1.2rem;
|
||||
> .item{
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
padding: 0 1.8rem;
|
||||
line-height: 2.4rem;
|
||||
color: #4D52C3;
|
||||
font-weight: 500;
|
||||
font-size: 1.6rem;
|
||||
background-color: #fff;
|
||||
border: 2px solid #dadada;
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0px .4rem .4rem 0px rgba(0,0,0,0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,160 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import { getMousePosition } from '@/utils/tools'
|
||||
import { gsap, TweenMax } from "gsap";
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
})
|
||||
const emit = defineEmits([
|
||||
'result',
|
||||
])
|
||||
let data = reactive({
|
||||
tlRight:gsap.timeline({ paused: true }),
|
||||
tlLeft:gsap.timeline({ paused: true }),
|
||||
imgEvent:{} as any,
|
||||
})
|
||||
|
||||
let imgDom = ref()
|
||||
let noLikeDom = ref()
|
||||
let likeDom = ref()
|
||||
|
||||
const setLikeOrOnLike = (event:any)=>{
|
||||
imgDom.value.style.transition = ''
|
||||
data.imgEvent = event
|
||||
|
||||
// document.addEventListener('mousemove', sizeMouseMove);
|
||||
document.addEventListener('touchmove', sizeTouchmove);
|
||||
// document.addEventListener('mouseup', sizeMouseup);
|
||||
document.addEventListener('touchend', sizeMouseup);
|
||||
}
|
||||
const sizeTouchmove = (event:any)=>{
|
||||
let e:any = getMousePosition(event,true)
|
||||
let moveSize = data.imgEvent.screenX - e?.screenX
|
||||
let domWidth = e?.target.parentNode.parentNode.offsetWidth
|
||||
if(moveSize > 0){
|
||||
data.tlLeft.progress(Math.abs(moveSize) / domWidth)
|
||||
}else{
|
||||
data.tlRight.progress(Math.abs(moveSize) / domWidth)
|
||||
}
|
||||
}
|
||||
const sizeMouseup = (event:any)=>{
|
||||
let e:any = getMousePosition(event,true)
|
||||
let moveSize = data.imgEvent.screenX - e?.screenX
|
||||
let domWidth = e?.target.parentNode.parentNode.offsetWidth
|
||||
let moveScale = Math.abs(moveSize) / domWidth
|
||||
if(moveScale > .4){
|
||||
emit('result',moveSize)
|
||||
}else{
|
||||
imgDom.value.style.transition = 'all .3s'
|
||||
data.tlLeft.progress(0)
|
||||
data.tlRight.progress(0)
|
||||
}
|
||||
// document.removeEventListener('mousemove',this.sizeMouseMove)
|
||||
document.removeEventListener('touchmove',sizeTouchmove)
|
||||
// document.removeEventListener('mouseup',this.sizeMouseup)
|
||||
document.removeEventListener('touchend',sizeMouseup)
|
||||
}
|
||||
const reset = ()=>{
|
||||
data.tlLeft.progress(0)
|
||||
data.tlRight.progress(0)
|
||||
}
|
||||
const cliSetNext = (num:number)=>{
|
||||
imgDom.value.style.transition = 'all .3s'
|
||||
if(num > 0){
|
||||
data.tlLeft.progress(1)
|
||||
}else{
|
||||
data.tlRight.progress(1)
|
||||
}
|
||||
setTimeout(()=>{
|
||||
imgDom.value.style.transition = 'all .0s'
|
||||
emit('result',num)
|
||||
},300)
|
||||
}
|
||||
onMounted(()=>{
|
||||
data.tlRight.to(imgDom.value, { rotation: 20, duration: 1 }, 0) // 第 0 秒开始
|
||||
.to(likeDom.value, { scale:1.3, duration: 1 }, '-=1')
|
||||
data.tlLeft.to(imgDom.value, { rotation: -20, duration: 1 }, 0) // 第 0 秒开始
|
||||
.to(noLikeDom.value, { scale:1.3, duration: 1 }, '-=1')
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const {} = toRefs(data);
|
||||
defineExpose({
|
||||
reset,
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="judge">
|
||||
<div class="edit">
|
||||
<div class="title">123123123</div>
|
||||
<img
|
||||
ref="imgDom"
|
||||
@mousedown.stop="setLikeOrOnLike(getMousePosition($event,false))"
|
||||
@touchstart.passive="setLikeOrOnLike(getMousePosition($event,true))"
|
||||
:src="item.itemImagePath" alt="">
|
||||
<div class="btnBox">
|
||||
<div class="likeOrNoLike">
|
||||
<img ref="noLikeDom" @click="cliSetNext(1)" src="@/assets/images/workshop/workshop2No.png" alt="">
|
||||
<img ref="likeDom" @click="cliSetNext(-1)" class="likeDom" src="@/assets/images/workshop/workshop2Yes.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.judge{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
> .edit{
|
||||
padding: 0 3rem 3rem 3rem;
|
||||
padding-bottom: 1.6rem;
|
||||
margin-top: 1.7rem;
|
||||
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
padding-bottom: 3.5rem;
|
||||
> .title{
|
||||
font-weight: 500;
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
margin-bottom: .8rem;
|
||||
}
|
||||
> img{
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 1.2rem;
|
||||
box-shadow: .7rem .4rem 1rem -0rem rgba(0,0,0,.2);
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
> .btnBox{
|
||||
// margin-top: 1.6rem;
|
||||
padding: 0 1.8rem;
|
||||
margin-top: 1.6rem;
|
||||
width: 100%;
|
||||
> .likeOrNoLike{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
> img{
|
||||
width: 6.6rem;
|
||||
height: 6.6rem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,113 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
// const props = defineProps({
|
||||
// })
|
||||
const emit = defineEmits([
|
||||
'next'
|
||||
])
|
||||
let data = reactive({
|
||||
})
|
||||
const next = ()=>{
|
||||
emit('next')
|
||||
}
|
||||
onMounted(()=>{
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
defineExpose({})
|
||||
const {} = toRefs(data);
|
||||
</script>
|
||||
<template>
|
||||
<div class="result">
|
||||
<div class="icon">😄</div>
|
||||
<div class="title">Correct! You got it!</div>
|
||||
<div class="keyPoint">
|
||||
<div class="aiBot">
|
||||
<img src="@/assets/images/workshop/workshop2Bot.png" alt="">
|
||||
<div>AI Bot:</div>
|
||||
</div>
|
||||
<div class="text">1312312312312312323123123123</div>
|
||||
</div>
|
||||
<div class="next" @click="next">
|
||||
<div>Next</div>
|
||||
<img src="@/assets/images/workshop/workshopRight.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.result{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
> div{
|
||||
flex-shrink: 0;
|
||||
}
|
||||
> .icon{
|
||||
font-size: 14.3rem;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
margin-bottom: .6rem;
|
||||
}
|
||||
> .title{
|
||||
font-size: 2.8rem;
|
||||
font-family: poppinsBold;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
color: #4D52C3;
|
||||
}
|
||||
> .keyPoint{
|
||||
font-size: 1.6rem;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
width: calc(100% - 30px * 2);
|
||||
margin: 0 auto;
|
||||
height: 21.5rem;
|
||||
padding: 1.8rem 1.6rem 0;
|
||||
border: 2px solid #b7b9e9;
|
||||
border-radius: 2rem;
|
||||
box-shadow: 0px .7rem .4rem 0px rgba(0, 0, 0, 0.15);
|
||||
margin-bottom: 10rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
> .aiBot{
|
||||
margin-bottom: .6rem;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> img{
|
||||
margin-right: .4rem;
|
||||
}
|
||||
}
|
||||
> .text{
|
||||
font-size: 1.2rem;
|
||||
font-weight: 400;
|
||||
font-family: poppinsRegular;
|
||||
}
|
||||
}
|
||||
> .next{
|
||||
margin: 0 3rem 0 auto;
|
||||
border: 1px solid #4d52c3;
|
||||
height: 3.6rem;
|
||||
display: flex;
|
||||
font-size: 1.6rem;
|
||||
border-radius: 1rem;
|
||||
padding: 0 1.3rem 0 1.6rem;
|
||||
color: #4D52C3;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
> img{
|
||||
margin-left: .6rem;
|
||||
width: .5rem;
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,274 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import {getCalculateReport} from '@/api/workshop'
|
||||
|
||||
const props = defineProps({
|
||||
isSummaryReport:{
|
||||
type:Boolean,
|
||||
default:false,
|
||||
},
|
||||
calculateReport:{
|
||||
type:Object,
|
||||
default:()=>{},
|
||||
},
|
||||
})
|
||||
const emit = defineEmits([
|
||||
'update:isSummaryReport'
|
||||
])
|
||||
let data = reactive({
|
||||
})
|
||||
const goBack = ()=>{
|
||||
emit('update:isSummaryReport',false)
|
||||
}
|
||||
onMounted(()=>{
|
||||
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const {} = toRefs(data);
|
||||
</script>
|
||||
<template>
|
||||
<div class="summaryReport">
|
||||
<img class="bg" src="@/assets/images/workshop/workshop2SuccessBg.png" alt="">
|
||||
<div class="header">
|
||||
Swipe Style
|
||||
<img @click="goBack" src="@/assets/images/workshop/workshop2Back.png" alt="">
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="topThree">
|
||||
<div class="item item1">
|
||||
<div class="head">
|
||||
<img class="one" src="@/assets/images/workshop/workshop2TopicOne.png" alt="">
|
||||
<img class="profile" src="@/assets/images/workshop/editProfile.png" alt="">
|
||||
</div>
|
||||
<div class="name">Name</div>
|
||||
<div class="points">
|
||||
99
|
||||
points
|
||||
</div>
|
||||
</div>
|
||||
<div class="item item2">
|
||||
<div class="head">
|
||||
<img class="profile" src="@/assets/images/workshop/editProfile.png" alt="">
|
||||
</div>
|
||||
<div class="name">Name</div>
|
||||
<div class="points">
|
||||
99
|
||||
points
|
||||
</div>
|
||||
</div>
|
||||
<div class="item item3">
|
||||
<div class="head">
|
||||
<img class="profile" src="@/assets/images/workshop/editProfile.png" alt="">
|
||||
</div>
|
||||
<div class="name">Name</div>
|
||||
<div class="points">
|
||||
99
|
||||
points
|
||||
</div>
|
||||
</div>
|
||||
<div class="topThreeBg">
|
||||
<img src="@/assets/images/workshop/workshopTopThree.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabulate">
|
||||
<div class="bgImg">
|
||||
<img src="@/assets/images/workshop/workshop2TopicList.png" alt="">
|
||||
<div class="placeholder"></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="roll">
|
||||
<div class="item">
|
||||
<div class="serialNum">1</div>
|
||||
<div class="profile">
|
||||
<img src="@/assets/images/workshop/editProfile.png" alt="">
|
||||
</div>
|
||||
<div class="user">
|
||||
<div class="name">Name</div>
|
||||
<div class="points">90 points</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="less" scoped>
|
||||
.summaryReport{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
> .bg{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background-color: #4d52c3;
|
||||
}
|
||||
> .header{
|
||||
padding: .9rem 0;
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
font-size: 2.4rem;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-family: poppinsBold;
|
||||
margin-bottom: 1.2rem;
|
||||
> img{
|
||||
position: absolute;
|
||||
left: 3rem;
|
||||
width: 1.7rem;
|
||||
height: 1.7rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
> .body{
|
||||
flex: 1;
|
||||
> .topThree{
|
||||
position: relative;
|
||||
width: 31.8rem;
|
||||
margin: 0 auto;
|
||||
> .topThreeBg{
|
||||
width: 31.8rem;
|
||||
padding-top: 17rem;
|
||||
height: auto;
|
||||
> img{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
> .item{
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
> .head{
|
||||
position: relative;
|
||||
> .one{
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: 0;
|
||||
}
|
||||
> .profile{
|
||||
margin-top: 3rem;
|
||||
width: 5.6rem;
|
||||
height: 5.6rem;
|
||||
}
|
||||
}
|
||||
> .name{
|
||||
margin-bottom: .4rem;
|
||||
color: #fff;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
> .points{
|
||||
border-radius: 1.2rem;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
padding: 0 1.2rem;
|
||||
line-height: 3.4rem;
|
||||
background-color: #cbcdf1;
|
||||
color: #4D52C3;
|
||||
}
|
||||
}
|
||||
> .item1{
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: 0;
|
||||
}
|
||||
> .item2{
|
||||
left: 1.9rem;
|
||||
top: calc(6.2rem - 3rem);
|
||||
}
|
||||
> .item3{
|
||||
top: calc(9.4rem - 3rem);
|
||||
left: auto;
|
||||
right: 1.9rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .tabulate{
|
||||
margin: 0 .8rem;
|
||||
margin-top: -12rem;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
> .bgImg{
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
> img{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
> .placeholder{
|
||||
margin-top: -1rem;
|
||||
width: 100%;
|
||||
height: 13rem;
|
||||
background-color: #efeefc;
|
||||
}
|
||||
}
|
||||
> .content{
|
||||
padding: 3.2rem 1.6rem 0 1.6rem;
|
||||
height: 100%;
|
||||
// height: calc(100% + 12rem);
|
||||
> .roll{
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
> .item{
|
||||
margin-bottom: 1.6rem;
|
||||
background-color: #ffffff;
|
||||
border-radius: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 9.2rem;
|
||||
> .serialNum{
|
||||
font-size: 1.6rem;
|
||||
font-weight: 350;
|
||||
color: #858494;
|
||||
margin-left: 2.3rem;
|
||||
}
|
||||
> .profile{
|
||||
margin-left: 2.3rem;
|
||||
width: 5.6rem;
|
||||
height: 5.6rem;
|
||||
> img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
> .user{
|
||||
margin-left: 1.6rem;
|
||||
> .name{
|
||||
font-size: 1.6rem;
|
||||
font-weight: 500;
|
||||
color: #0c092a;
|
||||
margin-bottom: .4rem;
|
||||
}
|
||||
> .points{
|
||||
font-size: 1.4rem;
|
||||
font-weight: 400;
|
||||
color: #858494;
|
||||
}
|
||||
}
|
||||
&:last-child{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
67
activities/src/views/Activities/workshop2/index.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
|
||||
import {getQueryPage} from '@/api/workshop'
|
||||
import { useWorkshopStore } from '@/stores/modules/workshop'
|
||||
|
||||
const store = useWorkshopStore()
|
||||
let dataDom = reactive({
|
||||
loadingDom:null as any,
|
||||
})
|
||||
let data = reactive({
|
||||
|
||||
})
|
||||
onMounted(()=>{
|
||||
// getQueryPage({page:1,size:200}).then((rv:any)=>{
|
||||
// store.setQueryList(rv.content)
|
||||
// })
|
||||
getQueryPage({page:1,size:200}).then((rv:any)=>{
|
||||
store.setQueryList(rv.content)
|
||||
})
|
||||
setTimeout(()=>{
|
||||
dataDom.loadingDom.style.opacity = '0';
|
||||
setTimeout(()=>{
|
||||
dataDom.loadingDom.style.display = 'none';
|
||||
},1000)
|
||||
},3000)
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
})
|
||||
const { loadingDom } = toRefs(dataDom);
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="workshop">
|
||||
<div class="loading" ref="loadingDom">
|
||||
<img src="@/assets/images/workshop/loadingPage.png" alt="">
|
||||
</div>
|
||||
<RouterView />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.workshop {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
> .loading{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
transition: all 1s;
|
||||
background: #fff;
|
||||
img{
|
||||
width: 25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||