完善功能、首页、报名、个人中心
This commit is contained in:
parent
c2c83a06ea
commit
9b42afdcfa
@ -1,2 +1,2 @@
|
||||
VITE_APP_PREVIEW=false
|
||||
VITE_APP_API_BASE_URL=https://api.example.com
|
||||
VITE_APP_API_BASE_URL=/api
|
||||
|
@ -1 +0,0 @@
|
||||
node scripts/verifyCommit.js
|
@ -1 +0,0 @@
|
||||
pnpm lint
|
21
package.json
21
package.json
@ -7,15 +7,13 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "cross-env MOCK_SERVER_PORT=8086 vite",
|
||||
"build": "vue-tsc --noEmit && vite build",
|
||||
"build": "vite build",
|
||||
"build:dev": "vue-tsc --noEmit && vite build --mode=development",
|
||||
"preview": "npm run build && vite preview",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"test": "vitest",
|
||||
"release": "bumpp --commit --push --tag",
|
||||
"prepare": "husky",
|
||||
"cz": "git-cz"
|
||||
"release": "bumpp --commit --push --tag"
|
||||
},
|
||||
"dependencies": {
|
||||
"@unhead/vue": "^1.8.10",
|
||||
@ -33,6 +31,7 @@
|
||||
"vant": "^4.8.4",
|
||||
"vconsole": "^3.15.1",
|
||||
"vue": "^3.4.15",
|
||||
"vue-cookies": "^1.8.3",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -48,12 +47,9 @@
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"bumpp": "^9.3.0",
|
||||
"commitizen": "^4.3.0",
|
||||
"consola": "^3.2.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"cz-emoji-chinese": "^0.3.1",
|
||||
"eslint": "^8.56.0",
|
||||
"husky": "^9.0.10",
|
||||
"less": "^4.2.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"postcss-mobile-forever": "^4.1.1",
|
||||
@ -82,16 +78,5 @@
|
||||
"rollup": "^4.x"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-emoji-chinese"
|
||||
},
|
||||
"cz-emoji-chinese": {
|
||||
"skipQuestions": [
|
||||
"body",
|
||||
"scope"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
915
pnpm-lock.yaml
915
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
23
src/api/user.ts
Normal file
23
src/api/user.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 根据openid获取参会用户信息
|
||||
*/
|
||||
export function getApplyInfoByOpenId(data: { openId: string, miceLink: string }) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/backstageApply/getByOpenId',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据手机号获取参会用户信息
|
||||
*/
|
||||
export function getApplyInfoByPhone(data: { phone: string, miceLink: string }) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/backstageApply/getByPhone',
|
||||
data,
|
||||
})
|
||||
}
|
@ -10,3 +10,40 @@ export function getWeixinSignature(url: string) {
|
||||
data: { url },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取用户信息
|
||||
*/
|
||||
export function userSign(code: string) {
|
||||
const formData = new FormData()
|
||||
formData.append('code', code)
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/wx/getUserInfoBycode',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* openid获取用户信息
|
||||
*/
|
||||
export function getUserInfoByOpenId(openid: any) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: `/wxUser/getInfoByOpenId/${openid}`,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* openid 是否已经参会
|
||||
*/
|
||||
export function openidIsApply(data: { openId: string, miceLink: string }) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/backstageApply/openIdIsApply',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
3
src/auto-imports.d.ts
vendored
3
src/auto-imports.d.ts
vendored
@ -43,6 +43,7 @@ declare global {
|
||||
const expect: typeof import('vitest')['expect']
|
||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||
const getActiveHead: typeof import('@unhead/vue')['getActiveHead']
|
||||
const getCookie: typeof import('./composables/cookie')['getCookie']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const getUrlMiceLink: typeof import('./composables/mice')['getUrlMiceLink']
|
||||
@ -97,9 +98,11 @@ declare global {
|
||||
const refDefault: typeof import('@vueuse/core')['refDefault']
|
||||
const refThrottled: typeof import('@vueuse/core')['refThrottled']
|
||||
const refWithControl: typeof import('@vueuse/core')['refWithControl']
|
||||
const removeCookie: typeof import('./composables/cookie')['removeCookie']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
||||
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
||||
const setCookie: typeof import('./composables/cookie')['setCookie']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
|
8
src/components.d.ts
vendored
8
src/components.d.ts
vendored
@ -7,22 +7,14 @@ export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
Chart: typeof import('./components/chart/index.vue')['default']
|
||||
Container: typeof import('./components/container/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
VanButton: typeof import('vant/es')['Button']
|
||||
VanCell: typeof import('vant/es')['Cell']
|
||||
VanCellGroup: typeof import('vant/es')['CellGroup']
|
||||
VanCheckbox: typeof import('vant/es')['Checkbox']
|
||||
VanConfigProvider: typeof import('vant/es')['ConfigProvider']
|
||||
VanEmpty: typeof import('vant/es')['Empty']
|
||||
VanField: typeof import('vant/es')['Field']
|
||||
VanForm: typeof import('vant/es')['Form']
|
||||
VanIcon: typeof import('vant/es')['Icon']
|
||||
VanNavBar: typeof import('vant/es')['NavBar']
|
||||
VanSpace: typeof import('vant/es')['Space']
|
||||
VanSwitch: typeof import('vant/es')['Switch']
|
||||
VanTag: typeof import('vant/es')['Tag']
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
<script lang="ts" setup>
|
||||
import useMiceStore from '@/stores/modules/mice'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
|
||||
const miceInfoStore = useMiceStore()
|
||||
const { getOpenId } = useUserStore()
|
||||
|
||||
onMounted(() => {
|
||||
const miceeLink = getUrlMiceLink()
|
||||
miceInfoStore.initMiceInfo(miceeLink)
|
||||
})
|
||||
getOpenId()
|
||||
const miceeLink = getUrlMiceLink()
|
||||
miceInfoStore.initMiceInfo(miceeLink)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createHead } from '@unhead/vue'
|
||||
import VueCookies from 'vue-cookies'
|
||||
import App from '@/App.vue'
|
||||
import router from '@/router'
|
||||
import pinia from '@/stores'
|
||||
|
||||
import 'virtual:uno.css'
|
||||
import '@/styles/app.less'
|
||||
|
||||
@ -23,6 +25,9 @@ import 'vant/es/image-preview/style'
|
||||
const app = createApp(App)
|
||||
const head = createHead()
|
||||
|
||||
// app.config.globalProperties.$cookies = VueCookies
|
||||
app.provide('$cookies', VueCookies)
|
||||
|
||||
app.use(head)
|
||||
app.use(router)
|
||||
app.use(pinia)
|
||||
|
@ -7,7 +7,7 @@ import 'nprogress/nprogress.css'
|
||||
NProgress.configure({ showSpinner: true, parent: '#app' })
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.VITE_APP_PUBLIC_PATH),
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
|
@ -26,6 +26,15 @@ const routes: Array<RouteRecordRaw> = [
|
||||
title: '报名',
|
||||
},
|
||||
},
|
||||
// 个人中心
|
||||
{
|
||||
path: 'user/:miceLink',
|
||||
name: 'User',
|
||||
component: () => import('@/views/user/index.vue'),
|
||||
meta: {
|
||||
title: '个人中心',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
@ -7,7 +7,14 @@ import { getMiceInfo } from '@/api/mice'
|
||||
const useMiceStore = defineStore('mice', () => {
|
||||
const miceInfo = ref<any>({})
|
||||
|
||||
// 初始化会议信息
|
||||
function initMiceInfo(miceLink: string) {
|
||||
if (!miceLink)
|
||||
return
|
||||
|
||||
if (miceInfo.value.linkName)
|
||||
return
|
||||
|
||||
getMiceInfo({ miceLink }).then((res) => {
|
||||
miceInfo.value = res
|
||||
})
|
||||
|
83
src/stores/modules/user.ts
Normal file
83
src/stores/modules/user.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { VueCookies } from 'vue-cookies'
|
||||
import { getUserInfoByOpenId, userSign } from '@/api/weixin'
|
||||
import { getApplyInfoByOpenId } from '@/api/user'
|
||||
|
||||
/**
|
||||
* 会议信息
|
||||
*/
|
||||
const useUserStore = defineStore('user', () => {
|
||||
const wxInfo = ref<any>({})
|
||||
const router = useRouter()
|
||||
const openId = ref('')
|
||||
const userInfo = ref<any>({})
|
||||
const applyInfo = ref<any>({})
|
||||
|
||||
// 获取openid
|
||||
async function getOpenId() {
|
||||
const APPID = 'wxa4d8f4b7c43cdf40'
|
||||
const cookies = inject<VueCookies>('$cookies')
|
||||
|
||||
let user = {} as any
|
||||
user = cookies.get('user')
|
||||
// user = {
|
||||
// openid: 'o_CUl6J2TlFYLbnTp8PqWle-DUSQ',
|
||||
// }
|
||||
|
||||
// 如果没有openId,跳转到授权页面
|
||||
if (!user || !user.openid) {
|
||||
if (!router.currentRoute.value.query.code) {
|
||||
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APPID}&redirect_uri=${window.location.href.split('#')[0]}&response_type=code&scope=snsapi_userinfo#wechat_redirect`
|
||||
}
|
||||
else {
|
||||
const code = router.currentRoute.value.query.code as string
|
||||
// 获取微信用户信息
|
||||
userSign(code).then((res: any) => {
|
||||
cookies.set('user', JSON.stringify(res))
|
||||
wxInfo.value = res
|
||||
openId.value = res.openid
|
||||
getUserInfo()
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
openId.value = user.openid
|
||||
wxInfo.value = user
|
||||
getUserInfo()
|
||||
}
|
||||
}
|
||||
|
||||
// 获取参会用户信息
|
||||
function getUserInfo() {
|
||||
getUserInfoByOpenId(openId.value).then((res: any) => {
|
||||
userInfo.value = res
|
||||
})
|
||||
}
|
||||
|
||||
// 根据手机号获取参会信息
|
||||
// function getApplyInfoByPhone() {
|
||||
|
||||
// }
|
||||
|
||||
// 根据openid获取参会信息
|
||||
function getApplyUserInfo(miceLink) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getApplyInfoByOpenId({ openId: openId.value, miceLink }).then((res: any) => {
|
||||
applyInfo.value = res.backstageApply
|
||||
resolve(res.backstageApply)
|
||||
}).catch((err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
wxInfo,
|
||||
openId,
|
||||
userInfo,
|
||||
getOpenId,
|
||||
getApplyUserInfo,
|
||||
}
|
||||
})
|
||||
|
||||
export default useUserStore
|
145
src/typed-router.d.ts
vendored
145
src/typed-router.d.ts
vendored
@ -1,145 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
|
||||
// It's recommended to commit this file.
|
||||
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
|
||||
|
||||
/// <reference types="unplugin-vue-router/client" />
|
||||
|
||||
import type {
|
||||
// type safe route locations
|
||||
RouteLocationTypedList,
|
||||
RouteLocationResolvedTypedList,
|
||||
RouteLocationNormalizedTypedList,
|
||||
RouteLocationNormalizedLoadedTypedList,
|
||||
RouteLocationAsString,
|
||||
RouteLocationAsRelativeTypedList,
|
||||
RouteLocationAsPathTypedList,
|
||||
|
||||
// helper types
|
||||
// route definitions
|
||||
RouteRecordInfo,
|
||||
ParamValue,
|
||||
ParamValueOneOrMore,
|
||||
ParamValueZeroOrMore,
|
||||
ParamValueZeroOrOne,
|
||||
|
||||
// vue-router extensions
|
||||
_RouterTyped,
|
||||
RouterLinkTyped,
|
||||
RouterLinkPropsTyped,
|
||||
NavigationGuard,
|
||||
UseLinkFnTyped,
|
||||
|
||||
// data fetching
|
||||
_DataLoader,
|
||||
_DefineLoaderOptions,
|
||||
} from 'unplugin-vue-router/types'
|
||||
|
||||
declare module 'vue-router/auto/routes' {
|
||||
export interface RouteNamedMap {
|
||||
export interface RouteNamedMap {
|
||||
'//': RouteRecordInfo<'//', '/', Record<never, never>, Record<never, never>>,
|
||||
} '/signUp/': RouteRecordInfo<'/signUp/', '/signUp', Record<never, never>, Record<never, never>>,
|
||||
'/signUp/components/FormItem': RouteRecordInfo<'/signUp/components/FormItem', '/signUp/components/FormItem', Record<never, never>, Record<never, never>>,
|
||||
'/signUp/components/SignForm': RouteRecordInfo<'/signUp/components/SignForm', '/signUp/components/SignForm', Record<never, never>, Record<never, never>>,
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'vue-router/auto' {
|
||||
import type { RouteNamedMap } from 'vue-router/auto/routes'
|
||||
|
||||
export type RouterTyped = _RouterTyped<RouteNamedMap>
|
||||
|
||||
/**
|
||||
* Type safe version of `RouteLocationNormalized` (the type of `to` and `from` in navigation guards).
|
||||
* Allows passing the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteLocationNormalized<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationNormalizedTypedList<RouteNamedMap>[Name]
|
||||
|
||||
/**
|
||||
* Type safe version of `RouteLocationNormalizedLoaded` (the return type of `useRoute()`).
|
||||
* Allows passing the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteLocationNormalizedLoaded<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[Name]
|
||||
|
||||
/**
|
||||
* Type safe version of `RouteLocationResolved` (the returned route of `router.resolve()`).
|
||||
* Allows passing the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteLocationResolved<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationResolvedTypedList<RouteNamedMap>[Name]
|
||||
|
||||
/**
|
||||
* Type safe version of `RouteLocation` . Allows passing the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteLocation<Name extends keyof RouteNamedMap = keyof RouteNamedMap> = RouteLocationTypedList<RouteNamedMap>[Name]
|
||||
|
||||
/**
|
||||
* Type safe version of `RouteLocationRaw` . Allows passing the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteLocationRaw<Name extends keyof RouteNamedMap = keyof RouteNamedMap> =
|
||||
| RouteLocationAsString<RouteNamedMap>
|
||||
| RouteLocationAsRelativeTypedList<RouteNamedMap>[Name]
|
||||
| RouteLocationAsPathTypedList<RouteNamedMap>[Name]
|
||||
|
||||
/**
|
||||
* Generate a type safe params for a route location. Requires the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteParams<Name extends keyof RouteNamedMap> = RouteNamedMap[Name]['params']
|
||||
/**
|
||||
* Generate a type safe raw params for a route location. Requires the name of the route to be passed as a generic.
|
||||
*/
|
||||
export type RouteParamsRaw<Name extends keyof RouteNamedMap> = RouteNamedMap[Name]['paramsRaw']
|
||||
|
||||
export function useRouter(): RouterTyped
|
||||
export function useRoute<Name extends keyof RouteNamedMap = keyof RouteNamedMap>(name?: Name): RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[Name]
|
||||
|
||||
export const useLink: UseLinkFnTyped<RouteNamedMap>
|
||||
|
||||
export function onBeforeRouteLeave(guard: NavigationGuard<RouteNamedMap>): void
|
||||
export function onBeforeRouteUpdate(guard: NavigationGuard<RouteNamedMap>): void
|
||||
|
||||
export const RouterLink: RouterLinkTyped<RouteNamedMap>
|
||||
export const RouterLinkProps: RouterLinkPropsTyped<RouteNamedMap>
|
||||
|
||||
// Experimental Data Fetching
|
||||
|
||||
export function defineLoader<
|
||||
P extends Promise<any>,
|
||||
Name extends keyof RouteNamedMap = keyof RouteNamedMap,
|
||||
isLazy extends boolean = false,
|
||||
>(
|
||||
name: Name,
|
||||
loader: (route: RouteLocationNormalizedLoaded<Name>) => P,
|
||||
options?: _DefineLoaderOptions<isLazy>,
|
||||
): _DataLoader<Awaited<P>, isLazy>
|
||||
export function defineLoader<
|
||||
P extends Promise<any>,
|
||||
isLazy extends boolean = false,
|
||||
>(
|
||||
loader: (route: RouteLocationNormalizedLoaded) => P,
|
||||
options?: _DefineLoaderOptions<isLazy>,
|
||||
): _DataLoader<Awaited<P>, isLazy>
|
||||
|
||||
export {
|
||||
_definePage as definePage,
|
||||
_HasDataLoaderMeta as HasDataLoaderMeta,
|
||||
_setupDataFetchingGuard as setupDataFetchingGuard,
|
||||
_stopDataFetchingScope as stopDataFetchingScope,
|
||||
} from 'unplugin-vue-router/runtime'
|
||||
}
|
||||
|
||||
declare module 'vue-router' {
|
||||
import type { RouteNamedMap } from 'vue-router/auto/routes'
|
||||
|
||||
export interface TypesConfig {
|
||||
beforeRouteUpdate: NavigationGuard<RouteNamedMap>
|
||||
beforeRouteLeave: NavigationGuard<RouteNamedMap>
|
||||
|
||||
$route: RouteLocationNormalizedLoadedTypedList<RouteNamedMap>[keyof RouteNamedMap]
|
||||
$router: _RouterTyped<RouteNamedMap>
|
||||
|
||||
RouterLink: RouterLinkTyped<RouteNamedMap>
|
||||
}
|
||||
}
|
@ -12,9 +12,9 @@ const miceInfoStore = useMiceStore()
|
||||
<template>
|
||||
<div>
|
||||
<img
|
||||
class="w-full"
|
||||
class="h-200 w-full"
|
||||
fit="contain"
|
||||
src="https://sn202108-1305501521.cos.ap-shanghai.myqcloud.com/202401162355044675902.jpg"
|
||||
:src="miceInfoStore.miceInfo.posters"
|
||||
>
|
||||
<!-- 会议标题 -->
|
||||
<div class="van-hairline--bottom my-0 px-10 py-5 font-bold">
|
||||
@ -28,29 +28,34 @@ const miceInfoStore = useMiceStore()
|
||||
<van-tag plain type="primary">
|
||||
报名
|
||||
</van-tag>
|
||||
<span>2024-01-16 23:55:04</span>
|
||||
<span v-if="miceInfoStore.miceInfo.regStartTime">{{ miceInfoStore.miceInfo.regStartTime.substr(0, 16) }} - {{ miceInfoStore.miceInfo.registerDeadline.substr(0, 16) }}</span>
|
||||
</div>
|
||||
<div class="mice-info-item">
|
||||
<van-icon name="clock-o" />
|
||||
<van-tag plain type="primary">
|
||||
活动
|
||||
</van-tag>
|
||||
<span>2024-01-16 23:55:04</span>
|
||||
<span v-if="miceInfoStore.miceInfo.startTime">{{ miceInfoStore.miceInfo.startTime.substr(0, 16) }} - {{ miceInfoStore.miceInfo.endTime.substr(0, 16) }}</span>
|
||||
</div>
|
||||
<div class="mice-info-item">
|
||||
<van-icon name="location-o" />
|
||||
<span>上海xxx</span>
|
||||
<span v-if="miceInfoStore.miceInfo.address">
|
||||
{{ JSON.parse(miceInfoStore.miceInfo.address).place }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mice-info-item">
|
||||
<div v-if="miceInfoStore.miceInfo.phone" class="mice-info-item">
|
||||
<van-icon name="phone-o" />
|
||||
<span>12345678901</span>
|
||||
<div>{{ JSON.parse(miceInfoStore.miceInfo.phone)[0].phone }}</div>
|
||||
</div>
|
||||
<!-- <div class="phone-list" style="text-indent: 22px;">
|
||||
12345678901
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- 报名人数 -->
|
||||
<div class="sign-num van-hairline--bottom p-10 text-2xl">
|
||||
<div class="van-hairline--bottom sign-num p-10 text-2xl">
|
||||
<span>已报名</span>
|
||||
<span>10人</span>
|
||||
<span>{{ miceInfoStore.miceInfo.applyCount || 0 }}人</span>
|
||||
</div>
|
||||
|
||||
<!-- 空白 -->
|
||||
@ -61,16 +66,16 @@ const miceInfoStore = useMiceStore()
|
||||
<div class="van-hairline--bottom p-10 font-semibold">
|
||||
会议简介
|
||||
</div>
|
||||
<div class="p-10" v-html="miceInfoStore.miceInfo.description" />
|
||||
<div class="inner-html p-10" v-html="miceInfoStore.miceInfo.description" />
|
||||
</div>
|
||||
|
||||
<!-- 底部操作栏 -->
|
||||
<div class="bottom-actions">
|
||||
<div class="bottom-item">
|
||||
<div class="bottom-item bg-white" @click="$router.push(`/user/${miceInfoStore.miceInfo.linkName}`)">
|
||||
<van-icon name="user-o" />
|
||||
<span>个人中心</span>
|
||||
</div>
|
||||
<div class="sign">
|
||||
<div class="sign" @click="$router.push(`/signUp/${miceInfoStore.miceInfo.linkName}`)">
|
||||
立即报名
|
||||
</div>
|
||||
</div>
|
||||
@ -126,4 +131,12 @@ const miceInfoStore = useMiceStore()
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.inner-html {
|
||||
padding-bottom: 60px;
|
||||
:deep(img) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
@ -3,18 +3,19 @@ import type { PropType } from 'vue'
|
||||
import { showToast } from 'vant'
|
||||
import FormItem from './FormItem.vue'
|
||||
import { getSignUpFormConfig, signUp, smsSend } from '@/api/mice'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
|
||||
const form = defineModel({
|
||||
type: Object as PropType<any>,
|
||||
required: true,
|
||||
})
|
||||
const userStore = useUserStore()
|
||||
const miceLink = getUrlMiceLink()
|
||||
|
||||
// 表单配置项
|
||||
const formConfigs = ref<any[]>([])
|
||||
|
||||
onMounted(() => {
|
||||
const miceLink = getUrlMiceLink()
|
||||
form.value.miceLink = miceLink
|
||||
getSignUpFormConfig({ miceLink }).then((res: any) => {
|
||||
formConfigs.value = res
|
||||
})
|
||||
@ -22,8 +23,10 @@ onMounted(() => {
|
||||
|
||||
// 提交注册报名
|
||||
function onSubmit() {
|
||||
signUp(form.value).then((res: any) => {
|
||||
console.log(res)
|
||||
form.value.miceLink = miceLink
|
||||
form.value.openId = userStore.openId
|
||||
signUp(form.value).then(() => {
|
||||
// console.log(res)
|
||||
})
|
||||
}
|
||||
|
||||
@ -32,8 +35,8 @@ async function sendSmsHandler() {
|
||||
if (!form.value.phone || !/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(form.value.phone)) {
|
||||
return showToast('请输入正确的手机号')
|
||||
}
|
||||
const res = await smsSend(form.value.phone)
|
||||
console.log(res)
|
||||
await smsSend(form.value.phone)
|
||||
// console.log(res)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,8 +1,35 @@
|
||||
<script setup lang="ts" name="SignUp">
|
||||
import { openidIsApply } from '@/api/weixin'
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
import SignForm from '@/views/signUp/components/SignForm.vue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const formConfigs = ref<any[]>([])
|
||||
const form = ref({})
|
||||
const userIsApply = ref(false)
|
||||
|
||||
// 验证用户是否已经报名
|
||||
function checkIsApply() {
|
||||
const miceLink = getUrlMiceLink()
|
||||
openidIsApply({ openId: userStore.wxInfo.openid, miceLink }).then((res: any) => {
|
||||
userIsApply.value = res
|
||||
|
||||
if (res) {
|
||||
router.replace(`/user/${miceLink}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (!userStore.openId) {
|
||||
userStore.getOpenId()
|
||||
}
|
||||
|
||||
checkIsApply()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
20
src/views/user/index.vue
Normal file
20
src/views/user/index.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const userApplyInfo = ref<any>({})
|
||||
|
||||
onMounted(() => {
|
||||
userStore.getApplyUserInfo(getUrlMiceLink()).then((res) => {
|
||||
userApplyInfo.value = res
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
个人中心
|
||||
{{ userApplyInfo }}
|
||||
</div>
|
||||
</template>
|
@ -1,4 +1,4 @@
|
||||
import { defineConfig, presetAttributify, presetMini, presetUno } from 'unocss'
|
||||
import { defineConfig, presetAttributify, presetUno } from 'unocss'
|
||||
import presetRemToPx from '@unocss/preset-rem-to-px'
|
||||
|
||||
// 刚使用unocss的朋友,可以借助这个工具: https://to-unocss.netlify.app
|
||||
|
@ -20,6 +20,7 @@ export default ({ mode }: ConfigEnv): UserConfig => {
|
||||
proxy: {
|
||||
'/api': {
|
||||
// 接口请求地址
|
||||
// target: 'http://localhost:8888/api',
|
||||
target: 'https://jihui.huiyipro.com/api',
|
||||
changeOrigin: true,
|
||||
rewrite: path => path.replace(/^\/api/, ''),
|
||||
|
Loading…
Reference in New Issue
Block a user