Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
O
offical_web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhangjie
offical_web
Commits
d081497d
Commit
d081497d
authored
Nov 05, 2025
by
wusiyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 官网2.0样式优化
parent
d5494f62
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
164 additions
and
173 deletions
+164
-173
src/components/footBanner.vue
+1
-1
src/components/headerNavMobile.vue
+32
-58
src/main.js
+12
-6
src/utils/axios.js
+27
-18
src/views/homePage/forgetPassword.vue
+0
-0
src/views/homePage/index.vue
+1
-1
src/views/homePage/login.vue
+49
-21
src/views/homePage/platform.vue
+42
-68
src/views/homePage/register.vue
+0
-0
No files found.
src/components/footBanner.vue
View file @
d081497d
...
...
@@ -6,7 +6,7 @@
<p
class=
"footer-title"
>
{{
bannerContent
.
title
}}
</p>
<p
class=
"footer-description"
>
{{
bannerContent
.
description
}}
</p>
<button
class=
"footer-register-btn"
@
click=
"goToLogin"
>
立即使用
</button>
<Register
v-if
=
"registerDialog"
@
close=
"registerDialog = false"
/>
<Register
:visible
=
"registerDialog"
@
close=
"registerDialog = false"
/>
</div>
<div
class=
"bg-right"
></div>
</div>
...
...
src/components/headerNavMobile.vue
View file @
d081497d
...
...
@@ -98,6 +98,12 @@
</
template
>
<
script
>
import
{
mapMutations
}
from
'vuex'
import
productionSvg
from
'../assets/images/home/production.svg'
import
customSvg
from
'../assets/images/home/custom.svg'
import
supplyChainSvg
from
'../assets/images/home/earth.svg'
import
logisticsSvg
from
'../assets/images/home/logistics.svg'
import
usSvg
from
'../assets/images/product/us.svg'
export
default
{
name
:
'headerNavMobile'
,
data
()
{
...
...
@@ -111,71 +117,34 @@ export default {
expanding
:
false
,
children
:
[
{
name
:
'生产管理'
,
path
:
'/product/production'
,
name
:
'九猫ERP'
,
subTitle
:
'精细化运营和供应链一体化解决方案'
,
path
:
'/product/production?tab=product'
,
icon
:
productionSvg
,
},
{
name
:
'一件定制'
,
path
:
'/product/custom-chain'
,
name
:
'POD和满印供应链'
,
subTitle
:
'⼏⼗万件底胚库存,多种⼯艺,五千多款模型,品类⻬全'
,
path
:
'/product/production?tab=custom-chain'
,
icon
:
customSvg
,
},
{
name
:
'海外仓物流'
,
path
:
'/product/logistics'
,
name
:
'九猫美国供应链 [LA POD]'
,
subTitle
:
'美国本⼟海外⽣产线,平台客户⾸选'
,
path
:
'/product/production?tab=supply-chain'
,
icon
:
supplyChainSvg
,
},
{
name
:
'自建站平台'
,
path
:
'/product/platform'
,
name
:
'九猫物流'
,
subTitle
:
'集成国内主流物流,价格优惠时效快'
,
path
:
'/product/production?tab=logistics'
,
icon
:
logisticsSvg
,
},
],
},
{
name
:
'价格'
,
path
:
'/price'
},
{
name
:
'一件定制'
,
path
:
'https://jomalls.com/custom/'
},
{
name
:
'案例'
,
path
:
'/case'
},
{
name
:
'资源与支持'
,
path
:
'/support'
,
expanding
:
false
,
children
:
[
{
name
:
'资源'
,
expanding
:
false
,
children
:
[
{
name
:
'活动信息'
,
path
:
''
,
},
{
name
:
'入住流程平台'
,
path
:
''
,
},
{
name
:
'资讯'
,
path
:
''
,
},
],
},
{
name
:
'支持'
,
expanding
:
false
,
children
:
[
{
name
:
'帮助中心'
,
path
:
''
,
},
],
},
{
name
:
'了解SaaS ERP'
,
expanding
:
false
,
// children: [
// {
// name: '如何通过财务管控向内部要效益',
// path: '/financial',
// },
// ],
},
],
},
// { name: '案例', path: '/case' },
{
name
:
'关于'
,
path
:
'/about'
,
...
...
@@ -183,14 +152,19 @@ export default {
children
:
[
{
name
:
'关于我们'
,
subTitle
:
'九猫ERP以精细化管理方案,帮助卖家实现业务增长'
,
path
:
'/about'
,
icon
:
usSvg
,
},
{
name
:
'加入我们'
,
path
:
'/join'
,
},
// {
// name: '加入我们',
// subTitle: '加入九猫,一切皆有可能',
// path: '/join',
// icon: joinSvg,
// },
],
},
{
name
:
'帮助'
,
path
:
'/help'
},
],
}
},
...
...
src/main.js
View file @
d081497d
...
...
@@ -20,12 +20,18 @@ import './assets/css/index.css'
import
'./styles/index.scss'
const
isMobile
=
()
=>
window
.
innerWidth
<=
1100
Vue
.
util
.
defineReactive
(
Vue
.
prototype
,
'$isMobile'
,
isMobile
())
// document.querySelector('html').style.fontSize = window.innerWidth / 100 + 'px'
// window.addEventListener('resize', () => {
// Vue.prototype.$isMobile = isMobile()
// document.querySelector('html').style.fontSize = window.innerWidth / 100 + 'px'
// })
// 响应式更新 $isMobile 状态
const
mobileData
=
Vue
.
observable
({
value
:
isMobile
()
})
Object
.
defineProperty
(
Vue
.
prototype
,
'$isMobile'
,
{
get
()
{
return
mobileData
.
value
},
enumerable
:
true
,
configurable
:
true
})
window
.
addEventListener
(
'resize'
,
()
=>
{
mobileData
.
value
=
isMobile
()
})
new
Vue
({
store
,
...
...
src/utils/axios.js
View file @
d081497d
...
...
@@ -20,7 +20,7 @@ const zImgPath = window.apiHostSetting.VUE_APP_ZIMG_URL
// 文件存储路径地址
const
filePath
=
getStaticPath
()
+
'upload/erp'
const
instance
=
axios
.
create
({
baseURL
:
baseURL
+
'api/'
,
baseURL
:
baseURL
+
'api/'
,
timeout
:
5
*
60
*
1000
,
// headers: {
// "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
...
...
@@ -43,12 +43,15 @@ instance.interceptors.request.use(
}
config
.
data
=
data
}
if
(
HTTPNUM
===
0
)
{
loading
=
Vue
.
prototype
.
$loading
({
background
:
'rgba(0, 0, 0, 0.3)'
,
})
// 如果配置了 skipLoading,跳过全局 loading
if
(
!
config
.
skipLoading
)
{
if
(
HTTPNUM
===
0
)
{
loading
=
Vue
.
prototype
.
$loading
({
background
:
'rgba(0, 0, 0, 0.3)'
,
})
}
HTTPNUM
++
}
HTTPNUM
++
cancelToken
.
add
(
config
)
return
config
},
...
...
@@ -62,9 +65,12 @@ instance.interceptors.request.use(
instance
.
interceptors
.
response
.
use
(
(
res
)
=>
{
cancelToken
.
remove
(
res
.
config
)
HTTPNUM
--
if
(
HTTPNUM
===
0
)
{
loading
.
close
()
// 如果配置了 skipLoading,跳过全局 loading 的关闭
if
(
!
res
.
config
.
skipLoading
)
{
HTTPNUM
--
if
(
HTTPNUM
===
0
)
{
loading
.
close
()
}
}
if
(
res
.
status
===
200
)
{
if
(
res
.
data
.
code
===
401
)
{
...
...
@@ -144,22 +150,25 @@ instance.interceptors.response.use(
// 服务器状态码不是200的情况
(
error
)
=>
{
cancelToken
.
clear
()
HTTPNUM
--
if
(
HTTPNUM
==
0
)
{
Vue
.
prototype
.
$alert
(
error
.
message
,
'Error'
,
{
confirmButtonText
:
'确定'
,
callback
:
()
=>
{},
})
loading
.
close
()
// 如果配置了 skipLoading,跳过全局 loading 的关闭和错误提示
if
(
!
error
.
config
||
!
error
.
config
.
skipLoading
)
{
HTTPNUM
--
if
(
HTTPNUM
==
0
)
{
Vue
.
prototype
.
$alert
(
error
.
message
,
'Error'
,
{
confirmButtonText
:
'确定'
,
callback
:
()
=>
{},
})
loading
.
close
()
}
}
return
Promise
.
reject
(
error
)
}
)
function
get
(
url
,
params
)
{
function
get
(
url
,
params
,
config
=
{}
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
instance
.
get
(
url
,
{
params
})
.
get
(
url
,
{
params
,
...
config
})
.
then
((
res
)
=>
{
if
(
res
.
status
===
200
&&
res
.
data
)
{
resolve
(
res
.
data
)
...
...
src/views/homePage/forgetPassword.vue
View file @
d081497d
This diff is collapsed.
Click to expand it.
src/views/homePage/index.vue
View file @
d081497d
...
...
@@ -36,7 +36,7 @@
<platform
/>
<product-intro
/>
<Register
v-if
=
"registerDialog"
@
close=
"registerDialog = false"
/>
<Register
:visible
=
"registerDialog"
@
close=
"registerDialog = false"
/>
</div>
</
template
>
<
script
>
...
...
src/views/homePage/login.vue
View file @
d081497d
...
...
@@ -16,7 +16,8 @@
<el-radio-group
v-model=
"labelPosition"
class=
"radioGroup mt-5 flex justify-center items-center mb-5"
size=
"small"
>
size=
"small"
@
change=
"clickChange"
>
<el-radio-button
label=
"passwordLogin"
>
密码登录
</el-radio-button>
<el-radio-button
label=
"verificationLogin"
>
验证码登录
</el-radio-button>
</el-radio-group>
...
...
@@ -75,7 +76,7 @@
prefix-icon=
"el-icon-postcard"
placeholder=
"请输入验证码(区分大小写)"
></el-input>
</div>
<div
@
click=
"getVerifycode"
>
<div
class=
"cursor-pointer"
@
click=
"getVerifycode"
>
<img
class=
"w-20 lg:w-32 h-full"
:src=
"VerifyUrl"
/>
</div>
</div>
...
...
@@ -88,11 +89,11 @@
<div
class=
"flex-1"
>
<el-input
v-model=
"ruleForm.code"
prefix-icon=
"el-icon-
messag
e"
prefix-icon=
"el-icon-
chat-line-squar
e"
placeholder=
"请输入短信验证码"
></el-input>
</div>
<el-button
class=
"w-22 text-white border-0"
class=
"w-22 text-white
text-xs lg:text-base
border-0"
:disabled=
"getCodeDisabled"
:class=
"getCodeDisabled ? 'disabled' : 'get-code-button'"
@
click=
"verPhonecode"
>
...
...
@@ -119,8 +120,7 @@
<
el
-
divider
direction
=
"vertical"
class
=
"bottom-line"
><
/el-divider
>
<
div
class
=
"register-btn-text cursor-pointer"
@
click
=
"registerDialog = true"
style
=
"color: var(--primary-color)"
>
@
click
=
"registerDialog = true"
>
马上注册
<
/div
>
<
/div
>
...
...
@@ -131,9 +131,8 @@
<
ForgetPassword
v
-
if
=
"isShowModal"
:
visible
=
"isShowModal"
:
label
-
position
=
"labelPosition"
@
close
=
"isShowModal = false"
/>
<
Register
v
-
if
=
"registerDialog"
@
close
=
"registerDialog = false"
/>
<
Register
:
visible
=
"registerDialog"
@
close
=
"registerDialog = false"
/>
<
/div
>
<
/template
>
...
...
@@ -175,7 +174,9 @@ export default {
trigger
:
[
'blur'
,
'change'
],
}
,
],
code
:
[{
required
:
true
,
message
:
'请输入验证码'
,
trigger
:
'blur'
}
],
code
:
[
{
required
:
true
,
message
:
'请输入短信验证码'
,
trigger
:
'blur'
}
,
],
verifyKey
:
[
{
required
:
true
,
message
:
'请输入验证码'
,
trigger
:
'blur'
}
,
],
...
...
@@ -188,11 +189,23 @@ export default {
return
this
.
codeCountDown
>
0
}
,
}
,
mounted
()
{
this
.
getVerifycode
()
}
,
methods
:
{
...
mapMutations
([
'setUserInfo'
]),
initForm
()
{
this
.
ruleForm
=
{
}
this
.
codeCountDown
=
0
if
(
this
.
labelPosition
===
'verificationLogin'
)
{
this
.
getVerifycode
()
}
this
.
$nextTick
(()
=>
{
this
.
$refs
.
ruleForm
&&
this
.
$refs
.
ruleForm
.
clearValidate
()
}
)
}
,
clearTimer
()
{
if
(
this
.
timer
)
clearInterval
(
this
.
timer
)
this
.
timer
=
null
}
,
async
verPhonecode
()
{
try
{
await
new
Promise
((
resolve
,
reject
)
=>
{
...
...
@@ -263,13 +276,26 @@ export default {
}
,
getVerifycode
()
{
this
.
verifyKeyTime
=
new
Date
().
getTime
()
get
(
'business/user/verifycode'
,
{
verifyKey
:
this
.
verifyKeyTime
,
}
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
this
.
VerifyUrl
=
res
.
message
}
}
)
get
(
'business/user/verifycode'
,
{
verifyKey
:
this
.
verifyKeyTime
,
}
,
{
skipLoading
:
true
}
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
this
.
VerifyUrl
=
res
.
message
}
else
{
this
.
VerifyUrl
=
''
}
}
)
.
catch
(()
=>
{
this
.
VerifyUrl
=
''
}
)
}
,
clickChange
()
{
this
.
initForm
()
}
,
}
,
}
...
...
@@ -315,9 +341,10 @@ export default {
}
.
disabled
{
background
-
color
:
#
d0d2d8
;
background
-
color
:
#
f0f0f0
;
color
:
#
666
;
margin
-
left
:
10
px
;
border
:
1
px
solid
#
cccccc
;
cursor
:
not
-
allowed
;
}
.
code
-
btn
{
...
...
@@ -348,6 +375,7 @@ export default {
}
.
register
-
btn
-
text
{
color
:
var
(
--
primary
-
color
);
&
:
hover
{
color
:
var
(
--
hover
-
color
);
}
...
...
src/views/homePage/platform.vue
View file @
d081497d
<
template
>
<div
class=
"docking-platform flex justify-center"
>
<div>
<div
class=
"flex justify-center flex-col items-center mb-5 gap-2"
>
<div
class=
"mt-30 platforms-marquee flex justify-center"
>
<vue-seamless-scroll
:data=
"platforms"
:class-option=
"classOption"
class=
"warp"
>
<ul
class=
"flex flex-wrap"
>
<li
class=
"platform-item"
v-for=
"platform in platforms"
:key=
"platform.name"
>
<a
v-if=
"platform.link"
:href=
"platform.link"
target=
"_blank"
>
<img
class=
"platform-image"
:src=
"
require(`../../assets/platforms/$
{platform.name}.${platform.type}`)
"
:alt="platform.name" />
</a>
<img
v-else
class=
"platform-image"
:src=
"
require(`../../assets/platforms/$
{platform.name}.${platform.type}`)
"
:alt="platform.name" />
</li>
</ul>
</vue-seamless-scroll>
</div>
</div>
</div>
<div
class=
"docking-platform flex justify-center py-8"
>
<vue-seamless-scroll
:data=
"platforms"
:class-option=
"classOption"
class=
"warp flex justify-center items-center"
>
<ul
class=
"flex flex-wrap"
>
<li
class=
"platform-item flex justify-center items-center w-20"
v-for=
"platform in platforms"
:key=
"platform.name"
>
<a
v-if=
"platform.link"
:href=
"platform.link"
target=
"_blank"
class=
"flex justify-center items-center w-full h-full"
>
<img
class=
"platform-image"
:src=
"
require(`../../assets/platforms/$
{platform.name}.${platform.type}`)
"
:alt="platform.name" />
</a>
<img
v-else
class=
"platform-image"
:src=
"
require(`../../assets/platforms/$
{platform.name}.${platform.type}`)
"
:alt="platform.name" />
</li>
</ul>
</vue-seamless-scroll>
</div>
</
template
>
...
...
@@ -68,7 +66,7 @@ export default {
],
classOption
:
{
step
:
0.6
,
// 数值越大速度滚动越快
limitMoveNum
:
5
,
// 开始无缝滚动的数据量 this.dataList.length
limitMoveNum
:
18
,
// 开始无缝滚动的数据量 this.dataList.length
hoverStop
:
true
,
// 是否开启鼠标悬停stop
direction
:
1
,
// 0向下 1向上 2向左 3向右
autoPlay
:
true
,
// 是否自动滚动
...
...
@@ -82,12 +80,6 @@ export default {
<
style
scoped
lang=
"scss"
>
.docking-platform
{
background
:
var
(
--light-color
);
padding
:
30px
0
10px
0
;
}
.docking-platform
h2
{
color
:
#000
;
font-weight
:
500
;
}
.warp
{
...
...
@@ -95,42 +87,24 @@ export default {
height
:
100px
;
overflow
:
hidden
;
}
.lx-title
{
font-size
:
2.25rem
;
color
:
#ffffff
;
font-weight
:
500
;
line-height
:
1.75rem
;
margin-bottom
:
0.25rem
;
max-width
:
840px
;
text-align
:
center
;
--tw-text-opacity
:
1
;
letter-spacing
:
1px
;
}
.platform
s-marquee
.platform
-item
{
.platform-item
{
flex
:
0
0
auto
;
width
:
140px
;
height
:
60px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
.platforms-marquee
.platform-item
a
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
width
:
100%
;
height
:
100%
;
text-decoration
:
none
;
transition
:
opacity
0.3s
ease
;
@media
(
max-width
:
1100px
)
{
.warp
{
width
:
90%
;
}
.platform-item
{
width
:
33%
;
}
}
.platform-image
{
width
:
120px
;
height
:
auto
;
max-height
:
80px
;
object-fit
:
contain
;
width
:
80%
;
transition
:
filter
0.3s
ease
;
filter
:
brightness
(
0
)
invert
(
1
);
}
...
...
src/views/homePage/register.vue
View file @
d081497d
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment