Commit 688ba4d9 by wusiyi

Merge branch 'dev'

parents ed1504d5 09b9724c
...@@ -1074,10 +1074,18 @@ ul li { ...@@ -1074,10 +1074,18 @@ ul li {
} }
.bg-colorBg { .bg-colorBg {
--tw-bg-opacity: 1;
background-color: var(--background-color); background-color: var(--background-color);
} }
.bg-colorBg-gradient {
background-image: linear-gradient(
to bottom,
#ffffff00 1%,
var(--background-color),
#ffffff00 99%
);
}
.primary-color { .primary-color {
color: var(--primary-color); color: var(--primary-color);
} }
...@@ -1464,7 +1472,7 @@ ul li { ...@@ -1464,7 +1472,7 @@ ul li {
/* 菜单主题色 */ /* 菜单主题色 */
.el-menu { .el-menu {
background-color: var(--el-color-primary-light-9) !important; background-color: #fff !important;
} }
/* 评分主题色 */ /* 评分主题色 */
......
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 14 14">
<g fill="none">
<path fill="#fff3d7" d="M9.5 12.5a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-11a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1z" />
<path stroke="#e8af24" stroke-linecap="round" stroke-linejoin="round" d="M9.5 10.5v2a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-11a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v2M6.5 7h7m-2-2l2 2l-2 2" stroke-width="1.6" />
</g>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24">
<path fill="#faaa15" d="M22 10H2v9a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3zM7 8a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v4a1 1 0 0 1-1 1m10 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v4a1 1 0 0 1-1 1" opacity="0.5" />
<path fill="#faaa15" d="M19 4h-1v3a1 1 0 0 1-2 0V4H8v3a1 1 0 0 1-2 0V4H5a3 3 0 0 0-3 3v3h20V7a3 3 0 0 0-3-3" />
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 48 48">
<defs>
<mask id="SVG5A3x2kwa">
<g fill="none">
<path fill="#555555" stroke="#fff" stroke-linejoin="round" stroke-width="4" d="M24 44a19.94 19.94 0 0 0 14.142-5.858A19.94 19.94 0 0 0 44 24a19.94 19.94 0 0 0-5.858-14.142A19.94 19.94 0 0 0 24 4A19.94 19.94 0 0 0 9.858 9.858A19.94 19.94 0 0 0 4 24a19.94 19.94 0 0 0 5.858 14.142A19.94 19.94 0 0 0 24 44Z" />
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M24 28.625v-4a6 6 0 1 0-6-6" />
<path fill="#fff" fill-rule="evenodd" d="M24 37.625a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5" clip-rule="evenodd" />
</g>
</mask>
</defs>
<path fill="#faaa15" d="M0 0h48v48H0z" mask="url(#SVG5A3x2kwa)" />
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24">
<path fill="#faaa15" d="M12.22 19.85c-.18.18-.5.21-.71 0a.504.504 0 0 1 0-.71l3.39-3.39l-1.41-1.41l-3.39 3.39c-.19.2-.51.19-.71 0a.504.504 0 0 1 0-.71l3.39-3.39l-1.41-1.41l-3.39 3.39c-.18.18-.5.21-.71 0a.513.513 0 0 1 0-.71l3.39-3.39l-1.42-1.41l-3.39 3.39c-.18.18-.5.21-.71 0a.513.513 0 0 1 0-.71L9.52 8.4l1.87 1.86c.95.95 2.59.94 3.54 0c.98-.98.98-2.56 0-3.54l-1.86-1.86l.28-.28c.78-.78 2.05-.78 2.83 0l4.24 4.24c.78.78.78 2.05 0 2.83z" opacity="0.3" />
<path fill="#faaa15" d="M12.22 19.85c-.18.18-.5.21-.71 0a.504.504 0 0 1 0-.71l3.39-3.39l-1.41-1.41l-3.39 3.39c-.19.2-.51.19-.71 0a.504.504 0 0 1 0-.71l3.39-3.39l-1.41-1.41l-3.39 3.39c-.18.18-.5.21-.71 0a.513.513 0 0 1 0-.71l3.39-3.39l-1.42-1.41l-3.39 3.39c-.18.18-.5.21-.71 0a.513.513 0 0 1 0-.71L9.52 8.4l1.87 1.86c.95.95 2.59.94 3.54 0c.98-.98.98-2.56 0-3.54l-1.86-1.86l.28-.28c.78-.78 2.05-.78 2.83 0l4.24 4.24c.78.78.78 2.05 0 2.83zm9.61-6.78a4.01 4.01 0 0 0 0-5.66l-4.24-4.24a4.01 4.01 0 0 0-5.66 0l-.28.28l-.28-.28a4.01 4.01 0 0 0-5.66 0L2.17 6.71a3.99 3.99 0 0 0-.4 5.19l1.45-1.45a2 2 0 0 1 .37-2.33l3.54-3.54c.78-.78 2.05-.78 2.83 0l3.56 3.56c.18.18.21.5 0 .71s-.53.18-.71 0L9.52 5.57l-5.8 5.79c-.98.97-.98 2.56 0 3.54c.39.39.89.63 1.42.7a2.46 2.46 0 0 0 2.12 2.12a2.46 2.46 0 0 0 2.12 2.12c.07.54.31 1.03.7 1.42c.47.47 1.1.73 1.77.73s1.3-.26 1.77-.73z" />
</svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735112224989" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15492" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M0 0m512 0l0 0q512 0 512 512l0 0q0 512-512 512l0 0q-512 0-512-512l0 0q0-512 512-512Z" fill="#007BF6" p-id="15493"></path><path d="M512 0h4.2496A309.248 309.248 0 0 0 512 51.2v972.8C229.2224 1024 0 794.7776 0 512S229.2224 0 512 0z" fill="#339EFA" p-id="15494"></path><path d="M757.76 348.0576L523.264 258.048a31.8464 31.8464 0 0 0-22.4768 0l-234.496 90.0096A15.872 15.872 0 0 0 256 363.008v36.9664c0 8.8064 7.168 15.9744 15.9744 15.9744h480.1024c8.8064 0 16.0256-7.168 16.0256-15.9744V363.008a16.0768 16.0768 0 0 0-10.3424-14.9504zM320 448v160.0512h-15.9744a16.0256 16.0256 0 0 0-15.9744 15.9744v48.0768h448.1536v-48.0768a16.0256 16.0256 0 0 0-15.9744-15.9744h-16.0256V448h-64v160.0512h-96.1024V448h-64v160.0512H384V448H320zM752.128 704.0512H271.9232a16.0256 16.0256 0 0 0-15.9744 15.9744v32c0 8.8064 7.168 15.9744 15.9744 15.9744h480.1024c8.8064 0 16.0256-7.168 16.0256-15.9744v-32a15.9744 15.9744 0 0 0-16.0256-15.9744z" fill="#FFFFFF" p-id="15495"></path></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24">
<g fill="none">
<path fill="#fff" d="m12 23.29l8.33-3.92l2.45-15.19L12 .75L1.22 4.18l2.45 15.19z" />
<path fill="#f7ead4" d="m20.33 19.35l2.45-15.19L12 .73v22.54z" />
<path stroke="#faaa15" stroke-linecap="round" stroke-linejoin="round" d="m11.854 15.92l4.9-4.9l-2.45-2.94l-2.45 1.96l-2.45-1.96l-2.45 2.94z" stroke-width="1.3" />
<path stroke="#faaa15" stroke-linecap="round" stroke-linejoin="round" d="m12 23.27l8.33-3.92l2.45-15.19L12 .73L1.22 4.16l2.45 15.19z" stroke-width="1.3" />
<path stroke="#faaa15" stroke-linecap="round" stroke-linejoin="round" d="m12 20.82l6.37-2.94l1.96-12.25L12 2.69L3.67 5.63l1.96 12.25z" stroke-width="1.3" />
</g>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
<g fill="#faaa15">
<path d="M16 152h32v56H16a8 8 0 0 1-8-8v-40a8 8 0 0 1 8-8M192.54 40A39.12 39.12 0 0 0 156 64a39.12 39.12 0 0 0-36.54-24C97.67 40 80 58.31 80 80c0 14.56 7 27.71 16.73 40H140a20 20 0 0 1 0 40h4l37.78-8.68C203.82 135.07 232 109.23 232 80c0-21.69-17.67-40-39.46-40" opacity="0.2" />
<path d="M230.33 141.06a24.34 24.34 0 0 0-18.61-4.77C230.5 117.33 240 98.48 240 80c0-26.47-21.29-48-47.46-48A47.58 47.58 0 0 0 156 48.75A47.58 47.58 0 0 0 119.46 32C93.29 32 72 53.53 72 80c0 11 3.24 21.69 10.06 33a31.87 31.87 0 0 0-14.75 8.4L44.69 144H16a16 16 0 0 0-16 16v40a16 16 0 0 0 16 16h104a8 8 0 0 0 1.94-.24l64-16a7 7 0 0 0 1.19-.4L226 182.82l.44-.2a24.6 24.6 0 0 0 3.93-41.56ZM119.46 48a31.15 31.15 0 0 1 29.14 19a8 8 0 0 0 14.8 0a31.15 31.15 0 0 1 29.14-19C209.59 48 224 62.65 224 80c0 19.51-15.79 41.58-45.66 63.9l-11.09 2.55A28 28 0 0 0 140 112h-39.32C92.05 100.36 88 90.12 88 80c0-17.35 14.41-32 31.46-32M16 160h24v40H16Zm203.43 8.21l-38 16.18L119 200H56v-44.69l22.63-22.62A15.86 15.86 0 0 1 89.94 128H140a12 12 0 0 1 0 24h-28a8 8 0 0 0 0 16h32a8.3 8.3 0 0 0 1.79-.2l67-15.41l.31-.08a8.6 8.6 0 0 1 6.3 15.9Z" />
</g>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256">
<g fill="#faaa15">
<path d="M216 128a88 88 0 1 1-88-88a88 88 0 0 1 88 88" opacity="0.4" />
<path d="M245.11 60.68c-7.65-13.19-27.84-16.16-58.5-8.66A95.93 95.93 0 0 0 32 128a98 98 0 0 0 .78 12.31C5.09 169 5.49 186 10.9 195.32C16 204.16 26.64 208 40.64 208a124 124 0 0 0 28.79-4A95.93 95.93 0 0 0 224 128a97 97 0 0 0-.77-12.25c12.5-13 20.82-25.35 23.65-35.92c1.95-7.32 1.36-13.76-1.77-19.15M128 48a80.11 80.11 0 0 1 78 62.2c-17.06 16.06-40.15 32.53-62.07 45.13c-27.55 15.81-51.45 25.67-70.51 31.07A79.94 79.94 0 0 1 128 48M24.74 187.29c-1.46-2.51-.65-7.24 2.22-13a79 79 0 0 1 10.29-15.05a96 96 0 0 0 18 31.32c-17.25 2.9-28.01 1.05-30.51-3.27M128 208a79.45 79.45 0 0 1-38.56-9.94a370 370 0 0 0 62.43-28.86c21.58-12.39 40.68-25.82 56.07-39.08A80.07 80.07 0 0 1 128 208M231.42 75.69c-1.7 6.31-6.19 13.53-12.63 21.13a95.7 95.7 0 0 0-18-31.35c14.21-2.35 27.37-2.17 30.5 3.24c.9 1.57.95 3.92.13 6.98" />
</g>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 24 24">
<path fill="#faaa15" d="M16.67 13.13C18.04 14.06 19 15.32 19 17v3h4v-3c0-2.18-3.57-3.47-6.33-3.87M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4c-.47 0-.91.1-1.33.24a5.98 5.98 0 0 1 0 7.52c.42.14.86.24 1.33.24m-6 0c2.21 0 4-1.79 4-4s-1.79-4-4-4s-4 1.79-4 4s1.79 4 4 4m0-6c1.1 0 2 .9 2 2s-.9 2-2 2s-2-.9-2-2s.9-2 2-2m0 7c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4m6 5H3v-.99C3.2 16.29 6.3 15 9 15s5.8 1.29 6 2z" />
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 48 48">
<defs>
<mask id="SVG2m4WoNWP">
<g fill="none" stroke="#fff" stroke-linejoin="round" stroke-width="4">
<path fill="#555555" d="M8 44V6a2 2 0 0 1 2-2h28a2 2 0 0 1 2 2v38l-16-8.273z" />
<path stroke-linecap="round" d="M16 18h16" />
</g>
</mask>
</defs>
<path fill="#faaa15" d="M0 0h48v48H0z" mask="url(#SVG2m4WoNWP)" />
</svg>
\ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<FootBanner /> <FootBanner />
<footer class="banner_footer"> <footer class="banner_footer">
<div <div
class="footer-container flex justify-between text-white w-full-70 w-full-90 mx-auto py-12 px-6 lg:py-20 lg:px-0"> class="footer-container flex justify-between text-white w-full-70 w-full-90 mx-auto py-12 px-6 lg:py-14 lg:px-0">
<div class="footer-content-left"> <div class="footer-content-left">
<div class="mr-48 hidden lg:block"> <div class="mr-48 hidden lg:block">
<div class="jomalls text-3xl font-bold tracking-wider font-mono"> <div class="jomalls text-3xl font-bold tracking-wider font-mono">
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
</div> </div>
<div class="footer-content-right flex flex-1 flex-col"> <div class="footer-content-right flex flex-1 flex-col">
<div <div
class="flex flex-col lg:flex-row lg:justify-between lg:mb-20 mb-7.5"> class="flex flex-col lg:flex-row lg:justify-between lg:mb-10 mb-7.5">
<div <div
v-for="(section, index) in footerSections" v-for="(section, index) in footerSections"
:key="index" :key="index"
...@@ -353,7 +353,6 @@ export default { ...@@ -353,7 +353,6 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
.banner_footer { .banner_footer {
background: #20222e; background: #20222e;
padding-bottom: 48px;
} }
.footer-routers { .footer-routers {
......
<template> <template>
<div <div
class="header bg-white sticky shadow-sm" class="header bg-white sticky"
:class="{ shadow: !$route.path.includes('help') }" :class="{ 'shadow-sm': !$route.path.includes('help') }"
ref="header"> ref="header">
<headHelper v-if="$route.path.includes('help')" /> <headHelper v-if="$route.path.includes('help')" :userInfo="userInfo" />
<headerNavMobile v-else-if="$isMobile" :userInfo="userInfo" /> <headerNavMobile v-else-if="$isMobile" :userInfo="userInfo" />
<div <div
class="container w-full lg:w-3/4 flex items-center h-full justify-between m-auto" class="container w-full lg:w-3/4 flex items-center h-full justify-between m-auto"
......
<template> <template>
<div> <div>
<div class="top pt-3 pl-5 flex justify-between"> <div v-if="!$isMobile" class="top pt-3 pl-5 flex justify-between">
<div class="flex items-center gap-2 cursor-pointer" @click="goHelp"> <div class="flex items-center gap-2 cursor-pointer" @click="goHelp">
<img class="h-8" :src="Logo" alt="logo" /> <img class="h-8" src="../assets/logo.png" alt="logo" />
<h2 <h2
class="text-lg font-bold mt-2 border-l border-solid border-gray-300 pl-2"> class="text-lg font-bold mt-2 border-l border-solid border-gray-300 pl-2">
九猫ERP帮助中心 九猫ERP帮助中心
...@@ -52,12 +52,50 @@ ...@@ -52,12 +52,50 @@
<!-- <el-button plain class="mr-10 mb-2" size="medium">免费试用</el-button> --> <!-- <el-button plain class="mr-10 mb-2" size="medium">免费试用</el-button> -->
</div> </div>
</div> </div>
<div v-else class="top pt-3 px-5 flex items-center justify-between">
<div class="flex items-center gap-2 cursor-pointer" @click="goHelp">
<img class="h-8" src="../assets/jomall.png" alt="logo" />
<h2
class="text-sm font-semibold text-gray-700 mt-1 border-l border-solid border-gray-300 pl-2">
九猫ERP帮助中心
</h2>
</div>
<div class="flex items-center justify-center gap-2">
<div class="text-sm" v-if="!userInfo">
<span @click="login" class="border-r-2 border-solid border-gray-200">
登录
</span>
<span @click="register">注册</span>
</div>
<div class="text-sm flex items-center justify-center" v-else>
<span>{{ userInfo.companyName }}</span>
<span class="border-r border-solid border-gray-300 pr-2">欢迎您</span>
<el-popconfirm title="确定退出登录吗?" @confirm="logout">
<div class="ml-2" title="退出登录" slot="reference">
<Icon
icon="mdi:logout"
width="20"
height="20"
color="var(--primary-color)" />
</div>
</el-popconfirm>
</div>
<div @click="toggleShow">
<Icon
class="bg-primary-color rounded-full p-1"
icon="typcn:th-menu"
color="white"
width="25"
height="25" />
</div>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import { Icon } from '@iconify/vue2' import { Icon } from '@iconify/vue2'
import { mapMutations } from 'vuex' import { mapMutations } from 'vuex'
import Logo from '../assets/logo.png' import { menuList } from '../views/help/menuConfig'
export default { export default {
name: 'headHelper', name: 'headHelper',
...@@ -67,16 +105,19 @@ export default { ...@@ -67,16 +105,19 @@ export default {
components: { components: {
Icon, Icon,
}, },
props: {
userInfo: {
type: Object,
},
},
data() { data() {
return { return {
Logo,
navs: [ navs: [
{ {
name: '首页', name: '首页',
path: '/', path: '/',
}, },
], ],
userInfo: JSON.parse(localStorage.getItem('userInfo')),
} }
}, },
methods: { methods: {
...@@ -129,6 +170,9 @@ export default { ...@@ -129,6 +170,9 @@ export default {
// 刷新页面 // 刷新页面
window.location.reload() window.location.reload()
}, },
toggleShow() {
console.log(menuList, '???')
},
}, },
} }
</script> </script>
......
...@@ -26,7 +26,11 @@ ...@@ -26,7 +26,11 @@
style="width: 16px; height: 16px; vertical-align: middle" style="width: 16px; height: 16px; vertical-align: middle"
title="退出登录" title="退出登录"
slot="reference"> slot="reference">
<img src="../assets/images/logout.svg" /> <Icon
icon="mdi:logout"
width="20"
height="20"
color="var(--primary-color)" />
</div> </div>
</el-popconfirm> </el-popconfirm>
</div> </div>
...@@ -34,73 +38,12 @@ ...@@ -34,73 +38,12 @@
<div v-show="showing" class="header-nav-mobile-overlay"> <div v-show="showing" class="header-nav-mobile-overlay">
<div <div
class="header-nav-mobile-header flex items-center justify-between p-2.5"> class="header-nav-mobile-header flex items-center justify-between p-2.5">
<img src="../assets/logo.png" class="w-32" style="height: 40px" /> <img src="../assets/logo.png" class="w-32" />
<i <i
class="el-icon-close text-xl font-bold cursor-pointer" class="el-icon-close text-xl font-bold cursor-pointer"
@click="toggleShow"></i> @click="toggleShow" />
</div> </div>
<ul class="header-nav-mobile-items" @click.stop> <NavMenu :nav="nav" @item-click="toggleShow" />
<li
v-for="(r, i) in nav"
:key="i"
class="header-nav-mobile-item"
:class="{ active: isRouteActive(r) }">
<router-link
v-if="!r.children"
class="header-nav-mobile-link flex items-center justify-between"
:to="r.path"
@click.native="toggleShow(r)">
{{ r.name }}
</router-link>
<div
v-else
class="header-nav-mobile-link flex items-center justify-between">
<span>{{ r.name }}</span>
<i
:class="r.expanding ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
@click.stop="toggleExpand(r)"></i>
</div>
<div v-if="r.expanding" class="header-nav-mobile-child">
<div
class="header-nav-mobile-child-item"
v-for="(c, index) in r.children"
:class="{ active: isRouteActive(c) }"
:key="index">
<router-link
v-if="!c.children"
class="header-nav-mobile-link"
:to="c.path"
@click.native="toggleShow(c)">
{{ c.name }}
</router-link>
<div
v-else
class="header-nav-mobile-link flex items-center justify-between">
<span>{{ c.name }}</span>
<i
:class="
c.expanding ? 'el-icon-arrow-up' : 'el-icon-arrow-down'
"
@click.stop="toggleExpand(c)"></i>
</div>
<div v-if="c.expanding" class="header-nav-mobile-sub-child">
<div
class="header-nav-mobile-child-item"
v-for="(s, index2) in c.children"
:class="{ active: isRouteActive(s) }"
:key="index2">
<router-link
class="header-nav-mobile-link"
:to="s.path"
@click.native="toggleShow(s)">
{{ s.name }}
</router-link>
</div>
</div>
</div>
</div>
</li>
</ul>
</div> </div>
</transition> </transition>
</div> </div>
...@@ -108,11 +51,11 @@ ...@@ -108,11 +51,11 @@
<script> <script>
import { mapMutations } from 'vuex' import { mapMutations } from 'vuex'
import { Icon } from '@iconify/vue2' import { Icon } from '@iconify/vue2'
import NavMenu from './navMenu.vue'
import productionSvg from '../assets/images/home/production.svg' import productionSvg from '../assets/images/home/production.svg'
import customSvg from '../assets/images/home/custom.svg' import customSvg from '../assets/images/home/custom.svg'
import supplyChainSvg from '../assets/images/home/earth.svg' import supplyChainSvg from '../assets/images/home/earth.svg'
import logisticsSvg from '../assets/images/home/logistics.svg' import logisticsSvg from '../assets/images/home/logistics.svg'
import usSvg from '../assets/images/product/us.svg'
export default { export default {
name: 'headerNavMobile', name: 'headerNavMobile',
...@@ -121,6 +64,7 @@ export default { ...@@ -121,6 +64,7 @@ export default {
}, },
components: { components: {
Icon, Icon,
NavMenu,
}, },
data() { data() {
return { return {
...@@ -162,17 +106,8 @@ export default { ...@@ -162,17 +106,8 @@ export default {
{ name: '一件定制', path: 'https://jomalls.com/custom/' }, { name: '一件定制', path: 'https://jomalls.com/custom/' },
// { name: '案例', path: '/case' }, // { name: '案例', path: '/case' },
{ {
name: '客户服务', name: '关于我们',
path: '/about', path: '/about',
expanding: false,
children: [
{
name: '关于我们',
subTitle: '九猫ERP以精细化管理方案,帮助卖家实现业务增长',
path: '/about',
icon: usSvg,
},
],
}, },
{ name: '帮助', path: '/help' }, { name: '帮助', path: '/help' },
], ],
...@@ -186,17 +121,9 @@ export default { ...@@ -186,17 +121,9 @@ export default {
computed: {}, computed: {},
methods: { methods: {
...mapMutations(['setUserInfo']), ...mapMutations(['setUserInfo']),
toggleShow(r) { toggleShow() {
if (r && r.children) return
this.showing = !this.showing this.showing = !this.showing
}, },
toggleExpand(r) {
this.$set(r, 'expanding', !r.expanding)
},
isRouteActive(nav) {
const path = this.$route.path
if (nav.path === path) return true
},
async login() { async login() {
// 跳转到首页 // 跳转到首页
await this.$router.push('/home').catch(() => {}) await this.$router.push('/home').catch(() => {})
...@@ -316,89 +243,4 @@ export default { ...@@ -316,89 +243,4 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.header-nav-mobile-items {
box-sizing: border-box;
width: 100%;
height: 100%;
// background-color: #fff;
margin: 0;
padding: 20px 20px;
flex: 1;
overflow-y: auto;
}
.header-nav-mobile-item,
.header-nav-mobile-child {
list-style-type: none;
line-height: 50px;
letter-spacing: 4px;
&.active > .header-nav-mobile-link {
color: var(--primary-color);
}
}
.header-nav-mobile-child-item {
&.active > .header-nav-mobile-link {
color: var(--primary-color);
}
}
.header-nav-mobile-item.active {
.header-nav-mobile-link {
position: relative;
}
}
.header-nav-mobile-item {
font-size: 16px;
}
.header-nav-mobile-child {
font-size: 14px;
// color: #999;
background-color: #fffdf8;
padding: 0 20px;
margin-top: 10px;
}
.header-nav-mobile-sub-child {
margin-left: 20px;
& > .header-nav-mobile-child-item {
border-bottom: 1px solid var(--border-color);
}
}
.header-nav-mobile-child-item {
line-height: 36px;
}
.header-nav-mobile-children {
margin: 0;
padding: 0;
}
.header-nav-mobile-item > .header-nav-mobile-link {
display: block;
width: 100%;
height: 100%;
color: inherit;
text-decoration: none;
cursor: pointer;
border-bottom: solid 1px var(--border-color);
}
.header-nav-mobile-item > .header-nav-mobile-link {
display: flex;
.expand-icon {
margin-left: auto;
margin-right: 20px;
}
}
.header-nav-mobile-child > .header-nav-mobile-link {
padding-left: 10px;
&::after {
display: none !important;
}
}
</style> </style>
<template>
<div>
<ul class="header-nav-mobile-items" @click.stop>
<li
v-for="(r, i) in nav"
:key="i"
class="header-nav-mobile-item"
:class="{ active: isRouteActive(r) }">
<router-link
v-if="!r.children"
class="header-nav-mobile-link flex items-center justify-between"
:to="r.path"
@click.native="handleMenuClick(r)">
{{ r.name }}
</router-link>
<div
v-else
class="header-nav-mobile-link flex items-center justify-between">
<span>{{ r.name }}</span>
<i
:class="r.expanding ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
@click.stop="handleMenuClick(r)"></i>
</div>
<div v-if="r.expanding" class="header-nav-mobile-child">
<div
class="header-nav-mobile-child-item"
v-for="(c, index) in r.children"
:class="{ active: isRouteActive(c) }"
:key="index">
<router-link
v-if="!c.children"
class="header-nav-mobile-link"
:to="c.path"
@click.native="handleMenuClick(c)">
{{ c.name }}
</router-link>
<div
v-else
class="header-nav-mobile-link flex items-center justify-between">
<span>{{ c.name }}</span>
<i
:class="c.expanding ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
@click.stop="handleMenuClick(c)"></i>
</div>
<div v-if="c.expanding" class="header-nav-mobile-sub-child">
<div
class="header-nav-mobile-child-item"
v-for="(s, index2) in c.children"
:class="{ active: isRouteActive(s) }"
:key="index2">
<router-link
class="header-nav-mobile-link"
:to="s.path"
@click.native="handleMenuClick(s)">
{{ s.name }}
</router-link>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'NavMenu',
props: {
nav: {
type: Array,
required: true,
},
},
methods: {
handleMenuClick(item) {
// 如果菜单项有子节点,不关闭菜单(由组件内部处理展开/收起)
if (item.children && item.children.length > 0) {
return
}
// 叶子节点点击后关闭菜单
this.$emit('item-click')
},
isRouteActive(item) {
const path = this.$route.path
if (item.path === path) return true
// 检查子节点中是否有激活的路由
if (item.children) {
return item.children.some((child) => this.isRouteActive(child))
}
return false
},
},
}
</script>
<style scoped lang="scss">
.header-nav-mobile-items {
box-sizing: border-box;
width: 100%;
height: 100%;
// background-color: #fff;
margin: 0;
padding: 20px 20px;
flex: 1;
overflow-y: auto;
}
.header-nav-mobile-item,
.header-nav-mobile-child {
list-style-type: none;
line-height: 50px;
letter-spacing: 4px;
&.active > .header-nav-mobile-link {
color: var(--primary-color);
}
}
.header-nav-mobile-child-item {
&.active > .header-nav-mobile-link {
color: var(--primary-color);
}
}
.header-nav-mobile-item.active {
.header-nav-mobile-link {
position: relative;
}
}
.header-nav-mobile-item {
font-size: 16px;
}
.header-nav-mobile-child {
font-size: 14px;
// color: #999;
background-color: #fffdf8;
padding: 0 20px;
margin-top: 10px;
}
.header-nav-mobile-sub-child {
margin-left: 20px;
& > .header-nav-mobile-child-item {
border-bottom: 1px solid var(--border-color);
}
}
.header-nav-mobile-child-item {
line-height: 36px;
}
.header-nav-mobile-children {
margin: 0;
padding: 0;
}
.header-nav-mobile-item > .header-nav-mobile-link {
display: block;
width: 100%;
height: 100%;
color: inherit;
text-decoration: none;
cursor: pointer;
border-bottom: solid 1px var(--border-color);
}
.header-nav-mobile-item > .header-nav-mobile-link {
display: flex;
.expand-icon {
margin-left: auto;
margin-right: 20px;
}
}
.header-nav-mobile-child > .header-nav-mobile-link {
padding-left: 10px;
&::after {
display: none !important;
}
}
// 递归菜单组件样式补充
.header-nav-mobile-items {
.header-nav-mobile-item {
list-style-type: none;
line-height: 50px;
letter-spacing: 4px;
font-size: 16px;
&.active > .header-nav-mobile-link {
color: var(--primary-color);
}
> .header-nav-mobile-link {
display: block;
width: 100%;
height: 100%;
color: inherit;
text-decoration: none;
cursor: pointer;
border-bottom: solid 1px var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
}
.header-nav-mobile-child {
font-size: 14px;
background-color: #fffdf8;
padding: 0 20px;
margin-top: 10px;
.header-nav-mobile-child-item {
line-height: 36px;
border-bottom: 1px solid var(--border-color);
&.active > .header-nav-mobile-link {
color: var(--primary-color);
}
> .header-nav-mobile-link {
padding-left: 10px;
&::after {
display: none !important;
}
}
}
}
.header-nav-mobile-sub-child {
margin-left: 20px;
}
.recursive-menu-children {
list-style-type: none;
margin: 0;
padding: 0;
}
}
</style>
...@@ -615,7 +615,12 @@ export default { ...@@ -615,7 +615,12 @@ export default {
flex-direction: row-reverse; flex-direction: row-reverse;
} }
.home-module-item:nth-child(odd) { .home-module-item:nth-child(odd) {
background-color: var(--background-color); background-image: linear-gradient(
to bottom,
#ffffff00 1%,
var(--background-color),
#ffffff00 99%
);
} }
.home-module-item:not(:last-child) { .home-module-item:not(:last-child) {
......
...@@ -93,10 +93,11 @@ const routes = [ ...@@ -93,10 +93,11 @@ const routes = [
require(['../views/help/pages/index.vue'], resolve), require(['../views/help/pages/index.vue'], resolve),
}, },
{ {
path: 'beginner', path: 'picTutorial/:id',
name: 'HelpBeginner', name: 'PicTutorial',
component: (resolve) => component: (resolve) =>
require(['../views/help/pages/Beginner/beginner.vue'], resolve), require(['../views/help/components/picTutorial.vue'], resolve),
props: true,
}, },
{ {
path: 'artical1', path: 'artical1',
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="about-us"> <div class="about-us">
<div class="banner-container"> <div class="banner-container">
<div <div
class="flex justify-between lg:flex-row flex-col items-center h-96 w-full-70 w-full-90 mx-auto pt-5 overflow-hidden"> class="flex justify-between lg:flex-row flex-col items-center py-10 lg:py-0 lg:h-96 w-full-70 w-full-90 mx-auto pt-5 overflow-hidden">
<div class="left-content"> <div class="left-content">
<h3 <h3
class="banner-title font-semibold text-2xl lg:text-5xl text-center lg:text-left"> class="banner-title font-semibold text-2xl lg:text-5xl text-center lg:text-left">
...@@ -13,23 +13,20 @@ ...@@ -13,23 +13,20 @@
<span>以一站式跨境电商运营管理系统,助力卖家轻松实现业务增长</span> <span>以一站式跨境电商运营管理系统,助力卖家轻松实现业务增长</span>
</div> </div>
</div> </div>
<div class="map-container mt-5"> <div class="map-container mt-5 hidden lg:block" />
<img src="../../assets/images/about/world.png" alt="world" />
</div>
</div> </div>
</div> </div>
<div class="w-3/4 flex flex-col m-auto mt-20"> <div class="lg:w-3/4 w-11/12 flex flex-col m-auto lg:mt-20 mt-5">
<h2 class="text-center mt-10">品牌介绍</h2> <h2 class="text-center mt-10">品牌介绍</h2>
<div class="flex w-full justify-between gap-10"> <div
class="flex lg:flex-row flex-col w-full items-center lg:justify-between gap-10">
<div <div
data-aos="fade-right" data-aos="fade-right"
class="w-3/4 flex-col items-center h-full lg:items-start"> class="w-3/4 flex-col items-center h-full lg:items-start lg:text-sm text-xs font-light">
<div <div class="lg:text-lg mt-4 lg:mt-8 lg:leading-7 lg:mt-7">
class="text-textTitle text-sm font-light lg:text-lg mt-4 lg:mt-8 lg:leading-7 lg:mt-7">
九猫(西安)科技有限公司成立于2022年,致力于为企业出海提供降本提效的全域数智化一站式管理解决方案 九猫(西安)科技有限公司成立于2022年,致力于为企业出海提供降本提效的全域数智化一站式管理解决方案
</div> </div>
<div <div class="mt-3 lg:text-lg lg:mt-5 lg:leading-7">
class="mt-3 text-sm font-light text-textTitle lg:text-lg lg:mt-5 lg:leading-7">
<p class="mt-5"> <p class="mt-5">
九猫科技核心团队拥有超过7年的跨境电商ERP开发经验,设计及开发过的项目覆盖产品管理系统,订单管理系统,供应链系统,供应商系统,生产管理系统,仓库管理系统,营销系统,OA系统等等。 九猫科技核心团队拥有超过7年的跨境电商ERP开发经验,设计及开发过的项目覆盖产品管理系统,订单管理系统,供应链系统,供应商系统,生产管理系统,仓库管理系统,营销系统,OA系统等等。
</p> </p>
...@@ -40,7 +37,7 @@ ...@@ -40,7 +37,7 @@
</p> </p>
</div> </div>
</div> </div>
<div class="video-container w-1/2"> <div class="video-container lg:w-1/2 w-3/4">
<video <video
class="video flex justify-center items-center" class="video flex justify-center items-center"
src="../../assets/video/abount-jomalls2-video.mp4" src="../../assets/video/abount-jomalls2-video.mp4"
...@@ -48,11 +45,12 @@ ...@@ -48,11 +45,12 @@
</div> </div>
</div> </div>
</div> </div>
<div class="w-4/5 flex flex-col m-auto mt-20"> <div class="w-4/5 flex flex-col m-auto lg:mt-20 mt-10">
<h2 class="text-center">企业文化</h2> <h2 class="text-center">企业文化</h2>
<div class="flex justify-center flex-wrap mt-10 gap-20 cursor-default"> <div
class="flex justify-center flex-wrap mt-10 lg:gap-20 gap-5 cursor-default">
<div <div
class="culture-pic1 bg-center bg-cover w-80 h-56 overflow-hidden p-5 relative flex items-center justify-center"> class="culture-pic1 bg-center bg-cover lg:w-80 w-64 lg:h-56 h-40 overflow-hidden p-5 relative flex items-center justify-center">
<div <div
class="text-gray-200 text-2xl font-semibold absolute top-5 left-5"> class="text-gray-200 text-2xl font-semibold absolute top-5 left-5">
使命 使命
...@@ -62,7 +60,7 @@ ...@@ -62,7 +60,7 @@
</div> </div>
</div> </div>
<div <div
class="culture-pic2 bg-center bg-cover w-80 h-56 overflow-hidden p-5 relative flex items-center justify-center"> class="culture-pic2 bg-center bg-cover lg:w-80 w-64 lg:h-56 h-40 overflow-hidden p-5 relative flex items-center justify-center">
<div <div
class="text-gray-200 text-2xl font-semibold absolute top-5 left-5"> class="text-gray-200 text-2xl font-semibold absolute top-5 left-5">
愿景 愿景
...@@ -72,12 +70,12 @@ ...@@ -72,12 +70,12 @@
</div> </div>
</div> </div>
<div <div
class="culture-pic3 bg-center bg-cover w-80 h-56 overflow-hidden p-5 relative flex items-center justify-center"> class="culture-pic3 bg-center bg-cover lg:w-80 w-64 lg:h-56 h-40 overflow-hidden p-5 relative flex items-center justify-center">
<div <div
class="text-gray-200 text-2xl font-semibold absolute top-5 left-5"> class="text-gray-200 text-2xl font-semibold absolute top-5 left-5">
价值观 价值观
</div> </div>
<div class="text-gray-100 text-base text-center"> <div class="text-gray-100 lg:text-base text-sm text-center">
客户第一、诚实正直 客户第一、诚实正直
<br /> <br />
艰苦奋斗、敢于批评 艰苦奋斗、敢于批评
...@@ -87,7 +85,7 @@ ...@@ -87,7 +85,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="bg-colorBg w-full flex flex-col m-auto mt-20 py-10"> <div class="bg-colorBg-gradient w-full flex flex-col m-auto mt-20 py-10">
<h2 class="text-center">发展历程</h2> <h2 class="text-center">发展历程</h2>
<timeline /> <timeline />
</div> </div>
...@@ -113,11 +111,12 @@ export default { ...@@ -113,11 +111,12 @@ export default {
.map-container { .map-container {
width: 55%; width: 55%;
position: relative; position: relative;
img { background-image: url('../../assets/images/about/world.png');
filter: grayscale(100%) hue-rotate(10deg) saturate(800%) brightness(110%); background-size: contain;
width: 100%; background-position: center;
height: auto; background-repeat: no-repeat;
} filter: grayscale(100%) hue-rotate(10deg) saturate(800%) brightness(110%);
min-height: 500px; // 确保容器有足够的高度显示背景图
} }
h2 { h2 {
...@@ -204,5 +203,14 @@ $culture-pics: ( ...@@ -204,5 +203,14 @@ $culture-pics: (
border-right: none; border-right: none;
} }
} }
.map-container {
min-height: 50px;
}
h2 {
font-size: 24px;
margin: 0 auto 10px;
}
} }
</style> </style>
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
:class="{ 'timeline-dot-current': currentIndex === index }"></div> :class="{ 'timeline-dot-current': currentIndex === index }"></div>
<div <div
v-if="index !== timelineItems.length - 1" v-if="index !== timelineItems.length - 1"
class="timeline-line w-64 h-px"></div> class="timeline-line lg:w-64 w-20 h-px"></div>
</div> </div>
<div class="-ml-3 mt-2 text-gray-600 font-semibold text-base"> <div class="-ml-3 mt-2 text-gray-600 font-semibold text-base">
{{ item.title }} {{ item.title }}
...@@ -26,19 +26,21 @@ ...@@ -26,19 +26,21 @@
class="timeline-card-item" class="timeline-card-item"
ref="cardItems"> ref="cardItems">
<div <div
class="timeline-card p-10 h-80 w-104 shadow-xl rounded-lg cursor-pointer" class="timeline-card lg:p-10 p-6 lg:h-80 h-64 lg:w-96 w-80 shadow-xl rounded-lg cursor-pointer"
:class="{ 'timeline-card-current': currentIndex === index }" :class="{ 'timeline-card-current': currentIndex === index }"
@click="selectTime(index)"> @click="selectTime(index)">
<div class="w-full text-gray-600 font-semibold text-2xl"> <div class="w-full text-gray-600 font-semibold lg:text-2xl text-lg">
{{ item.title }} {{ item.title }} : {{ item.subtitle }}
</div> </div>
<div class="bg-gray-200 mt-3 h-px" /> <div class="bg-gray-200 mt-3 h-px" />
<el-timeline class="mt-5"> <el-timeline class="mt-8">
<el-timeline-item <el-timeline-item
v-for="(content, index) in item.content" v-for="(content, index) in item.content"
:key="index" :key="index"
color="var(--el-color-primary-light-3)"> color="var(--el-color-primary-light-3)">
{{ content }} <div class="text-gray-600 lg:text-base text-base">
{{ content }}
</div>
</el-timeline-item> </el-timeline-item>
</el-timeline> </el-timeline>
</div> </div>
...@@ -54,19 +56,31 @@ export default { ...@@ -54,19 +56,31 @@ export default {
timelineItems: [ timelineItems: [
{ {
title: '2022年', title: '2022年',
content: [], subtitle: '奠基与启航',
content: [
'公司于西安成立,以跨境电商与智能营销为核心,完成技术架构搭建,实现从0到1的突破。',
],
}, },
{ {
title: '2023年', title: '2023年',
content: [], subtitle: '拓展与深耕',
content: [
'业务规模快速扩大,通过优化供应链与丰富SaaS工具矩阵,提升了运营效率并获市场认可。',
],
}, },
{ {
title: '2024年', title: '2024年',
content: [], subtitle: '整合与赋能',
content: [
'战略转向生态整合,将核心能力产品化输出,成功从服务商转型为生态赋能者。',
],
}, },
{ {
title: '2025年', title: '2025年',
content: [], subtitle: '创新与跨越',
content: [
'建立美国柔性供应链积极拓展海外市场,推动品牌国际化,开启智能化与全球布局新阶段。',
],
}, },
], ],
currentIndex: 0, currentIndex: 0,
......
...@@ -8,7 +8,11 @@ ...@@ -8,7 +8,11 @@
<div class="user-info mt-2 flex items-center"> <div class="user-info mt-2 flex items-center">
<el-popconfirm title="确定退出登录吗?" @confirm="logout"> <el-popconfirm title="确定退出登录吗?" @confirm="logout">
<div class="logout" title="退出登录" slot="reference"> <div class="logout" title="退出登录" slot="reference">
<img src="../assets/images/logout.svg" style="width: 20px" /> <Icon
icon="mdi:logout"
width="20"
height="20"
color="var(--primary-color)" />
</div> </div>
</el-popconfirm> </el-popconfirm>
</div> </div>
......
<template>
<div>
<el-submenu
v-if="menuItem.children && menuItem.children.length > 0"
:index="String(menuItem.id)">
<template slot="title">
<span>{{ menuItem.name }}</span>
</template>
<menu-item
v-for="child in menuItem.children"
:key="child.id"
:menu-item="child" />
</el-submenu>
<el-menu-item
v-else
:index="
menuItem.url
? '/help/' + menuItem.path + '/' + menuItem.url
: '/help/' + menuItem.path
"
@click="handleMenuItemClick">
<span>{{ menuItem.name }}</span>
</el-menu-item>
</div>
</template>
<script>
import { menuList } from '../menuConfig'
export default {
name: 'MenuItem',
props: {
menuItem: {
type: Object,
required: true,
},
},
methods: {
handleMenuItemClick() {
if (this.menuItem.link) {
this.$router.push({
path: `/help/${this.menuItem.path}/${this.menuItem.url}`,
query: { url: this.menuItem.link },
})
}
const id = [...String(this.menuItem.id)].map(Number)
const result = []
let fullPath = ''
let current = menuList
id.forEach((index, i) => {
current = current?.[index - 1] || current?.children?.[index - 1]
if (i === id.length - 1 && current.url) {
fullPath = current.url
}
result.push({ name: current.name, path: fullPath || 'index' })
})
this.$store.dispatch('path/setCurrentPathNames', result)
},
},
}
</script>
<template> <template>
<div> <div>
<el-breadcrumb separator-class="el-icon-arrow-right"> <el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item <el-breadcrumb-item v-for="(item, index) in breadList" :key="item.id">
v-for="(item, index) in breadList" <a
:key="item.path" v-if="index === 0"
@click.native="handleBreadClick(index)"> href="javascript:void(0)"
<a href="javascript:void(0)">{{ item.name }}</a> @click="handleBreadClick(index)"
:class="{ 'breadcrumb-clickable': true }">
{{ item.name }}
</a>
<span v-else class="breadcrumb-disabled">{{ item.name }}</span>
</el-breadcrumb-item> </el-breadcrumb-item>
</el-breadcrumb> </el-breadcrumb>
</div> </div>
...@@ -15,7 +19,6 @@ export default { ...@@ -15,7 +19,6 @@ export default {
name: 'Bread', name: 'Bread',
computed: { computed: {
breadList() { breadList() {
// currentPathNames 已经包含了帮助中心作为第一项
return this.$store.getters['path/currentPathNames'] || [] return this.$store.getters['path/currentPathNames'] || []
}, },
}, },
...@@ -27,9 +30,31 @@ export default { ...@@ -27,9 +30,31 @@ export default {
const clickedItem = currentPathNames[index] const clickedItem = currentPathNames[index]
const newPathNames = currentPathNames.slice(0, index + 1) const newPathNames = currentPathNames.slice(0, index + 1)
this.$store.dispatch('path/setCurrentPathNames', newPathNames) this.$store.dispatch('path/setCurrentPathNames', newPathNames)
this.$router.push(`/help/${clickedItem.path}`)
// 如果是帮助中心,跳转到 /help/index
if (index === 0) {
this.$router.push('/help/index')
} else {
this.$router.push(`/help/${clickedItem.path}`)
}
} }
}, },
}, },
} }
</script> </script>
<style scoped>
.breadcrumb-clickable {
color: var(--primary-color);
cursor: pointer;
text-decoration: none;
}
.breadcrumb-clickable:hover {
color: var(--el-color-primary-light-4);
}
.breadcrumb-disabled {
color: #606266;
cursor: default;
}
</style>
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</div> </div>
<div class="tabs flex gap-5"> <div class="tabs flex gap-5">
<div <div
class="tab flex justify-center items-center text-gray-700 font-medium text-sm cursor-pointer" class="tab flex justify-center items-center text-gray-700 font-medium lg:text-sm text-xs cursor-pointer"
v-for="(sub, index) in tab.content" v-for="(sub, index) in tab.content"
@click="setCurrentTab(tabIndex, index)" @click="setCurrentTab(tabIndex, index)"
:key="sub.key" :key="sub.key"
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
{{ sub.subtitle }} {{ sub.subtitle }}
</div> </div>
</div> </div>
<div class="tab-content grid grid-cols-3 gap-x-10 gap-y-8 mt-5"> <div
class="tab-content lg:grid lg:grid-cols-3 gap-x-10 lg:gap-y-8 gap-2 mt-5 flex flex-col">
<div <div
v-for="c in tab.content[getCurrentTab(tabIndex)].articles" v-for="c in tab.content[getCurrentTab(tabIndex)].articles"
:key="c.article"> :key="c.article">
...@@ -92,15 +93,13 @@ export default { ...@@ -92,15 +93,13 @@ export default {
this.$router.push(content.url) this.$router.push(content.url)
}, },
goToMore(tab) { goToMore() {
const breadcrumbPath = [ // const breadcrumbPath = [
{ name: '帮助中心', path: 'index' }, // { name: '帮助中心', path: 'index' },
{ name: tab.title, path: tab.url }, // { name: tab.title, path: tab.url },
] // ]
// this.$store.dispatch('path/setCurrentPathNames', breadcrumbPath)
this.$store.dispatch('path/setCurrentPathNames', breadcrumbPath) // this.$router.push(`/help/${tab.url}`)
this.$router.push(`/help/${tab.url}`)
}, },
}, },
} }
...@@ -133,6 +132,13 @@ export default { ...@@ -133,6 +132,13 @@ export default {
} }
} }
@media (max-width: 1024px) {
.tab {
width: 80px;
height: 30px;
}
}
.content-title { .content-title {
position: relative; position: relative;
transition: all 0.2s ease; transition: all 0.2s ease;
......
<template>
<div style="height: 80vh">
<iframe :key="link" class="w-full h-full" frameborder="0" :src="link" />
</div>
</template>
<script>
import { FEISHU_BASE_URL } from '../menuConfig.js'
export default {
name: 'PicTutorial',
props: {
id: {
type: [String, Number],
required: true,
},
},
data() {
return {
isLoading: true,
}
},
computed: {
link() {
const anchor = this.$route.query.url || ''
if (!anchor) return ''
if (this.$route.name === 'PicTutorial') {
return FEISHU_BASE_URL + anchor
}
return ''
},
},
watch: {},
methods: {},
}
</script>
<style scoped></style>
<template> <template>
<div> <div>
<div class="top flex flex-col items-center py-16"> <div
<div class="text-gray-700 text-4xl font-bold">帮助中心</div> v-if="$route.path === '/help/index'"
class="top flex flex-col items-center lg:py-6 mb-3">
<div class="text-gray-700 lg:text-4xl text-2xl font-bold">帮助中心</div>
<el-input <el-input
v-model="keyword" v-model="keyword"
class="w-1/3 mt-5 search-input" class="lg:w-1/3 w-4/5 mt-5 search-input"
placeholder="请输入关键词查询..." placeholder="请输入关键词查询..."
@keyup.enter.native="search"> @keyup.enter.native="search">
<el-button slot="append" icon="el-icon-search" @click="search" /> <el-button slot="append" icon="el-icon-search" @click="search" />
</el-input> </el-input>
</div> </div>
<div class="content p-5"> <div class="content p-5">
<sideNav /> <sideNav v-if="!$isMobile" />
<div <div
class="right-content w-full h-full p-5" class="right-content w-full lg:p-5 p-0"
style="height: 90vh"
:class="{ 'rounded-md bg-white': $route.path !== '/help/index' }"> :class="{ 'rounded-md bg-white': $route.path !== '/help/index' }">
<Bread v-if="$route.path !== '/help/index'" /> <Bread v-if="$route.path !== '/help/index'" />
<router-view></router-view> <router-view></router-view>
......
<template>
<div class="w-full h-full bg-white rounded-md">
<div class="text-xl font-bold my-10">{{ title }}</div>
<div class="content">
<a
v-for="(t, index) in titles"
:key="t"
class="content-title text-gray-600 ml-8 block mb-3 pb-3 border-b border-gray-200"
@click="goArtical(t, index)"
:href="`/help/artical${index + 1}`">
{{ t }}
</a>
</div>
</div>
</template>
<script>
export default {
components: {},
data() {
return {
title: '',
titles: [],
}
},
created() {
const currentPathNames = this.$store.getters['path/currentPathNames']
this.title = currentPathNames[currentPathNames.length - 1].name
try {
const ctx = require.context('./', false, /\.vue$/)
ctx.keys().forEach((key) => {
if (/beginner\.vue$/i.test(key)) return
const mod = ctx(key)
const comp = mod && (mod.default || mod)
if (comp && typeof comp.data === 'function') {
const dataObj = comp.data.call({}) || {}
if (dataObj.title) {
this.titles.push(dataObj.title)
}
}
})
} catch (e) {
// ignore
}
},
methods: {
goArtical(title, index) {
// 调用 vuex action 添加文章路径
this.$store.dispatch('path/addArticlePath', { title, index })
},
},
}
</script>
<style scoped lang="scss">
.content-title {
position: relative;
transition: all 0.2s ease;
&::before {
content: '';
display: block;
width: 6px;
height: 6px;
border-radius: 50%;
position: absolute;
left: -23px;
top: 10px;
background-color: var(--primary-color);
box-shadow: 0 0 0 5px #e6c07977;
}
&:hover {
color: var(--primary-color);
}
}
</style>
<template> <template>
<div class="side-nav mr-5 rounded-md"> <div class="side-nav mr-5 rounded-md overflow-scroll">
<el-input <el-input
class="mt-3 ml-5 w-4/5 mb-5" class="mt-3 ml-5 w-4/5 mb-5"
v-model="searchKeyword" v-model="searchKeyword"
placeholder="在目录中搜索..."></el-input> placeholder="在目录中搜索..."></el-input>
<el-menu <el-menu
@select="handleSelect" router
:unique-opened="true" :unique-opened="true"
:default-active="activeMenu"> :default-active="$route.path"
<span v-for="item in menuList" :key="item.path"> :default-openeds="openedMenus">
<el-submenu <menu-item v-for="item in menuList" :key="item.id" :menu-item="item" />
v-if="item.children && item.children.length > 0"
:index="item.path">
<template slot="title">
<span>{{ item.name }}</span>
</template>
<el-menu-item
v-for="child in item.children"
:key="child.path"
:index="child.path">
<span>{{ child.name }}</span>
</el-menu-item>
</el-submenu>
<el-menu-item v-else :key="item.path" :index="item.path">
<span>{{ item.name }}</span>
</el-menu-item>
</span>
</el-menu> </el-menu>
</div> </div>
</template> </template>
<script> <script>
import MenuItem from './components/MenuItem.vue'
import { menuList } from './menuConfig.js'
export default { export default {
name: 'sideNav', name: 'sideNav',
components: {
MenuItem,
},
data() { data() {
return { return {
searchKeyword: '', searchKeyword: '',
activeMenu: '', menuList,
menuList: [
{
id: 1,
path: 'mustSee',
name: '入门必看',
children: [{ id: 11, path: 'beginner', name: '新手入门' }],
},
{
id: 2,
path: 'pic',
name: '图文教程',
children: [{ id: 21, path: 'base', name: '基础数据维护' }],
},
{ id: 3, path: 'video', name: '视频教程' },
// { id: 4, path: 'problem', name: '常见问题' },
// { id: 5, path: 'contact', name: '联系我们' },
],
} }
}, },
mounted() { computed: {
this.syncMenuWithRoute() // 需要展开的父级菜单
}, openedMenus() {
watch: { const currentPath = this.$route.path
$route() { // 递归查找匹配的菜单项及其父级菜单
this.syncMenuWithRoute() const findMenuItem = (items, parentIds = []) => {
}, for (const item of items) {
}, // 构建菜单项的完整路径(与 MenuItem.vue 中的逻辑保持一致)
methods: { let itemPath = ''
syncMenuWithRoute() { if (item.url) {
const path = this.$route && this.$route.path ? this.$route.path : '' // 如果有 url,路径格式为 /help/path/url
const match = path.match(/^\/help\/([^/]+)/) itemPath = item.path
const currentKey = match ? match[1] : '' ? `/help/${item.path}/${item.url}`
: `/help/${item.url}`
} else if (item.path) {
// 如果只有 path,路径格式为 /help/path
itemPath = `/help/${item.path}`
}
this.activeMenu = currentKey // 如果当前路径完全匹配
}, if (itemPath && itemPath === currentPath) {
handleSelect(key, keyPath) { return parentIds
if (key === this.activeMenu) return }
const names = [] // 如果有子菜单,递归查找
for (const item of this.menuList) { if (item.children && item.children.length > 0) {
if (item.path === keyPath[0]) { const newParentIds = [...parentIds, String(item.id)]
names.push({ name: item.name, path: item.path }) const result = findMenuItem(item.children, newParentIds)
if (keyPath[1] && Array.isArray(item.children)) { if (result !== null) {
for (const child of item.children) { return result
if (child.path === keyPath[1]) {
names.push({ name: child.name, path: child.path })
break
}
} }
} }
break
} }
return null
} }
// 使用 vuex 保存路径名称 const result = findMenuItem(this.menuList)
this.$store.dispatch('path/setCurrentPathNames', names) return result || []
const target = keyPath[1] || keyPath[0]
this.$router.push(`/help/${target}`)
}, },
}, },
} }
...@@ -102,8 +73,8 @@ export default { ...@@ -102,8 +73,8 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
.side-nav { .side-nav {
background-color: #ffffff; background-color: #ffffff;
height: 100%; height: 90vh;
width: 13%; width: 15%;
} }
::v-deep .el-input--mini .el-input__inner { ::v-deep .el-input--mini .el-input__inner {
background-color: var(--background-color); background-color: var(--background-color);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment