Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
project-online-fi
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
project-online-fi
Commits
da6e909b
提交
da6e909b
authored
11月 22, 2022
作者:
matian
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
updates
上级
5d038661
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
689 行增加
和
4 行删除
+689
-4
ApplyForm.vue
src/components/layout/ApplyForm.vue
+205
-0
Footer.vue
src/components/layout/Footer.vue
+0
-0
Index.vue
src/components/layout/Index.vue
+16
-1
RightAside.vue
src/components/layout/RightAside.vue
+335
-0
RightAsideH5.vue
src/components/layout/RightAsideH5.vue
+92
-0
Index.vue
src/modules/shop/views/Index.vue
+41
-3
没有找到文件。
src/components/layout/ApplyForm.vue
0 → 100644
浏览文件 @
da6e909b
<
template
>
<div
class=
"app-apply-form"
>
<h2
class=
"title"
>
报名咨询
</h2>
<div
class=
"form"
>
<div
class=
"form-item"
>
<input
type=
"text"
class=
"form-input"
placeholder=
"请输入您的名字"
v-model=
"ruleForm.name"
/>
</div>
<div
class=
"form-item"
>
<input
type=
"number"
class=
"form-input"
placeholder=
"请输入您的电话"
maxlength=
"11"
v-model=
"ruleForm.phone"
/>
</div>
<div
class=
"form-item"
>
<input
type=
"text"
class=
"form-input"
placeholder=
"请输入验证码"
maxlength=
"4"
v-model=
"phoneCode"
/>
<input
type=
"button"
class=
"form-button"
:disabled=
"codeButtonDisabled"
:value=
"buttonText"
@
click=
"onSendCode"
/>
</div>
<div
class=
"form-item"
>
<input
type=
"button"
value=
"立即报名"
class=
"form-button"
@
click=
"onSbumit"
/>
</div>
</div>
</div>
</
template
>
<
script
>
import
*
as
api
from
'@/api/base'
export
default
{
data
()
{
return
{
ruleForm
:
{
name
:
''
,
phone
:
''
,
project_id
:
'5007'
,
channel
:
''
},
phoneCode
:
''
,
codeButtonDisabled
:
false
,
timer
:
null
,
disabledTime
:
60
}
},
mounted
()
{
this
.
ruleForm
.
channel
=
window
.
localStorage
.
getItem
(
'channel_num'
)
||
19960
},
computed
:
{
buttonText
()
{
return
this
.
codeButtonDisabled
?
`
${
this
.
disabledTime
}
s`
:
'获取验证码'
}
},
methods
:
{
onSbumit
()
{
if
(
!
this
.
ruleForm
.
name
)
{
this
.
$notify
(
'请输入您的姓名'
)
return
}
if
(
!
this
.
ruleForm
.
phone
||
!
/^1
[
3-9
]\d{9}
$/
.
test
(
this
.
ruleForm
.
phone
))
{
this
.
$notify
(
'请输入正确的手机号'
)
return
}
if
(
!
this
.
phoneCode
)
{
this
.
$notify
(
'请输入短信验证码'
)
return
}
this
.
checkPhoneCode
().
then
(
this
.
handleSubmit
)
},
handleSubmit
()
{
const
params
=
{
...
this
.
ruleForm
}
api
.
submit
(
params
).
then
((
response
)
=>
{
// this.$notify({ type: 'success', message: response.message })
this
.
$dialog
.
alert
({
message
:
response
.
message
}).
then
(()
=>
{
this
.
$emit
(
'success'
)
})
})
},
// 校验短信验证码
checkPhoneCode
()
{
return
api
.
checkCode
({
account
:
this
.
ruleForm
.
phone
,
code
:
this
.
phoneCode
})
},
onSendCode
()
{
if
(
!
this
.
ruleForm
.
phone
||
!
/^1
[
3-9
]\d{9}
$/
.
test
(
this
.
ruleForm
.
phone
))
{
this
.
$notify
(
'请输入正确的手机号'
)
return
}
this
.
sendCode
()
},
// 发送验证码
sendCode
()
{
this
.
setTimer
()
api
.
sendCode
({
account
:
this
.
ruleForm
.
phone
})
.
then
(()
=>
{
this
.
$notify
({
type
:
'success'
,
message
:
'验证码发送成功,注意查收'
})
})
.
catch
(()
=>
{
this
.
clearTimer
()
})
},
setTimer
()
{
this
.
codeButtonDisabled
=
true
this
.
disabledTime
=
60
this
.
timer
=
setInterval
(()
=>
{
this
.
disabledTime
--
if
(
this
.
disabledTime
<=
0
)
{
this
.
clearTimer
()
}
},
1000
)
},
clearTimer
()
{
this
.
codeButtonDisabled
=
false
this
.
timer
&&
clearInterval
(
this
.
timer
)
}
},
destroyed
()
{
this
.
clearTimer
()
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.app-apply-form
{
min-width
:
290px
;
position
:
relative
;
z-index
:
3000
;
.title
{
padding
:
30px
0
;
font-size
:
20px
;
color
:
#fff
;
text-align
:
center
;
}
}
.form-item
{
display
:
flex
;
align-items
:
center
;
margin-bottom
:
20px
;
}
.form-input
{
padding
:
0
10px
;
width
:
100%
;
height
:
38px
;
background-color
:
#fff
;
box-sizing
:
border-box
;
border
:
none
;
}
.form-select
{
position
:
relative
;
padding
:
0
10px
;
width
:
100%
;
height
:
38px
;
background
:
#fff
url('https://webapp-pub.ezijing.com/www/h5/images/icon_arrows.png')
no-repeat
;
background-position
:
right
0
.7em
top
50%
,
0
0
;
background-size
:
30px
30px
;
box-sizing
:
border-box
;
border
:
none
;
}
.form-button
{
padding
:
0
10px
;
width
:
100%
;
height
:
38px
;
font-size
:
16px
;
color
:
#aa1941
;
background-color
:
#ffd61b
;
box-sizing
:
border-box
;
border
:
none
;
cursor
:
pointer
;
}
.form-input
+
.form-button
{
margin-left
:
10px
;
}
</
style
>
\ No newline at end of file
src/components/layout/Footer.vue
浏览文件 @
da6e909b
差异被折叠。
点击展开。
src/components/layout/Index.vue
浏览文件 @
da6e909b
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
AppHeader
from
'./Header.vue'
import
AppHeader
from
'./Header.vue'
import
AppFooter
from
'./Footer.vue'
import
AppFooter
from
'./Footer.vue'
import
RightAside
from
'./RightAside.vue'
import
RightAsideH5
from
'./RightAsideH5.vue'
import
{
useDevice
}
from
'@/composables/useDevice'
const
{
mobile
}
=
useDevice
()
const
route
=
useRoute
()
interface
Props
{
interface
Props
{
fixed
?:
boolean
fixed
?:
boolean
}
}
...
@@ -13,6 +18,16 @@ const props = defineProps<Props>()
...
@@ -13,6 +18,16 @@ const props = defineProps<Props>()
<section
class=
"app-layout-container"
>
<section
class=
"app-layout-container"
>
<router-view
:key=
"$route.fullPath"
></router-view>
<router-view
:key=
"$route.fullPath"
></router-view>
</section>
</section>
<AppFooter></AppFooter>
<template
v-if=
"(!mobile && route.path !== '/shop/pay') || route.path !== '/shop'"
>
<AppFooter></AppFooter>
</
template
>
<
template
v-if=
"!mobile"
>
<RightAside
/>
</
template
>
<
template
v-else
>
<RightAsideH5
/>
</
template
>
</div>
</div>
</template>
</template>
src/components/layout/RightAside.vue
0 → 100644
浏览文件 @
da6e909b
<
script
>
import
{
sendCode
,
checkCode
,
postNes
}
from
'@/api/base'
const
MOBILE_REG
=
/^1
(
3
[
0-9
]
|4
[
01456879
]
|5
[
0-35-9
]
|6
[
2567
]
|7
[
0-8
]
|8
[
0-9
]
|9
[
0-35-9
])\d{8}
$/
export
default
{
data
()
{
return
{
tabBtnActive
:
false
,
tabBtnTarget
:
''
,
projectName
:
'金融硕士保研项目'
,
sendCode
:
''
,
isBtnDisabled
:
false
,
formInfo
:
{
name
:
''
,
phone
:
''
,
projectId
:
'5007'
}
}
},
methods
:
{
handleMsOver
(
type
)
{
this
.
tabBtnActive
=
true
if
(
type
!==
''
)
{
this
.
tabBtnTarget
=
type
}
},
handleMsOut
(
type
)
{
this
.
tabBtnActive
=
false
},
submitEnroll
()
{
let
flag
=
true
Object
.
keys
(
this
.
formInfo
).
map
((
item
)
=>
{
if
(
this
.
formInfo
[
item
]
===
''
)
{
flag
=
false
}
})
if
(
!
flag
||
!
this
.
sendCode
)
{
this
.
$message
(
'请完善信息'
)
}
else
if
(
!
MOBILE_REG
.
test
(
this
.
formInfo
.
phone
))
{
this
.
$message
(
'手机号格式错误'
)
}
else
{
this
.
checkSendcode
()
.
then
((
res
)
=>
{
return
this
.
enrollQuery
()
})
.
then
((
res
)
=>
{
this
.
$message
({
type
:
'success'
,
message
:
'报名成功'
,
duration
:
5000
})
})
.
catch
((
err
)
=>
{
if
(
err
&&
err
.
type
===
'checkcode'
)
this
.
$message
.
error
(
err
.
msg
)
else
this
.
$message
.
error
(
err
.
msg
||
'报名提交失败'
)
})
}
},
enrollQuery
()
{
const
params
=
{
channel
:
localStorage
.
getItem
(
'channel_num'
)
||
19962
,
project_id
:
this
.
formInfo
.
projectId
,
name
:
this
.
formInfo
.
name
,
phone
:
this
.
formInfo
.
phone
}
return
new
Promise
((
resolve
,
reject
)
=>
{
postNes
(
params
).
then
((
res
)
=>
{
if
(
res
&&
res
.
status
===
200
&&
res
.
error
===
0
)
{
resolve
({
type
:
'enroll'
,
state
:
'success'
})
}
else
{
reject
({
type
:
'enroll'
,
state
:
'fail'
,
msg
:
res
.
message
||
'报名提交失败'
})
}
})
})
},
getSendCode
()
{
if
(
!
this
.
formInfo
.
phone
)
{
this
.
$message
(
'手机号不能为空'
)
}
else
if
(
!
MOBILE_REG
.
test
(
this
.
formInfo
.
phone
))
{
this
.
$message
(
'手机号格式错误'
)
}
else
{
const
param
=
{
account
:
this
.
formInfo
.
phone
,
service
:
'ezijing.com'
}
sendCode
(
param
)
.
then
((
res
)
=>
{
this
.
btnDisabledTimer
()
if
(
res
&&
res
.
code
===
0
)
this
.
$message
.
success
(
'验证码已发送,请注意查收'
)
else
this
.
$message
.
error
(
'获取验证码失败,请稍后再试'
)
})
.
catch
(()
=>
{})
}
},
checkSendcode
()
{
const
checkCodeParam
=
{
account
:
this
.
formInfo
.
phone
,
code
:
this
.
sendCode
,
countryCode
:
86
}
return
new
Promise
((
resolve
,
reject
)
=>
{
checkCode
(
checkCodeParam
).
then
((
res
)
=>
{
if
(
res
&&
res
.
code
===
0
)
{
res
.
type
=
'checkcode'
resolve
({
type
:
'checked'
,
state
:
'success'
})
}
else
{
reject
({
type
:
'checked'
,
state
:
'fail'
,
msg
:
res
.
msg
||
'验证码检测失败'
})
}
})
})
},
btnDisabledTimer
()
{
this
.
isBtnDisabled
=
true
let
count
=
60
document
.
querySelector
(
'#checkedCode'
).
innerHTML
=
count
+
's'
const
timer
=
setInterval
(()
=>
{
count
--
if
(
count
<
1
)
{
clearInterval
(
timer
)
this
.
isBtnDisabled
=
false
document
.
querySelector
(
'#checkedCode'
).
innerHTML
=
'获取验证码'
}
else
{
document
.
querySelector
(
'#checkedCode'
).
innerHTML
=
count
+
's'
}
},
1000
)
}
}
}
</
script
>
<
template
>
<div
class=
"right_bar"
>
<ul
class=
"tab_btns"
>
<li
:class=
"
{
enroll: true,
active: tabBtnActive
&&
tabBtnTarget === 'enroll'
}"
@mouseenter="handleMsOver('enroll')"
@mouseleave="handleMsOut"
>
<p>
报名咨询
</p>
</li>
</ul>
<div
id=
"show-enroll"
v-show=
"tabBtnActive"
class=
"tab_cont"
@
mouseenter=
"handleMsOver('')"
@
mouseleave=
"handleMsOut"
>
<div
class=
"enroll_cont"
id=
"show-enroll-content"
>
<h5>
报名咨询
</h5>
<div
class=
"p"
>
<el-input
v-model=
"formInfo.name"
placeholder=
"请输入您的名字"
size=
"small"
></el-input>
</div>
<div
class=
"p"
>
<el-input
v-model=
"formInfo.phone"
placeholder=
"请输入您的电话"
size=
"small"
></el-input>
</div>
<div
class=
"p sendcode"
>
<el-input
v-model=
"sendCode"
placeholder=
"请输入验证码"
size=
"small"
></el-input
><el-button
class=
"btn"
:disabled=
"isBtnDisabled"
id=
"checkedCode"
@
click=
"getSendCode"
>
获取验证码
</el-button>
</div>
<div
class=
"p"
>
<el-button
style=
"width: 100%"
@
click=
"submitEnroll"
>
立即报名
</el-button
>
</div>
</div>
</div>
</div>
</
template
>
<
style
lang=
"scss"
scoped
>
.right_bar
{
position
:
fixed
;
top
:
50%
;
right
:
10px
;
z-index
:
2000
;
transform
:
translateY
(
-50%
);
.tab_btns
{
width
:
100px
;
font-size
:
12px
;
border-radius
:
4px
;
box-shadow
:
0px
2px
4px
0px
rgba
(
0
,
0
,
0
,
0
.1
);
overflow
:
hidden
;
li
{
padding
:
70px
0
18px
;
color
:
#999
;
background-position
:
center
18px
;
background-repeat
:
no-repeat
;
background-color
:
#fff
;
text-align
:
center
;
}
li
.active
{
background-color
:
#af1b40
;
color
:
#fff
;
opacity
:
0
.9
;
transition
:
0
.3s
;
}
li
.enroll
{
position
:
relative
;
background-image
:
url(https://zws-imgs-pub.ezijing.com/static/public/d434fa0ffd77892273e63e6d694cff0a.png)
;
}
li
.enroll
:after
{
content
:
''
;
width
:
100%
;
height
:
1px
;
background
:
#b8bcbf
;
position
:
absolute
;
left
:
0
;
bottom
:
0
;
// transform: translateX(-50%) scale(0.5);
}
li
.enroll.active
{
background-image
:
url(https://zws-imgs-pub.ezijing.com/static/public/4cbef518113d24b392be80148e921abd.png)
;
}
li
.wx
{
background-image
:
url(https://zws-imgs-pub.ezijing.com/static/public/5526b83d7526b2742f6eba7151c367db.png)
;
}
li
.wx.active
{
background-image
:
url(https://zws-imgs-pub.ezijing.com/static/public/0831ea27fee535ab0ce9f730f467b2e1.png)
;
}
li
>
p
{
font-size
:
12px
;
line-height
:
14px
;
text-align
:
center
;
// transform: scale(0.9);
line-height
:
100%
;
cursor
:
default
;
}
}
.tab_cont
{
position
:
absolute
;
left
:
-360px
;
top
:
-120px
;
width
:
346px
;
height
:
390px
;
background
:
url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/project_online/fi/right_bg.png)
;
// display:none;
h5
{
font-size
:
24px
;
font-weight
:
400
;
line-height
:
19px
;
color
:
#ffffff
;
text-align
:
center
;
margin-bottom
:
25px
;
}
.enroll_cont
{
padding
:
46px
29px
69px
29px
;
box-sizing
:
border-box
;
.p
{
margin-bottom
:
20px
;
position
:
relative
;
:deep
(
.el-input__inner
)
{
line-height
:
40px
;
height
:
40px
;
}
:deep
(
.el-input__inner
::placeholder
)
{
font-weight
:
300
;
font-size
:
14px
;
color
:
#999999
;
line-height
:
40px
;
height
:
40px
;
}
:deep
(
.el-button
)
{
background-color
:
#c1ab85
;
border
:
1px
solid
#c1ab85
;
color
:
#ffffff
;
height
:
40px
;
font-size
:
16px
;
}
}
.sendcode
{
display
:
flex
;
justify-content
:
space-between
;
:deep
(
.el-input
)
{
width
:
170px
;
height
:
40px
;
}
:deep
(
.el-button
)
{
height
:
40px
;
color
:
#ffffff
;
font-size
:
14px
;
margin-left
:
10px
;
}
:deep
(
.is-disabled
)
{
color
:
#c0c4cc
;
cursor
:
not
-
allowed
;
background-image
:
none
;
background-color
:
#fff
;
border-color
:
#ebeef5
;
}
}
}
}
}
</
style
>
src/components/layout/RightAsideH5.vue
0 → 100644
浏览文件 @
da6e909b
<
template
>
<div
class=
"rigth-aside"
>
<ul
class=
"right-aside-btns"
>
<li
@
click=
"showApplyForm"
>
<img
src=
"https://zws-imgs-pub.ezijing.com/static/public/d434fa0ffd77892273e63e6d694cff0a.png"
/>
<p>
报名咨询
</p>
</li>
</ul>
</div>
<!-- 我要报名 -->
<van-overlay
:show=
"applyFormVisible"
@
click=
"hideApplyForm"
>
<div
class=
"dialog-box"
@
click
.
stop
>
<apply-form
@
success=
"hideApplyForm"
></apply-form>
</div>
</van-overlay>
</
template
>
<
script
>
import
ApplyForm
from
'./ApplyForm.vue'
export
default
{
components
:
{
ApplyForm
},
data
()
{
return
{
applyFormVisible
:
false
}
},
methods
:
{
// 我要报名
showApplyForm
()
{
this
.
applyFormVisible
=
true
},
hideApplyForm
()
{
this
.
applyFormVisible
=
false
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.van-overlay
{
z-index
:
1000
!
important
;
}
.rigth-aside
{
position
:
fixed
;
top
:
40%
;
right
:
16px
;
z-index
:
1000
;
transform
:
translateY
(
-50%
);
.right-aside-btns
{
box-shadow
:
0
2px
4px
0
rgb
(
0
0
0
/
10%
);
li
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
width
:
1rem
;
height
:
1rem
;
font-size
:
0
.1rem
;
color
:
#999
;
background-color
:
#fff
;
cursor
:
pointer
;
border-radius
:
0
.12rem
;
img
{
width
:
0
.46rem
;
height
:
0
.46rem
;
}
}
}
}
.dialog-box
{
position
:
absolute
;
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
flex-direction
:
column
;
width
:
6
.9rem
;
height
:
7
.5rem
;
background
:
url('https://webapp-pub.ezijing.com/www/h5/images/dialog_bg.png')
no-repeat
;
background-size
:
cover
;
.title
{
font-size
:
0
.4rem
;
color
:
#fff
;
text-align
:
center
;
}
}
</
style
>
src/modules/shop/views/Index.vue
浏览文件 @
da6e909b
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
CourseList
from
'../components/CourseList.vue'
import
CourseList
from
'../components/CourseList.vue'
import
{
useShopStore
}
from
'@/stores/shop'
import
{
useShopStore
}
from
'@/stores/shop'
import
{
useDevice
}
from
'@/composables/useDevice'
const
{
mobile
}
=
useDevice
()
const
shopStore
=
useShopStore
()
const
shopStore
=
useShopStore
()
const
handleTabClick
=
(
tab
:
any
)
=>
{
const
handleTabClick
=
(
tab
:
any
)
=>
{
if
(
tab
.
index
===
'4'
)
{
if
(
tab
.
index
===
'4'
)
{
...
@@ -12,7 +13,7 @@ const handleTabClick = (tab: any) => {
...
@@ -12,7 +13,7 @@ const handleTabClick = (tab: any) => {
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"main_shop"
>
<div
class=
"main_shop"
v-if=
"!mobile"
>
<img
<img
src=
"https://webapp-pub.ezijing.com/project_online/fi/shop_banner.jpg"
src=
"https://webapp-pub.ezijing.com/project_online/fi/shop_banner.jpg"
class=
"shop_banner"
class=
"shop_banner"
...
@@ -38,6 +39,22 @@ const handleTabClick = (tab: any) => {
...
@@ -38,6 +39,22 @@ const handleTabClick = (tab: any) => {
</div>
</div>
</div>
</div>
</div>
</div>
<div
v-else
>
<van-tabs>
<van-tab
:title=
"item.label"
v-for=
"(item, index) in shopStore.filters.slice(0, 4)"
:key=
"index"
lazy
>
<CourseList
:type=
"item.value"
:courseList=
"shopStore.shopList"
:key=
"index"
/>
</van-tab>
</van-tabs>
</div>
</template>
</template>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
.is-pc
{
.is-pc
{
...
@@ -121,7 +138,7 @@ const handleTabClick = (tab: any) => {
...
@@ -121,7 +138,7 @@ const handleTabClick = (tab: any) => {
font-weight
:
500
;
font-weight
:
500
;
line-height
:
34px
;
line-height
:
34px
;
color
:
#eda020
;
color
:
#eda020
;
padding
:
0
0
.
1
rem
!
important
;
padding
:
0
0
.
4
rem
!
important
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
}
}
:deep
(
.el-tabs__nav-scroll
)
{
:deep
(
.el-tabs__nav-scroll
)
{
...
@@ -152,4 +169,25 @@ const handleTabClick = (tab: any) => {
...
@@ -152,4 +169,25 @@ const handleTabClick = (tab: any) => {
display
:
none
;
display
:
none
;
}
}
}
}
:deep
(
.van-tab--active
)
{
.van-tab__text
{
color
:
#eda020
!
important
;
font-size
:
0
.28rem
;
}
}
:deep
(
.van-tab
)
{
.van-tab__text
{
color
:
#333333
;
font-size
:
0
.28rem
;
}
.van-tabs__nav
{
background
:
none
;
}
}
:deep
(
.van-tabs__line
)
{
background
:
#eda023
!
important
;
}
:deep
(
.van-tab__panel
)
{
margin-top
:
0
.3rem
;
}
</
style
>
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论