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>
|
||||||
|
|
||||||