Commit 49a63db6 by Administrator

Merge branch 'hxh' into 'dev'

Hxh

See merge request !13
parents 93a266c5 201573a4
...@@ -2269,87 +2269,6 @@ ...@@ -2269,87 +2269,6 @@
"webpack-chain": "^6.4.0", "webpack-chain": "^6.4.0",
"webpack-dev-server": "^3.11.0", "webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2" "webpack-merge": "^4.2.2"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
}
} }
}, },
"@vue/cli-shared-utils": { "@vue/cli-shared-utils": {
...@@ -13264,6 +13183,87 @@ ...@@ -13264,6 +13183,87 @@
} }
} }
}, },
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-navigation": { "vue-navigation": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/vue-navigation/-/vue-navigation-1.1.4.tgz", "resolved": "https://registry.npmjs.org/vue-navigation/-/vue-navigation-1.1.4.tgz",
......
<template> <template>
<header class="header" :class="{ 'no-shadow': !shadow }"> <header class="header" :class="{ 'no-shadow': !shadow }">
<headerNavMobile v-if="$isMobile" :nav="navbar"></headerNavMobile> <headerNavMobile v-if="$isMobile" :nav="navbar" :userInfo="userInfo"></headerNavMobile>
<div class="container" v-else> <div class="container" v-else>
<div class="logo"> <div class="logo">
<span class="logo_text"> <span class="logo_text">
...@@ -15,27 +15,26 @@ ...@@ -15,27 +15,26 @@
v-for="item in navbar" v-for="item in navbar"
@click="changePath" @click="changePath"
:key="item.path"> :key="item.path">
<router-link :to="item.path">{{ item.name }}</router-link> <a :href="item.path">{{ item.name }}</a>
</li> </li>
</ul> </ul>
</nav> </nav>
<!-- <div class="user-info" v-if="userInfo">
<div class="user-msg">
<span class="user-name">{{ '小溪' }}</span>
<span>欢迎您</span>
</div>
<div class="logout" title="退出登录" @click="logout">
<img src="../assets/images/logout.png"/>
</div>
</div> -->
<div class="right_btn"> <div class="right_btn">
<!-- <el-button type="primary" size="mini" @click="login">登录</el-button> <!-- <el-button type="primary" size="mini" @click="login">登录</el-button>
<el-button size="mini" @click="register">注册</el-button> --> <el-button size="mini" @click="register">注册</el-button> -->
<div class="user-operate"> <div class="user-operate" v-if="!userInfo">
<span class="login-btn" @click="login">登录</span> <span class="login-btn" @click="login">登录</span>
<span class="reg-btn" @click="register">注册</span> <span class="reg-btn" @click="register">注册</span>
</div> </div>
<div class="user-info" v-else>
<div class="user-msg">
<span class="user-name">{{ userInfo.companyName }}</span>
<span>欢迎您</span>
</div>
<div class="logout" title="退出登录" @click="logout">
<img src="../assets/images/logout.png" />
</div>
</div>
<el-button type="primary" @click="freeTrial">免费试用</el-button> <el-button type="primary" @click="freeTrial">免费试用</el-button>
</div> </div>
</div> </div>
...@@ -43,7 +42,7 @@ ...@@ -43,7 +42,7 @@
</template> </template>
<script> <script>
import { mapMutations, mapState } from 'vuex' import { mapMutations } from 'vuex'
import headerNavMobile from './headerNavMobile.vue' import headerNavMobile from './headerNavMobile.vue'
export default { export default {
...@@ -61,21 +60,31 @@ export default { ...@@ -61,21 +60,31 @@ export default {
navbar: [ navbar: [
{ name: '首页', path: '/home' }, { name: '首页', path: '/home' },
{ name: '核心功能', path: '/function' }, { name: '核心功能', path: '/function' },
{ name: '价格', path: '/price' }, // { name: '价格', path: '/price' },
{ name: '需求痛点', path: '/demand_pain_point' }, { name: '需求痛点', path: '/demand_pain_point' },
{ name: '关于我们', path: '/about_us' }, { name: '关于我们', path: '/about_us' },
{ name: '帮助', path: '/help'}, { name: '一键定制', path: 'https://jomalls.com/custom/' },
{ name: '帮助', path: '/help' },
], ],
userInfo:JSON.parse(localStorage.getItem('userInfo'))
} }
}, },
computed: { computed: {
...mapState(['userInfo']), // ...mapState(['shopifyObj']),
active() { active() {
return this.$route.path return this.$route.path
}, },
}, },
mounted() {
if(this.$route.query.shopKey){
localStorage.setItem('shopifyObj', JSON.stringify(this.$route.query))
}
if(this.userInfo && this.$route.query.shopKey){
this.$router.push('/contact')
}
},
methods: { methods: {
...mapMutations(['setUserInfo']), ...mapMutations(['setUserInfo','setShopKey']),
changePath() { changePath() {
this.scrollParent().scrollTo({ this.scrollParent().scrollTo({
behavior: 'smooth', behavior: 'smooth',
...@@ -83,6 +92,9 @@ export default { ...@@ -83,6 +92,9 @@ export default {
}) })
}, },
login() { login() {
if(this.$route.query&&this.$route.query.shopKey){
this.setShopKey(this.$route.query.shopKey)
}
this.$router.push('/login') this.$router.push('/login')
}, },
register() { register() {
...@@ -108,6 +120,19 @@ export default { ...@@ -108,6 +120,19 @@ export default {
right: 0; right: 0;
left: 0; left: 0;
} }
.user-name {
margin-right: 10px;
}
.user-msg {
color: #fff;
}
.logout {
margin-right: 30px;
}
@media screen and (max-width: 1100px) { @media screen and (max-width: 1100px) {
.header { .header {
position: sticky; position: sticky;
...@@ -156,10 +181,6 @@ export default { ...@@ -156,10 +181,6 @@ export default {
margin-right: 50px; margin-right: 50px;
} }
.user-name {
margin-right: 10px;
}
.logout img { .logout img {
width: 20px; width: 20px;
vertical-align: middle; vertical-align: middle;
......
...@@ -6,11 +6,21 @@ ...@@ -6,11 +6,21 @@
<div class="header-nav-mobile_logo"> <div class="header-nav-mobile_logo">
<img src="../assets/logo.png" height="40px" /> <img src="../assets/logo.png" height="40px" />
</div> </div>
<div class="header-nav-mobile_login"> <div class="header-nav-mobile_login" v-if="!userInfo">
<span @click="login">登录</span> <span @click="login">登录</span>
<span style="margin: 0 5px">|</span> <span style="margin: 0 5px">|</span>
<span @click="register">注册</span> <span @click="register">注册</span>
</div> </div>
<div class="header-nav-mobile_user" v-else>
<span class="user-name">{{ userInfo.companyName }}</span>
<span style="margin: 0 10px">欢迎您</span>
<span style="margin: 0 5px">|</span>
<span style="margin-left: 10px;cursor: pointer;" @click="logout">
<img
style="width: 16px; height: 16px; vertical-align: middle"
src="../assets/images/logout.png" />
</span>
</div>
<transition name="header-nav-mobile"> <transition name="header-nav-mobile">
<div <div
v-show="showing" v-show="showing"
...@@ -35,6 +45,7 @@ ...@@ -35,6 +45,7 @@
</div> </div>
</template> </template>
<script> <script>
import { mapMutations } from 'vuex'
export default { export default {
name: 'headerNavMobile', name: 'headerNavMobile',
data() { data() {
...@@ -46,8 +57,14 @@ export default { ...@@ -46,8 +57,14 @@ export default {
nav: { nav: {
type: Array, type: Array,
}, },
userInfo: {
type: Object,
},
},
computed: {
}, },
methods: { methods: {
...mapMutations(['setUserInfo']),
toggleShow() { toggleShow() {
this.showing = !this.showing this.showing = !this.showing
}, },
...@@ -61,6 +78,11 @@ export default { ...@@ -61,6 +78,11 @@ export default {
register() { register() {
this.$router.push('/register') this.$router.push('/register')
}, },
logout() {
localStorage.removeItem('userInfo')
this.setUserInfo(undefined)
this.$router.push('/login')
},
}, },
} }
</script> </script>
...@@ -94,6 +116,14 @@ export default { ...@@ -94,6 +116,14 @@ export default {
justify-content: flex-end; justify-content: flex-end;
} }
.header-nav-mobile_user {
flex: 1;
display: flex;
font-size: 12px;
margin-right: 10px;
justify-content: flex-end;
}
.header-nav-mobile_trigger { .header-nav-mobile_trigger {
flex: 1; flex: 1;
} }
......
...@@ -57,6 +57,7 @@ import { ...@@ -57,6 +57,7 @@ import {
CascaderPanel, CascaderPanel,
Tag, Tag,
Scrollbar, Scrollbar,
RadioButton,
} from 'element-ui' } from 'element-ui'
Vue.prototype.$ELEMENT = { size: 'mini' } Vue.prototype.$ELEMENT = { size: 'mini' }
...@@ -91,7 +92,7 @@ Vue.use(Container) ...@@ -91,7 +92,7 @@ Vue.use(Container)
Vue.use(ButtonGroup) Vue.use(ButtonGroup)
Vue.use(Tag) Vue.use(Tag)
Vue.use(Scrollbar) Vue.use(Scrollbar)
Vue.use(RadioButton)
Vue.use(Cascader) Vue.use(Cascader)
Vue.prototype.$alert = MessageBox.alert Vue.prototype.$alert = MessageBox.alert
Vue.prototype.$message = (message) => Vue.prototype.$message = (message) =>
......
...@@ -70,10 +70,15 @@ const routes = [ ...@@ -70,10 +70,15 @@ const routes = [
component: (resolve) => require(['../views/authorization-failed'], resolve), component: (resolve) => require(['../views/authorization-failed'], resolve),
}, },
{ {
path: '/protocol', path: '/protocol/:type',
name: 'protocol', name: 'protocol',
component: (resolve) => require(['../views/protocol'], resolve), component: (resolve) => require(['../views/protocol'], resolve),
}, },
{
path: '/message',
name: 'message',
component: (resolve) => require(['../views/message'], resolve),
}
] ]
const router = new VueRouter({ const router = new VueRouter({
......
...@@ -7,10 +7,14 @@ export default new Vuex.Store({ ...@@ -7,10 +7,14 @@ export default new Vuex.Store({
}, },
state: { state: {
userInfo: JSON.parse(JSON.stringify(localStorage.getItem('userInfo'))) || undefined, userInfo: JSON.parse(JSON.stringify(localStorage.getItem('userInfo'))) || undefined,
shopifyObj:{}
}, },
mutations: { mutations: {
setUserInfo(state, profile) { setUserInfo(state, profile) {
state.userInfo = profile state.userInfo = profile
},
setShopKey(state,data){
state.shopifyObj = data
} }
}, },
actions: { actions: {
......
...@@ -2,49 +2,69 @@ ...@@ -2,49 +2,69 @@
<div class="login_bg"> <div class="login_bg">
<div class="contact-header"> <div class="contact-header">
<div class="header-image"> <div class="header-image">
<img src="../assets/logo.png" height="40px"/> <img src="../assets/logo.png" height="40px" />
</div> </div>
<!-- <div class="user-info"> <div class="user-info">
<div class="user-msg"> <!-- <div class="user-msg">
<span class="user-name">{{ '小溪' }}</span> <span class="user-name">{{ '小溪' }}</span>
<span>欢迎您</span> <span>欢迎您</span>
</div> </div> -->
<div class="logout" title="退出登录" @click="logout"> <div class="logout" title="退出登录" @click="logout">
<img src="../assets/images/logout.png" /> <img src="../assets/images/logout.png" />
</div> </div>
</div> --> </div>
</div> </div>
<div class="login_content"> <div class="login_content">
<div class="no-authority"> <div class="no-authority">
<div <div
style=" style="
text-align: center; text-align: center;
color: #fff; color: #fff;
font-size: 50px; font-size: 50px;
line-height: 100px; line-height: 100px;
font-family: '微软雅黑'; font-family: '微软雅黑';
" v-if="userInfo.erpKey"> "
<a :href="userInfo.erpKey+'.jomalls.com'" target="_blank" style="text-decoration: none"> {{userInfo.erpKey+'.jomalls.com'}}</a> v-if="userInfo && userInfo.erpKey">
<a
:href="`https://${userInfo && userInfo.erpKey}.jomalls.com`"
target="_blank"
style="text-decoration: none">
{{ `https://${userInfo && userInfo.erpKey}.jomalls.com` }}
</a>
</div> </div>
<h1 <h1
style=" style="
text-align: center; text-align: center;
color: #fff; color: #fff;
font-size: 50px; font-size: 50px;
line-height: 100px; line-height: 100px;
font-family: '微软雅黑'; font-family: '微软雅黑';
" v-else> "
v-else>
您尚未开通erp权限,请联系您的商务经理 您尚未开通erp权限,请联系您的商务经理
</h1> </h1>
<h2 style=" <h2
style="
text-align: center; text-align: center;
color: #fff; color: #fff;
font-size: 36px; font-size: 36px;
line-height: 100px; line-height: 100px;
font-family: '微软雅黑'; font-family: '微软雅黑';
">联系电话:15399065167</h2> ">
联系电话:18710915638
</h2>
<h2
style="
text-align: center;
color: #fff;
font-size: 36px;
line-height: 50px;
font-family: '微软雅黑';
">
邮箱:nina@jomalls.com
</h2>
<el-button <el-button
style=" style="
text-align: center; text-align: center;
font-size: 30px; font-size: 30px;
width: 160px; width: 160px;
...@@ -53,8 +73,8 @@ ...@@ -53,8 +73,8 @@
margin-top: 30px; margin-top: 30px;
border-radius: 15px; border-radius: 15px;
" "
type="success" type="success"
@click="goBack"> @click="goBack">
返回首页 返回首页
</el-button> </el-button>
</div> </div>
...@@ -64,27 +84,48 @@ ...@@ -64,27 +84,48 @@
</template> </template>
<script> <script>
import {mapState} from 'vuex' import { mapMutations, mapState } from 'vuex'
import { post } from '../utils/axios'
export default { export default {
name: 'contact', name: 'contact',
components: {}, components: {},
data() { data() {
return {} return {
userInfo: JSON.parse(localStorage.getItem('userInfo')),
shopifyObj: JSON.parse(localStorage.getItem('shopifyObj'))
}
}, },
computed: { computed: {
...mapState(['userInfo']), ...mapState(['shopifyObj']),
}, },
mounted() { mounted() {
console.log(this.userInfo,123) console.log(this.shopifyObj);
if (this.userInfo && this.shopifyObj) {
this.getShopifyInfo()
}
}, },
methods: { methods: {
...mapMutations(['setUserInfo']),
goBack() { goBack() {
this.$router.push('/') this.$router.push('/')
}, },
getShopifyInfo() {
console.log(this.shopifyObj)
if (!this.shopifyObj.shopKey || !this.userInfo.erpKey) return
post('business/shop/bind', {
shopKey: this.shopifyObj.shopKey,
platform: this.shopifyObj.platform,
companyCode: this.userInfo.erpKey,
}).then((res) => {
console.log(res)
})
},
logout() { logout() {
localStorage.removeItem('userInfo')
this.setUserInfo(undefined)
this.$router.push('/login')
}, },
}, },
} }
</script> </script>
......
...@@ -12,35 +12,30 @@ ...@@ -12,35 +12,30 @@
</div> </div>
<div :class="$isMobile ? 'login-mobile' : ''"> <div :class="$isMobile ? 'login-mobile' : ''">
<div :class="$isMobile ? 'login-content-mobile' : 'login_content'"> <div :class="$isMobile ? 'login-content-mobile' : 'login_content'">
<h2 <el-radio-group v-model="labelPosition" class="radioGroup" size="small">
style=" <el-radio-button label="passwordLogin">密码登录</el-radio-button>
text-align: center; <el-radio-button label="verificationLogin">验证码登录</el-radio-button>
font-weight: 400; </el-radio-group>
color: #4a4c6d;
margin-bottom: 40px;
">
欢迎登录
</h2>
<el-form <el-form
size="medium" size="medium"
:model="ruleForm" :model="ruleForm"
:rules="rules" :rules="rules"
ref="ruleForm" ref="ruleForm"
class="login_form"> class="login_form">
<el-form-item prop="email"> <el-form-item v-if="labelPosition==='passwordLogin'" prop="email">
<el-input <el-input
prefix-icon="el-icon-message" prefix-icon="el-icon-message"
style="background: #fff" style="background: #fff"
v-model="ruleForm.email" v-model="ruleForm.email"
placeholder="Email"></el-input> placeholder="请输入手机号或者邮箱"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password" style="margin-bottom: 20px"> <el-form-item v-if="labelPosition==='passwordLogin'" prop="password" style="margin-bottom: 20px">
<el-input <el-input
:type="showPwd ? 'text' : 'password'" :type="showPwd ? 'text' : 'password'"
prefix-icon="el-icon-lock" prefix-icon="el-icon-lock"
style="background: #fff" style="background: #fff"
v-model="ruleForm.password" v-model="ruleForm.password"
placeholder="Password" placeholder="请输入密码"
@keyup.enter.native="submitForm"> @keyup.enter.native="submitForm">
<i <i
@click="showPwd = !showPwd" @click="showPwd = !showPwd"
...@@ -48,6 +43,52 @@ ...@@ -48,6 +43,52 @@
:class="{ eyes: true, open: !showPwd, close: showPwd }"></i> :class="{ eyes: true, open: !showPwd, close: showPwd }"></i>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item v-if="labelPosition==='verificationLogin'" prop="phone">
<el-input
prefix-icon="el-icon-phone"
style="background: #fff"
v-model="ruleForm.phone"
placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item v-if="labelPosition==='verificationLogin'" prop="verifyKey" label="">
<div style="display: flex; gap: 20px; margin-bottom: -10px;">
<div style="flex: 1">
<el-input
v-model="ruleForm.verifyKey"
prefix-icon="el-icon-postcard"
placeholder="请输入验证码,区分大小写">
</el-input>
</div>
<div @click="getVerifycode">
<img
style="width: 100px; height: 80%"
:src="VerifyUrl">
</img>
</div>
</div>
</el-form-item>
<el-form-item v-if="labelPosition==='verificationLogin'" prop="code" label="">
<div style="display: flex; gap: 20px">
<div style="flex: 1">
<el-input
v-model="ruleForm.code"
prefix-icon="el-icon-message"
placeholder="请输入短信验证码"></el-input>
</div>
<div>
<el-button
class="get-code-button"
style="width: 112px"
:disabled="getCodeDisabled"
:class="getCodeDisabled ? 'disabled' : 'code-btn'"
@click="verPhonecode">
{{
codeCountDown === 0 ? '获取验证码' : `${codeCountDown}秒`
}}
</el-button>
</div>
</div>
</el-form-item>
<div class="forget-password"> <div class="forget-password">
<span style="cursor: pointer" @click="forgetPassword"> <span style="cursor: pointer" @click="forgetPassword">
忘记密码? 忘记密码?
...@@ -71,9 +112,10 @@ ...@@ -71,9 +112,10 @@
<div class="forget-title">忘记密码</div> <div class="forget-title">忘记密码</div>
<el-form size="medium" :model="forgetForm" ref="forgetForm"> <el-form size="medium" :model="forgetForm" ref="forgetForm">
<el-form-item <el-form-item
v-if="labelPosition==='passwordLogin'"
prop="email" prop="email"
label="" label=""
:rules="[{ required: true, message: '请输入邮箱', type: 'email' }]"> :rules="[{ required: true, message: '请输入邮箱地址', type: 'email' }]">
<el-input <el-input
v-model="forgetForm.email" v-model="forgetForm.email"
prefix-icon="el-icon-postcard" prefix-icon="el-icon-postcard"
...@@ -81,6 +123,7 @@ ...@@ -81,6 +123,7 @@
placeholder="请输入邮箱"></el-input> placeholder="请输入邮箱"></el-input>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="labelPosition==='passwordLogin'"
prop="code" prop="code"
label="" label=""
:rules="[{ required: true, message: '请输入验证码' }]"> :rules="[{ required: true, message: '请输入验证码' }]">
...@@ -106,6 +149,63 @@ ...@@ -106,6 +149,63 @@
</div> </div>
</el-form-item> </el-form-item>
<el-form-item <el-form-item
v-if="labelPosition==='verificationLogin'"
prop="phone"
:rules="[{ required: true, message: '请输入手机号'}]">
<el-input
prefix-icon="el-icon-phone"
style="background: #fff"
v-model="forgetForm.phone"
placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item
v-if="labelPosition==='verificationLogin'"
prop="verifyKey"
label=""
:rules="[{ required: true, message: '请输入验证码'}]">
<div style="display: flex; gap: 20px; margin-bottom: -10px;">
<div style="flex: 1">
<el-input
v-model="forgetForm.verifyKey"
prefix-icon="el-icon-postcard"
placeholder="请输入验证码,区分大小写">
</el-input>
</div>
<div @click="getVerifycode">
<img
style="width: 100px; height: 80%"
:src="VerifyUrl">
</img>
</div>
</div>
</el-form-item>
<el-form-item
v-if="labelPosition==='verificationLogin'"
prop="code"
label=""
:rules="[{ required: true, message: '请输入短信验证码'}]">
<div style="display: flex; gap: 20px">
<div style="flex: 1">
<el-input
v-model="forgetForm.code"
prefix-icon="el-icon-message"
placeholder="请输入短信验证码"></el-input>
</div>
<div>
<el-button
class="get-code-button"
style="width: 112px"
:disabled="getCodeDisabled"
:class="getCodeDisabled ? 'disabled' : 'code-btn'"
@click="forgetPhonecode">
{{
codeCountDown === 0 ? '获取验证码' : `${codeCountDown}秒`
}}
</el-button>
</div>
</div>
</el-form-item>
<el-form-item
prop="password" prop="password"
:rules="[{ required: true, message: '请输入新密码' }]"> :rules="[{ required: true, message: '请输入新密码' }]">
<el-input <el-input
...@@ -173,7 +273,7 @@ ...@@ -173,7 +273,7 @@
<script> <script>
import { post, get } from '../utils/axios' import { post, get } from '../utils/axios'
import md5 from 'js-md5' import md5 from 'js-md5'
import { mapMutations } from 'vuex' import {mapMutations, mapState} from 'vuex'
export default { export default {
name: 'login', name: 'login',
components: {}, components: {},
...@@ -188,6 +288,8 @@ export default { ...@@ -188,6 +288,8 @@ export default {
callback() callback()
} }
}, },
VerifyUrl:'',
labelPosition: 'passwordLogin',
isShowModal: false, isShowModal: false,
ruleForm: { ruleForm: {
password: '', password: '',
...@@ -197,15 +299,18 @@ export default { ...@@ -197,15 +299,18 @@ export default {
codeCountDown: 0, codeCountDown: 0,
forgetForm: {}, forgetForm: {},
rules: { rules: {
email: [ email: [{ required: true, message: '请输入邮箱或手机号', trigger: 'blur' }],
{ required: true, message: '请输入邮箱', trigger: 'blur' }, password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ {
type: 'email', pattern: /^1[3,4,5,6,7,8,9][0-9]{9}$/,
message: '请输入正确的邮箱地址', message: "请输入正确手机号码",
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
}, }
], ],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
verifyKey: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
}, },
showPwd: false, showPwd: false,
showNewPwd: false, showNewPwd: false,
...@@ -217,6 +322,9 @@ export default { ...@@ -217,6 +322,9 @@ export default {
return this.codeCountDown > 0 return this.codeCountDown > 0
}, },
}, },
mounted(){
this.getVerifycode()
},
methods: { methods: {
...mapMutations(['setUserInfo']), ...mapMutations(['setUserInfo']),
async verCode() { async verCode() {
...@@ -245,7 +353,66 @@ export default { ...@@ -245,7 +353,66 @@ export default {
console.error(e) console.error(e)
} }
}, },
async verPhonecode(){
try {
await new Promise((resolve, reject) => {
this.$refs.ruleForm.validateField('phone', (m) => {
m ? reject() : resolve()
})
})
} catch {
return
}
try {
const res = await post('business/user/phonecode', {
account: this.ruleForm.phone,
verifyKey: this.verifyKeyTime,
verifyCode: this.ruleForm.verifyKey
})
this.codeCountDown = 60
this.timer = setInterval(() => {
this.codeCountDown--
if (this.codeCountDown <= 0) {
clearInterval(this.timer)
}
}, 1000)
this.$message.success(res.message)
} catch (e) {
this.getVerifycode()
console.error(e)
}
},
async forgetPhonecode(){
try {
await new Promise((resolve, reject) => {
this.$refs.forgetForm.validateField('phone', (m) => {
m ? reject() : resolve()
})
})
} catch {
return
}
try {
const res = await post('business/user/phonecode', {
account: this.forgetForm.phone,
verifyKey: this.verifyKeyTime,
verifyCode: this.forgetForm.verifyKey
})
this.codeCountDown = 60
this.timer = setInterval(() => {
this.codeCountDown--
if (this.codeCountDown <= 0) {
clearInterval(this.timer)
}
}, 1000)
this.$message.success(res.message)
} catch (e) {
this.getVerifycode()
console.error(e)
}
},
forgetPassword() { forgetPassword() {
this.getVerifycode()
this.isShowModal = true this.isShowModal = true
this.forgetForm = {} this.forgetForm = {}
this.codeCountDown = 0 this.codeCountDown = 0
...@@ -267,8 +434,8 @@ export default { ...@@ -267,8 +434,8 @@ export default {
const passwordHash = hash.hex() const passwordHash = hash.hex()
post('business/user/restPassword', { post('business/user/restPassword', {
password: passwordHash, password: passwordHash,
email: this.forgetForm.email, account: this.forgetForm.email ? this.forgetForm.email : this.forgetForm.phone,
code: this.forgetForm.code, code: this.forgetForm.code
}).then((res) => { }).then((res) => {
if (res.code === 200) { if (res.code === 200) {
this.$message.success('密码修改成功') this.$message.success('密码修改成功')
...@@ -283,15 +450,24 @@ export default { ...@@ -283,15 +450,24 @@ export default {
e.preventDefault() e.preventDefault()
this.$refs.ruleForm.validate((valid) => { this.$refs.ruleForm.validate((valid) => {
if (valid) { if (valid) {
const hash = md5.create() let parmes = {}
hash.update(this.ruleForm.password) if(this.ruleForm.password){
const hash = md5.create()
const passwordHash = hash.hex() hash.update(this.ruleForm.password)
const passwordHash = hash.hex()
parmes = {
account: this.ruleForm.email ? this.ruleForm.email : this.ruleForm.phone,
password: passwordHash,
}
}else{
parmes = {
account: this.ruleForm.email ? this.ruleForm.email : this.ruleForm.phone,
code: this.ruleForm.code
}
}
let url = `business/user/login` let url = `business/user/login`
post(url, { post(url, parmes).then((res) => {
email: this.ruleForm.email,
password: passwordHash,
}).then((res) => {
if (res.code === 200) { if (res.code === 200) {
localStorage.setItem('userInfo', JSON.stringify(res.data)) localStorage.setItem('userInfo', JSON.stringify(res.data))
this.setUserInfo(JSON.parse(JSON.stringify(res.data))) this.setUserInfo(JSON.parse(JSON.stringify(res.data)))
...@@ -302,6 +478,16 @@ export default { ...@@ -302,6 +478,16 @@ 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
}
})
}
}, },
} }
</script> </script>
...@@ -476,6 +662,12 @@ export default { ...@@ -476,6 +662,12 @@ export default {
.login-page::v-deep .el-input__inner::-ms-clear { .login-page::v-deep .el-input__inner::-ms-clear {
display: none; display: none;
} }
.radioGroup{
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
}
@media screen and (max-width: 1100px) { @media screen and (max-width: 1100px) {
.login-page { .login-page {
......
<template>
<div class="message">
<div>
<h1 class="code" v-if="code === '200'" style="color: green;font-weight: bold;"><span>{{ msg }}</span></h1>
<h1 class="code" v-if="code === '500'" style="color: red;font-weight: bold;"><span>{{ msg }}</span></h1>
</div>
</div>
</template>
<script>
export default {
name: 'message',
data() {
return {
code: '',
msg: '',
}
},
mounted() {
const { code, msg } = this.$route.query
if (code) {
this.code = code
}
if (msg) {
this.msg = msg
}
},
}
</script>
<style scoped>
.message {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
</style>
...@@ -67,6 +67,10 @@ export default { ...@@ -67,6 +67,10 @@ export default {
valueClass: 'fs-20 fw-b', valueClass: 'fs-20 fw-b',
}, },
{ {
label: '适用范围',
value: 'radius'
},
{
label: '收费方式', label: '收费方式',
value: (d) => { value: (d) => {
d = d.chargeType d = d.chargeType
...@@ -111,12 +115,34 @@ export default { ...@@ -111,12 +115,34 @@ export default {
prices: [ prices: [
{ {
name: 'shopify版',
chargeType: '一次性收费',
price: '10$',
radius: 'shopify',
accountsCount: '不限',
deploymentType: 'SaaS',
rechargeAmount: '0',//充值金额
featureCustomization: false, // 功能定制
permissionManage: true, // 权限管理
financialManage: true, // 财务管理
statisticalReport: true, // 统计报表
orderManage: true, // 订单管理
logisticsManage: true, // 物流管理
orderStorage: '180天', // 订单数据存储
logsRetainDays: '90天', // 操作日志查看天数
shopCount: 50, // 店铺数量
imageStorage: '4G', // 图片空间
trainingType: '线上培训', // 培训方式
exclusivePM: true, // 专属产品经理
},
{
name: '试用版', name: '试用版',
chargeType: ['免费3个月', '或3000单'], // 收费方式 chargeType: ['免费3个月', '或3000单'], // 收费方式
price: 0, // 价格 price: 0, // 价格
radius: 'other',
accountsCount: 10, // 账号数量 accountsCount: 10, // 账号数量
rechargeAmount: '赠送', // 充值金额 rechargeAmount: '0', // 充值金额
deploymentType: 'SaaS', // 部署方式 deploymentType: 'SaaS', // 部署方式
featureCustomization: false, // 功能定制 featureCustomization: false, // 功能定制
permissionManage: true, // 权限管理 permissionManage: true, // 权限管理
...@@ -136,6 +162,7 @@ export default { ...@@ -136,6 +162,7 @@ export default {
chargeType: '按单收费', // 收费方式 chargeType: '按单收费', // 收费方式
price: '0.2元/单', // 价格 price: '0.2元/单', // 价格
radius: 'other',
accountsCount: 100, // 账号数量 accountsCount: 100, // 账号数量
rechargeAmount: '首充10000元', // 充值金额 rechargeAmount: '首充10000元', // 充值金额
deploymentType: 'SaaS', // 部署方式 deploymentType: 'SaaS', // 部署方式
...@@ -158,6 +185,7 @@ export default { ...@@ -158,6 +185,7 @@ export default {
chargeType: '按单收费', // 收费方式 chargeType: '按单收费', // 收费方式
price: '0.16元/单', // 价格 price: '0.16元/单', // 价格
radius: 'other',
accountsCount: '不限', // 账号数量 accountsCount: '不限', // 账号数量
rechargeAmount: '首充30000元', // 充值金额 rechargeAmount: '首充30000元', // 充值金额
deploymentType: 'SaaS', // 部署方式 deploymentType: 'SaaS', // 部署方式
...@@ -180,6 +208,7 @@ export default { ...@@ -180,6 +208,7 @@ export default {
chargeType: '按月收费', // 收费方式 chargeType: '按月收费', // 收费方式
price: 9800, // 价格 price: 9800, // 价格
radius: 'other',
accountsCount: '不限', // 账号数量 accountsCount: '不限', // 账号数量
rechargeAmount: '季付', // 充值金额 rechargeAmount: '季付', // 充值金额
deploymentType: 'SaaS', // 部署方式 deploymentType: 'SaaS', // 部署方式
...@@ -202,6 +231,7 @@ export default { ...@@ -202,6 +231,7 @@ export default {
chargeType: '按月收费', // 收费方式 chargeType: '按月收费', // 收费方式
price: 29800, // 价格 price: 29800, // 价格
radius: 'other',
accountsCount: '不限', // 账号数量 accountsCount: '不限', // 账号数量
rechargeAmount: '季付', // 充值金额 rechargeAmount: '季付', // 充值金额
deploymentType: 'SaaS或阿里云独立部署', // 部署方式 deploymentType: 'SaaS或阿里云独立部署', // 部署方式
......
<template> <template>
<div class="page_main"> <div class="page_main">
<h4 class="title">前言</h4> <el-tabs type="card" v-model="activeName">
<p> <el-tab-pane name="term" label="九猫ERP条款与协议">
欢迎使用九猫科技(广州)有限公司 <h4 class="title">前言</h4>
(以下称“我们”)开发和运营的九猫ERP软件及服务! <p>
</p> 欢迎使用九猫科技(广州)有限公司
<p> (以下称“我们”)开发和运营的九猫ERP软件及服务!
九猫ERP </p>
软件供shopify、shopline、magento以及速卖通商城的卖家或者其从业人员使用,其结合了各种不同的工具,这将有助于您或者您代表的某个实体公司及其附属机构(以下合称为“您”)在shopify、shopline、magento以及速卖通等商城做出商业决策。 <p>
</p> 九猫ERP
<p> 软件供shopify、shopline、magento以及速卖通商城的卖家或者其从业人员使用,其结合了各种不同的工具,这将有助于您或者您代表的某个实体公司及其附属机构(以下合称为“您”)在shopify、shopline、magento以及速卖通等商城做出商业决策。
为使用我们的九猫ERP软件及服务,您应当阅读并遵守《九猫ERP使用条款与条件》(以下简称“本协议”)。请您务必审慎阅读、充分理解各条款内容。本协议通过点击“阅读并同意”,即视为您已阅读并同意本协议项下的所有条款。 </p>
<strong>本协议自您点击“阅读并同意”时起生效。</strong> <p>
</p> 为使用我们的九猫ERP软件及服务,您应当阅读并遵守《九猫ERP使用条款与条件》(以下简称“本协议”)。请您务必审慎阅读、充分理解各条款内容。本协议通过点击“阅读并同意”,即视为您已阅读并同意本协议项下的所有条款。
<ul> <strong>本协议自您点击“阅读并同意”时起生效。</strong>
<li> </p>
<p>1、适用范围</p>
<ul> <ul>
<li> <li>
1.1本协议适用于您下载(如有)、安装(如有)、注册、使用、登陆九猫ERP软件(以下简称“本软件”),以及适用本软件所订立本协议的人员,或您与我们直接签订个人合同的主体; <p>1、适用范围</p>
</li> <ul>
<li> <li>
2.2本协议最后更新时间为2021年8月24日。我们可能不断发布关于本软件的相关协议、规则、规范等内容,前述内容一经发布,即为本协议不可分割的组成部分,与其构成统一整体,您同样应当遵守。 1.1本协议适用于您下载(如有)、安装(如有)、注册、使用、登陆九猫ERP软件(以下简称“本软件”),以及适用本软件所订立本协议的人员,或您与我们直接签订个人合同的主体;
</li> </li>
</ul> <li>
</li> 2.2本协议最后更新时间为2021年8月24日。我们可能不断发布关于本软件的相关协议、规则、规范等内容,前述内容一经发布,即为本协议不可分割的组成部分,与其构成统一整体,您同样应当遵守。
<li> </li>
<p>2、关于服务</p> </ul>
<ul>
<li>2.1服务内容是指我们通过本软件向用户提供相关服务。</li>
<li>
2.2服务形式:您可能通过电脑以客户端、网页等形式使用本软件及服务,具体以我们提供的为准,我们会不断丰富您适用本软件及服务的终端、形式等。当您使用本软件及服务时,您应选择与您系统等相匹配的本软件版本,否则无法正常使用本软件及服务。您可以创建自己的用户帐户以使用本软件。我们将通过您的帐户授予您购买的服务范围的使用权限。
</li>
</ul>
</li>
<li>
<p>3、软件更新</p>
<ul>
<li>
3.1
为了改善用户体验、完善服务内容,九猫ERP将不断努力开发新的功能及服务,并为用户不定期提供软件更新(这些更新可能
会采取软件功能替换、强化、修改、去除,版本升级等形式)。
</li>
<li>
3.2
为了保证本软件及服务的安全性和功能的一致性,九猫ERP有权不向您特别通知而对软件进行更新,或者对软件的部分功能效果进行改变或限制。
</li>
<li>
3.3
本软件新版本发布后,旧的功能可能无法使用或改变了旧功能的操作方式和展现形式,九猫ERP不保证本软件的某个功能会一直保留存在。
</li>
<li>
3.4
本软件在版本升级或维护期间需要停止本服务。该行为属于正常的例行工作,用户理解并同意九猫ERP将会尽其商业和技术上的合理努力保障您在停止服务期间受到最小影响。但是,九猫ERP并不承担停止服务期间所造成的任何用户损失。
</li>
<li>
3.5
九猫ERP所合作的第三方服务商在未主动通知或未发布更新公告的情况下进行的更新操作包括但不限于数据更新、接口改动、标签模板修改等所造成本软件部分或全部功能不能及时有效运行并造成用户损失的情况,九猫ERP不对产生的影响负责。
</li>
</ul>
</li>
<li>
<p>4、权利与义务</p>
<ul>
<li>
4.1
九猫ERP的部分功能以及服务是以收费方式提供的,如用户使用收费服务,请遵守相关的条款。
</li>
<li>
4.2
九猫ERP可能根据实际需要对收费服务的收费标准、方式进行修改和变更,九猫ERP也可能会对部分免费服务开始收费。前述修改、
变更或开始收费前,九猫ERP将在相应服务页面进行通知或公告。如果用户不同意上述修改、变更或付费内容,则应停止使用该服务。
</li>
<li>
4.3
用户按约定自行续费后,本司有权利对用户的续费费用不进行提前退费或将费用结转至我司及其附属公司的其它软件或功能中。法律另有约定或本司另有其他约定的除外。
</li>
<li>
4.4
用户注册的九猫ERP账号及其子账号的所有权归本司所有,申请注册人本人完成申请注册手续后,仅获得本服务及本软件的使用权,
且该使用权仅属于注册用户本人以及用户下的子账号。被授权子账号使用者的任何违反本协议的行为将由注册用户本人承担所有责任。
同时,用户以及所属子账号不得赠与、借用、租用、转让或售卖九猫ERP账号。
</li>
<li>
4.5
用户以及用户所授权的子账号使用者有责任妥善保管注册账户信息及账户密码的安全,并需要对注册账户以及密码下的行为承担法律责任。用户同意在任何情况下不向他人透露账户及密码信息。当用户怀疑他人在使用您的账号时,用户应立即通知本司。
</li>
<li>
4.6
用户的九猫ERP账号如长期未登录并欠费达到一定时间,本司有权收回该账号,并保留向欠费用户通过法律途径追缴欠款的权利。
</li> </li>
<li> <li>
4.7 <p>2、关于服务</p>
用户理解并同意:本软件的某些和第三方接口对接的功能(如物流接口),可能会让第三方物流服务商知晓用户的信息,例如:收件人(买家)的地址,电子邮件,电话等信息;销售产品的图片和描述信息;订单及留言信息等;以上信息均为从第三方物流服务商处获取或传递。 <ul>
<li>2.1服务内容是指我们通过本软件向用户提供相关服务。</li>
<li>
2.2服务形式:您可能通过电脑以客户端、网页等形式使用本软件及服务,具体以我们提供的为准,我们会不断丰富您适用本软件及服务的终端、形式等。当您使用本软件及服务时,您应选择与您系统等相匹配的本软件版本,否则无法正常使用本软件及服务。您可以创建自己的用户帐户以使用本软件。我们将通过您的帐户授予您购买的服务范围的使用权限。
</li>
</ul>
</li> </li>
<li> <li>
<p> <p>3、软件更新</p>
4.8
用户在使用本软件及服务时,须自行承担如下来自本司不可掌控的风险内容,包括但不限于:
</p>
<ul> <ul>
<li> <li>
(1)由于不可抗拒因素可能引起的用户数据的丢失,泄露等风险; 3.1
为了改善用户体验、完善服务内容,九猫ERP将不断努力开发新的功能及服务,并为用户不定期提供软件更新(这些更新可能
会采取软件功能替换、强化、修改、去除,版本升级等形式)。
</li>
<li>
3.2
为了保证本软件及服务的安全性和功能的一致性,九猫ERP有权不向您特别通知而对软件进行更新,或者对软件的部分功能效果进行改变或限制。
</li> </li>
<li> <li>
(2)因用户使用本软件或要求提供特定服务时,本软件需要从第三方服务商处下载及同步数据,本司不保证通过第三方服务商提供服务及内容的安全性、准确性、有效性及其他不确定的风险,若由此引发的任何争议及损害,与本司无关,本司不承担任何责任; 3.3
本软件新版本发布后,旧的功能可能无法使用或改变了旧功能的操作方式和展现形式,九猫ERP不保证本软件的某个功能会一直保留存在。
</li> </li>
<li> <li>
(3)用户在使用本软件及服务的过程中,因操作不当造成业务数据错乱,丢失等而引发的任何损失,本司不承担任何责任。 3.4
<strong> 本软件在版本升级或维护期间需要停止本服务。该行为属于正常的例行工作,用户理解并同意九猫ERP将会尽其商业和技术上的合理努力保障您在停止服务期间受到最小影响。但是,九猫ERP并不承担停止服务期间所造成的任何用户损失。
如果我们发现或收到别人举报您有违反本协议约定,我们有权采取包括但不限于暂停、终止您使用本软件,追究法律责任等措施。 </li>
</strong> <li>
3.5
九猫ERP所合作的第三方服务商在未主动通知或未发布更新公告的情况下进行的更新操作包括但不限于数据更新、接口改动、标签模板修改等所造成本软件部分或全部功能不能及时有效运行并造成用户损失的情况,九猫ERP不对产生的影响负责。
</li> </li>
</ul> </ul>
</li> </li>
</ul>
</li>
<li>
<p>5、保密约定</p>
<ul>
<li>
您与我们双方对本协议内容以及对本协议过程执行情况予以保密,不得向第三方披露。您与我们双方互为保密资料的提供方和接受方,负有保密义务,承担保密责任。甲乙双方中任何一方未经对方书面同意不得向第三方公开和披露任何保密资料或以其他方式使用保密资料。您与我们也须促使各自代表不向第三方公开或披露任何保密资料或以其它方式使用保密资料。除非披露、公开或利用保密资料是双方从事或开展合作项目工作在通常情况下应承担的义务(包括双方今后依法律或合同应承担的义务)适当所需的。
</li>
</ul>
</li>
<li>
<p>6、保证与免责声明</p>
<ul>
<li> <li>
<p>6.1 相互保证 各方认可和保证:</p> <p>4、权利与义务</p>
<ul> <ul>
<li>(1) 签署本协议具有法律效力;</li>
<li> <li>
(2) 不会向对方转移任何恶意代码(由其它方向保证方传输的恶意代码除外)。 4.1
九猫ERP的部分功能以及服务是以收费方式提供的,如用户使用收费服务,请遵守相关的条款。
</li>
<li>
4.2
九猫ERP可能根据实际需要对收费服务的收费标准、方式进行修改和变更,九猫ERP也可能会对部分免费服务开始收费。前述修改、
变更或开始收费前,九猫ERP将在相应服务页面进行通知或公告。如果用户不同意上述修改、变更或付费内容,则应停止使用该服务。
</li>
<li>
4.3
用户按约定自行续费后,本司有权利对用户的续费费用不进行提前退费或将费用结转至我司及其附属公司的其它软件或功能中。法律另有约定或本司另有其他约定的除外。
</li>
<li>
4.4
用户注册的九猫ERP账号及其子账号的所有权归本司所有,申请注册人本人完成申请注册手续后,仅获得本服务及本软件的使用权,
且该使用权仅属于注册用户本人以及用户下的子账号。被授权子账号使用者的任何违反本协议的行为将由注册用户本人承担所有责任。
同时,用户以及所属子账号不得赠与、借用、租用、转让或售卖九猫ERP账号。
</li>
<li>
4.5
用户以及用户所授权的子账号使用者有责任妥善保管注册账户信息及账户密码的安全,并需要对注册账户以及密码下的行为承担法律责任。用户同意在任何情况下不向他人透露账户及密码信息。当用户怀疑他人在使用您的账号时,用户应立即通知本司。
</li>
<li>
4.6
用户的九猫ERP账号如长期未登录并欠费达到一定时间,本司有权收回该账号,并保留向欠费用户通过法律途径追缴欠款的权利。
</li>
<li>
4.7
用户理解并同意:本软件的某些和第三方接口对接的功能(如物流接口),可能会让第三方物流服务商知晓用户的信息,例如:收件人(买家)的地址,电子邮件,电话等信息;销售产品的图片和描述信息;订单及留言信息等;以上信息均为从第三方物流服务商处获取或传递。
</li>
<li>
<p>
4.8
用户在使用本软件及服务时,须自行承担如下来自本司不可掌控的风险内容,包括但不限于:
</p>
<ul>
<li>
(1)由于不可抗拒因素可能引起的用户数据的丢失,泄露等风险;
</li>
<li>
(2)因用户使用本软件或要求提供特定服务时,本软件需要从第三方服务商处下载及同步数据,本司不保证通过第三方服务商提供服务及内容的安全性、准确性、有效性及其他不确定的风险,若由此引发的任何争议及损害,与本司无关,本司不承担任何责任;
</li>
<li>
(3)用户在使用本软件及服务的过程中,因操作不当造成业务数据错乱,丢失等而引发的任何损失,本司不承担任何责任。
<strong>
如果我们发现或收到别人举报您有违反本协议约定,我们有权采取包括但不限于暂停、终止您使用本软件,追究法律责任等措施。
</strong>
</li>
</ul>
</li> </li>
</ul> </ul>
</li> </li>
<li> <li>
<p>6.2 免责声明</p> <p>5、保密约定</p>
<ul> <ul>
<li> <li>
<strong> 您与我们双方对本协议内容以及对本协议过程执行情况予以保密,不得向第三方披露。您与我们双方互为保密资料的提供方和接受方,负有保密义务,承担保密责任。甲乙双方中任何一方未经对方书面同意不得向第三方公开和披露任何保密资料或以其他方式使用保密资料。您与我们也须促使各自代表不向第三方公开或披露任何保密资料或以其它方式使用保密资料。除非披露、公开或利用保密资料是双方从事或开展合作项目工作在通常情况下应承担的义务(包括双方今后依法律或合同应承担的义务)适当所需的。
(1) 由于您将用户密码告知他人或与他人共享注册帐户,由此导致的任何个人资料泄露。
</strong>
</li> </li>
</ul>
</li>
<li>
<p>6、保证与免责声明</p>
<ul>
<li> <li>
<strong> <p>6.1 相互保证 各方认可和保证:</p>
(2) 任何黑客政击、计算机病毒侵入或发作、政府部门管制和其他不可抗力等造成的个人资料泄露、丢失、被盗用或被窜改等。 <ul>
</strong> <li>(1) 签署本协议具有法律效力;</li>
<li>
(2)
不会向对方转移任何恶意代码(由其它方向保证方传输的恶意代码除外)。
</li>
</ul>
</li> </li>
<li> <li>
<strong> <p>6.2 免责声明</p>
(3) 因与本软件或我们的网站链接的其它网站造成个人资料泄露及由此而导致的任何法律争议和后果。 <ul>
</strong> <li>
<strong>
(1)
由于您将用户密码告知他人或与他人共享注册帐户,由此导致的任何个人资料泄露。
</strong>
</li>
<li>
<strong>
(2)
任何黑客政击、计算机病毒侵入或发作、政府部门管制和其他不可抗力等造成的个人资料泄露、丢失、被盗用或被窜改等。
</strong>
</li>
<li>
<strong>
(3)
因与本软件或我们的网站链接的其它网站造成个人资料泄露及由此而导致的任何法律争议和后果。
</strong>
</li>
</ul>
</li> </li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> <p style="text-align: center; margin-top: 30px; margin-bottom: 50px">
</ul> 本《协议》版权由九猫科技(广州)有限公司所有,保留一切解释权利。
<p style="text-align: center; margin-top: 30px; margin-bottom: 50px"> </p>
本《协议》版权由九猫科技(广州)有限公司所有,保留一切解释权利。 <div style="height: 10px"></div>
</p> </el-tab-pane>
<div style="height: 10px"></div> <el-tab-pane name="privacy" label="隐私协议">
<h4 class="title">前言</h4>
<p style="text-indent: 2em">
隐私权是每个人的重要权利,九猫科技(西安)有限公司(下称“我们”)非常重视用户个人信息和隐私的保护。在使用九猫科技(西安)有限公司的网站或
APP前,请您务必仔细阅读并透彻理解九猫科技(西安)有限公司《隐私政策》(下称“本隐私政策”、“本政策”)。我们希望通过本隐私政策向您说明我们在您使用九猫科技(西安)有限公司的产品与服务时如何收集、使用、保存、共享和转让这些信息,以及我们为您提供的访问、更新、删除和保护这些信息的方式。如果您是
18周岁以下的未成年人,您应确保您的监护人阅读并同意本政策后,您才使用并向我们提供您的个人信息。
</p>
<p>最近更新日期:2022 年 12月 1 日。</p>
<p>如果您有任何疑问、意见或建议,请通过以下联系方式与我们联系:</p>
<p>电子邮件:hjj@jomalls.com 电 话:15009153166</p>
<p style="font-weight: bold">【特别提示】</p>
<p style="text-indent: 2em">
为了更好保护您的个人信息,请在使用九猫科技(西安)有限公司的产品与服务前,仔细阅读并充分了解本政策。重点内容我们已采用粗体特别提示,希望您在阅读浏览时特别关注。一旦您使用或继续使用九猫科技(西安)有限公司产品与服务,即表示您同意我们按照本政策处理您的相关信息。对于我们所收集的您的个人信息,我们亦用粗体的方式进行了标示,以此向您增强式提示。一旦您同意提供您的个人信息,我们将按本政策所述的目的和方式处理您的个人信息。我们使用您的个人信息的目的是为了实现九猫科技(西安)有限公司的产品与服务相关的功能。您有权拒绝向我们提供个人信息,但是拒绝我们收集使用这些信息可能会影响您使用相关功能。
</p>
<p style="font-weight: bold; font-size: 20px">
一、我们如何收集和使用您的个人信息
</p>
<p style="text-indent: 2em">
个人信息是以电子或者其他方式记录的与已识别或者可识别的自然人有关的各种信息,不包括匿名化处理后的信息。本隐私政策中涉及的个人信息包括:个人身份信息(包括身份
证、护照、驾驶证、社保卡、居住证、家庭住址等)、个人财产信息(包括银行账号、资产证明信息、交易和消费记录等)、网络身份标识信息(包括系统账号、IP
地址、邮箱地址及与前述有关的密码、口令、口令保护答案等)、个人生物识别信息(指纹、面部识别特征等)、个人常用设备信息(包括硬件型号、设备
MAC 地址、操作系统类型、软件列表惟一设备识别码(如 IMEI/android
ID/IDFA/OPENUDID/GUID、SIM 卡 IMSI
信息等在内的描述个人常用设备基本情况的信息))、个人位置信息(包括行程信息、精准定位信息、住宿信息、经纬度等)。敏感个人信息是一旦泄露或者非法使用,容易导致自然人的人格尊严受到侵害或者人身、财产安全受到危害的个人信息,包括生物识别、宗教信仰、特定身份、医疗健康、金融账户、行踪轨迹等信息,以及不满十四周岁未成年人的个人信息。
我们仅会出于本政策以下目的,收集和使用您的个人信息:
</p>
<p style="font-weight: bold">
(一)您须授权我们收集和使用您个人信息的情形
</p>
<p style="font-weight: bold">
1、获取 九猫科技(西安)有限公司的产品与服务所需的功能
</p>
<p>(1)注册成为 九猫科技(西安)有限公司用户</p>
<p style="text-indent: 2em">
您注册成为
九猫科技(西安)有限公司用户时,您需要至少向我们提供您准备使用的
九猫科技(西安)有限公司账户名、密码、您本人的手机号码,我们将通过发送短信验证码的方式来验证您的身份是否有效。您的账户名为您的默认昵称,您可以修改补充您的昵称、性别、生日、兴趣爱好以及您的实名验证
相关信息,这些信息均属于您的“账户信息”。您补充的账户信息将有助于我们为您提供个
性化的服务推荐和更优的用户体验,但如果您不提供这些补充信息,不会影响您使用九猫科技(西安)有限公司的基本功能。
如您仅使用浏览、搜索等基本服务,您不需要注册成为九猫科技(西安)有限公司用户以及提供上述信息。
</p>
<p>(2)产品与服务信息展示和搜索</p>
<p style="text-indent: 2em">
为了让您快速地找到您所需要的产品与服务,我们可能会在应用启动或后台运行时收集您使用我们的产品与服务的设备信息(包括设备名称和型号、设备识别码、操作系统和应用程序版本、分辨率、服务提供商网络
ID(PLMN)、Mac
地址)、浏览器类型等以便为您提供产品与服务展示的最优方式。我们也会为了不断改进和优化上述的功能来使用您的上述个人信息。
</p>
<p>(3)在九猫科技(西安)有限公司使用订单拉取功能</p>
<p style="text-indent: 2em">
我们将通过记录用户行为收集您的发单地址、送达地、行踪轨迹、时长信息。我们收集上述信息,是基于法律法规要求以及保护您的人身财产安全、依照平台规则处理用户纠纷之需要。
我们将使用您的订单信息来进行您的身份核验、确定交易、支付结算、为您查询订单以及提供客服咨询与售后服务;我们还会使用您的订单信息来判断您的交易是否存在异常以保护您的交易安全。
</p>
<p>(4)支付功能</p>
<p style="text-indent: 2em">
在您下单后,您可以选择九猫科技(西安)有限公司的关联方或与九猫科技(西安)有限公司合作的第三方支付机构(包括支付宝、微信支付等支付通道,以下称“支付机构”)所提供的支付服务,此时可能需要您提供银行卡卡号、有效期、银行预留手机号、持卡人姓名、持卡人身份证件、卡验证码信息,支付功能本身并不收集您的个人信息,但我们需要将您的九猫科技(西安)有限公司订单号与交易金额信息与这些支付机构共享以实现其确认您的支付指令并完成支付。“关联方”指一方现在或将来控制、受控制或与其处于共同控制下的任何公司、机构以及上述公司或机构的法定代表人。“控制”
是指直接或间接地拥有影响所提及公司管理的能力,无论是通过所有权、有投票权的股
份、合同或其他被人民法院认定的方式。
</p>
<p>(5)交付产品与服务功能</p>
<p style="text-indent: 2em">
我们会通过电话、邮件、短信等形式与您确认您购买的产品与服务的相关信息,并由实际服务提供方向您交付产品或提供服务。
</p>
<p>(6)客服与售后功能</p>
<p style="text-indent: 2em">
当您需要我们提供与您订单信息相关的客服与售后服务时,我们将会查询您的订单信息。因此,我们的电话客服和售后服务会使用您的账号信息和订单信息来对您进行身份核验。您有可能会在与我们的客服人员沟通时,提供原订单信息外的其他信息,如当您要求我们变更订单信息时。
</p>
<p>(7)改进我们的产品与服务所必须的功能</p>
<p style="text-indent: 2em">
为了提升用户体验和服务品质,我们可能会收集您的订单信息、浏览信息进行汇集和数据分析,以便可将您感兴趣的产品或服务信息展示给您;或在您搜索时向您展示您可能希望找到的商品;或与其他来源(包括第三方)的数据相匹配,从而改进我们的产品与服务。
</p>
<p>(8)产品业务功能所收集使用您的信息逐项列举</p>
<p style="text-indent: 2em">
在您注册为
九猫科技(西安)有限公司用户时,至少需要提供手机号并设置密码用以创建
九猫科技(西安)有限公司账号。
</p>
<p style="font-weight: bold">2、提供安全保障所必须的功能</p>
<p style="text-indent: 2em">
为提高您使用我们以及我们关联公司或合作伙伴提供的产品与服务时系统的安全性,更准确地预防钓鱼网站或
APP 欺诈、计算机病毒、网络攻击、网络侵入以及保护账户安全,
我们可能会通过了解您的浏览信息、订单信息、交易信息、设备应用安装列表、设备
MAC
地址等来综合判断您账户和交易风险、检测和防范安全事件,并可能会记录一些我们认为有风险的链接(“URL”);我们也会收集您的设备信息对于九猫科技(西安)有限公司系统问题进行分析、统计流量并排查可能存在的风险并依法采取必要的记录、审计、分析、处置措施。
</p>
<p style="font-weight: bold">3、其他</p>
<p style="text-indent: 2em">
为给您带来更好的产品服务体验,我们会持续努力改进我们的产品及服务,因此可能需要收集、使用新的个人信息或变更个人信息使用目的或方式。如发生上述情形,我们将通过更新本政策、页面提示等方式另行向您说明,在征得您的同意后再开始收集、使用。
</p>
<p>(二)无需征得您授权同意可收集、使用您个人信息的情形</p>
<p style="text-indent: 2em">
根据相关法律法规、监管要求及国家标准,在以下情形中,我们可以在不征得您的授权同意情况下收集、使用一些必要的个人信息:
</p>
<p>(1)与我们履行法律法规规定的义务相关的;</p>
<p>(2)与国家安全、国防安全直接相关的;</p>
<p>(3)与公共安全、公共卫生、重大公共利益直接相关的;</p>
<p>(4)与犯罪侦查、起诉、审判和判决执行等直接相关的;</p>
<p>
(5)出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
</p>
<p>(6)所涉及的个人信息是您自行向社会公众公开的;</p>
<p>(7)根据您与我们签订和履行合同所必需的;</p>
<p>
(8)从合法公开披露的信息中收集到您的个人信息,如从合法的新闻报道、政府信息公开等渠道;
</p>
<p>
(9)用于维护我们产品与服务的安全稳定运行所必需的,例如发现、处置产品与服务故障;
</p>
<p>
(10)从合法公开披露的信息中收集个人信息的,如合法的新闻报道、政府信息公开等渠道;
</p>
<p>
(11)出于公共利益开展统计或学术研究所必需,且对外提供学术研究或描述的结果时,
对结果中所包含的个人信息进行去标识化处理的;
</p>
<p>(12)法律法规规定的其他情形。</p>
<p>(三)您可选择是否授权我们收集和使用您的个人信息的情形</p>
<p style="text-indent: 2em">
1、为提升用户体验,使九猫科技(西安)有限公司的产品与服务更人性化,我们的以下附加功能中可能会收集和使用您的个人信息。如果您不提供这些个人信息,您依然可以使用九猫科技(西安)有限公司的其他产品与服务,这些附加功能包括:
</p>
<p>
(1)基于位置信息的个性化推荐功能:我们会收集您的位置信息(我们仅收集您当时所处的地理位置,但不会将您各时段的位置信息进行结合以判断您的行踪轨迹)来判断您所处的地点,自动为您推荐您所在区域可以购买的产品与服务。
</p>
<p style="text-indent: 2em">
2、需要使用到您的银行卡信息(例如银行卡号)的场景,主要包括:您申请赔付时,需
要提供您银行卡信息才能支付给您赔偿金;您使用钱包业务中的提现功能时或您进行支付时,需要绑定您的银行卡才能完成提现或支付;您本人作为合作方与我们合作时,需要提供您的银行卡信息才能完成结算。您了解并同意我们基于上述场景使用您的银行卡信息,
如您不提供该信息,可能无法完成支付、提现、结算等。
</p>
<p style="text-indent: 2em">
3、上述第 1
项附加功能可能需要您在您的设备中向我们开启您的地理位置(位置信
息)、相机(摄像头)、相册(图片库)、麦克风以及通讯录的访问权限,以实现这些功
能所涉及的信息的收集和使用。您可以在通过设置找到应用程序详情,点击进入权限查看找到您上述权限开启的状态,并可以决定将这些权限随时开启或关闭。
</p>
<p>(四)我们从第三方获得您个人信息</p>
<p style="text-indent: 2em">
我们可能会在您的授权同意范围内从第三方(我们的合作方)处收集并使用您的个人信
息。我们会将依据与第三方的约定并对个人信息来源的合法性进行确认后,在符合相关法律法规前提下,使用您的这些个人信息,同时请您详细阅读该第三方的隐私政策及用户协议。如您拒绝第三方在提供服务时收集、使用或者传递您的个人信息,将可能导致您无法使用九猫科技(西安)有限公司对应的产品与服务。
</p>
<p>(五)您个人信息使用的规则</p>
<p style="text-indent: 2em">
1、我们会根据本隐私政策的约定并为实现我们的产品与服务功能对所收集的个人信息进行使用。当我们要将您的个人信息用于本政策未载明的其它用途时,会通过事先征求您的授权同意。
</p>
<p style="text-indent: 2em">
2、在收集您的个人信息后,在我们对您的个人信息进行去标识化处理,去标识化处理的信息将无法识别主体。请您注意,在此情况下我们有权使用已经去标识化的信息,在不透漏您个人信息的前提下,我们可对去标识化处理后的用户数据库进行分析并予以商业化的利用。
</p>
<p style="text-indent: 2em">
3、请您注意,您在使用我们的产品与服务时,除非您删除或通过系统设置拒绝我们收集,否则将在您使用我们的产品与服务期间将持续授权我们使用。
</p>
<p style="text-indent: 2em">
4、我们会对我们的产品与服务使用情况进行统计,并可能会与公众或第三方共享这些统计信息,以展示我们的产品与服务的整体使用趋势。但这些统计信息不包含您的任何身份识别信息。
</p>
<p style="text-indent: 2em">
5、如果我们发生合并、收购或破产清算可能涉及到个人信息转让时,我们会要求新的持
有您个人信息的公司、组织继续受本政策的约束。
</p>
<p style="font-weight: bold; font-size: 20px">
二、我们如何使用 Cookie 技术
</p>
<p style="text-indent: 2em">
为确保网站或 APP 正常运转,我们会在您的计算机或移动设备上储存名为
Cookie 的小数据文件。Cookie
通常包含标识符、站点名称以及一些号码和字符。借助于 Cookie,网站或 APP
能够储存您的偏好数据。我们不会将 Cookie 用于本政策所述目的之外的任何用
途。您可根据自己的偏好管理或删除 Cookie。有关详情,请参见
AboutCookies.org。您可以清除计算机上保存的所有
Cookie,大部分网络浏览器都设有阻止 Cookie
的功能。但如果您这么做,则需要在每一次访问我们的网站或 APP
时更改用户设置。
</p>
<p style="font-weight: bold; font-size: 20px">
三、我们如何共享、转让、公开披露您的个人信息
</p>
<p>(一)共享</p>
<p style="text-indent: 2em">
1、我们可能会向合作伙伴等第三方共享您的订单信息、账户信息、设备信息以及位置信息,以保障为您提供的产品与服务顺利完成。但我们仅会出于合法、正当、必要、特定、明确的目的共享您的个人信息,并且只会共享提供服务所必要的个人信息。我们的合作伙伴无权将共享的个人信息用于任何其他用途。
</p>
<p style="text-indent: 2em">
2、除上述第 1
种情况外,我们不会与任何公司、组织和个人共享您的个人信息,但以下情况除外:
</p>
<p>
(1)事先获得您的明确授权或同意:获得您的明确同意后,我们会与其他方共享您的个人信息;
</p>
<p>
(2)在法定情形下的共享:根据适用的法律法规、法律程序、诉讼/仲裁、政府的强制命
令、监管要求而需共享您的个人信息;
</p>
<p>
(3)在法律要求或允许的范围内,为了保护您或社会公众的利益、财产或安全免遭损害
而有必要提供您的个人信息给第三方(含消费者权益保护部门等行业组织);
</p>
<p>
(4)为了保护国家安全、公共安全以及您和其他个人的重大合法权益而需要共享您的个人信息;
</p>
<p>(5)您自行公开的或者我们能从其他合法公开渠道获取到您的个人信息。</p>
<p>(二)转让</p>
<p style="text-indent: 2em">
我们不会将您的个人信息转让给任何公司、组织或个人,除非发生下列情况:
</p>
<p>(1)事先获得您的明确同意;</p>
<p>
(2)根据所适用的法律法规、行业规定、法律程序要求、诉讼/仲裁、政府的强制命令、监管要求所必须要求提供的;
</p>
<p>
(3)为了保护国家安全、公共安全以及您和其他个人的重大合法权益而需要转让您的个人信息;
</p>
<p>(4)您自行公开的或者我们能从其他合法公开渠道获取到您的个人信息。</p>
<p style="text-indent: 2em">
如果发生合并、收购或破产清算,将可能涉及到个人信息转让,此种情况下我们会要求新的持有您个人信息的公司、组织继续受本政策的约束。如果本政策中约定的个人信息的收集、处理方式发生任何改变,该公司、组织将重新向您征求授权同意。
</p>
<p>(三)公开披露</p>
<p style="text-indent: 2em">
除非获取您的明确同意,我们不会公开披露您的个人信息。基于法律、法律程序、诉讼或政府主管部门强制性要求的情况下,为了保护国家安全、公共安全以及您和其他个人的重大合法权益,我们可能会向有权机关或公众披露您的个人信息。但我们保证,在上述情况发生时,我们会要求披露请求方必须出具与之相应的有效法律文件,并对被披露的信息采取符合法律和业界标准的安全防护措施。
</p>
<p style="font-weight: bold; font-size: 20px">
四、我们如何储存和保护您的个人信息
</p>
<p>(一)您个人信息的储存</p>
<p style="text-indent: 2em">
1、您的个人信息将全被储存于中华人民共和国境内,储存位置包括九猫科技(西安)有限公司及其关联公司的服务器,或九猫科技(西安)有限公司委托机构的服务器。我们会采取合理可行的措施,尽力避免收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非法律
有强制的存留要求。例如《中华人民共和国电子商务法》要求商品和服务信息、交易信息保存时间自交易完成之日起不少于三年。而我们判断前述期限的标准包括:
</p>
<p>
(1)完成与您相关的交易目的、维护相关交易及业务记录、应对可能的查询或投诉;
</p>
<p>(2)保证我们为您提供的服务安全及质量;</p>
<p>(3)您是否同意更长的留存期限;</p>
<p>(4)是否存在保留期限的其他特别约定。</p>
<p style="text-indent: 2em">
请您注意,在您的个人信息超出保留期间后,我们会根据适用法律的要求删除您的个人信息或匿名化处理;此外,在注销账户后,我们将停止为您提供产品和服务,并根据您的要求,删除您的个人信息或匿名化处理,法律法规另有规定的除外。
</p>
<p style="text-indent: 2em">
2、我们在中华人民共和国境内运营中收集和产生的个人信息,存储在中国境内,部分场
景需要将您的个人信息传输至境外:
</p>
<p>(1)适用的法律有明确规定;</p>
<p>(2)获得您的明确授权;</p>
<p>(3)您通过互联网进行跨境交易等个人主动行为。</p>
<p style="text-indent: 2em">
针对以上情形,我们会确保依据本隐私权政策对您的个人信息提供足够的保护。
如您使用跨境交易服务,且需要向境外传输您的个人信息完成交易的,我们会单独征得您的授权同意并要求接收方按照我们的说明、本隐私政策以及其他任何相关的保密和安全措施来处理这些个人信息。
</p>
<p>(二)我们保护您个人信息的技术与措施</p>
<p style="text-indent: 2em">
我们非常重视个人信息安全,并采取一切合理可行的措施,保护您的个人信息:
</p>
<p>1、数据安全技术措施</p>
<p style="text-indent: 2em">
我们会采用符合业界标准的安全防护措施,包括建立合理的制度规范、安全技术来防止您的个人信息遭到未经授权的访问、公开披露、使用、修改,避免数据的损坏或丢失。
九猫科技(西安)有限公司的网络服务采取了传输层安全协议等加密技术,通过
https 等方式提供浏览服务, 确保用户数据在传输过程中的安全。
九猫科技(西安)有限公司采取加密技术对用户个人信息进行加密保存,并通过隔离技术进行隔离。
在个人信息使用时,例如个人信息展示、个人信息关联计算,我们会采用包括内容替换、
SHA256 和 FPE 在内多种数据脱敏技术增强个人信息在使用中安全性。
九猫科技(西安)有限公司采用严格的数据访问权限控制和多因素身份认证技术以及数据防泄漏技术保护个人信息,避免数据被违规使用。
九猫科技(西安)有限公司采用代码安全自动检查、数据访问日志分析、系统访问权限审计、数据访问流量审计技术进行个人信息安全审计
</p>
<p>2、九猫科技(西安)有限公司为保护个人信息采取的其他安全措施</p>
<p style="text-indent: 2em">
九猫科技(西安)有限公司通过建立数据分类分级制度、数据安全管理规范、个人信息保护与合规总则、用户信息安全展示规范、安全开发规范、代码发布规范来管理规范个人信息的储存和使用。
九猫科技(西安)有限公司通过信息接触者保密协议、监控和审计机制来对数据进行全面安全控制。
九猫科技(西安)有限公司建立信息安全部并下设信息安全保护专职部门、数据安全应急响应中心来推进和保障个人信息安全。
安全认证和服务。
加强安全意识。我们还会定期举报信息安全意识和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。
</p>
<p>
3、我们仅允许有必要知晓这些信息的九猫科技(西安)有限公司及九猫科技(西安)有限公司关联方的员工、合作伙伴访问个人信息,并为此设置了严格的访问权限控制和监控机制。我们同时要求可能接触到您个人信息的所有人员履行相应的保密义务。如果未能履行这些义务,可能会被追究法律责任或被中止与九猫科技(西安)有限公司的合作关系。
</p>
<p>
4、我们会采取一切合理可行的措施,确保未收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非需要延长保留期或受到法律的允许。
</p>
<p>
5、九猫科技(西安)有限公司的网站或
APP、产品、或服务中可能含有到其他网站或 APP
的链接,我们提醒您,九猫科技(西安)有限公司对其他网站或 APP
的隐私保护措施无法做出承诺和保证。但是,我们网站或 APP
的页面有显著的“九猫科技(西安)有限公司”标记,您可以据此判断是否跳转至外部链接。
</p>
<p>
6、互联网并非绝对安全的环境,而且电子邮件、即时通讯、社交软件等与其他用户的交流方式无法确定是否完全加密,我们建议您使用此类工具时请使用8位以上复杂密码,并注意保护您的个人信息安全。
</p>
<p>
7、互联网环境并非百分之百安全,我们将尽力确保或担保您发送给我们的任何信息的安全性。如果我们的物理、技术、或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改、或毁坏,导致您的合法权益受损,我们将承担相应的法律责任。
</p>
<p>
8、在不幸发生个人信息安全事件后,我们将按照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。我们同时将及时将事件相关情况以邮件、信函、电话、推送通知等方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。
</p>
<p style="font-weight: bold; font-size: 20px">
五、您如何管理您的个人信息
</p>
<p style="text-indent: 2em">
九猫科技(西安)有限公司非常重视您对个人信息的关注,并尽全力保护您对于您个人信息访问、更正、删除以及撤回同意的权利,以使您拥有充分的能力保障您的隐私和安全。您的权利包括:
</p>
<p style="font-weight: bold">1、访问和更正您的个人信息</p>
<p style="text-indent: 2em">
您有权访问和更正您的个人信息,法律法规规定的例外情况除外。如果您想行使数据访问权,可以通过以下方式自行访问:
</p>
<p>
(1)您的账户信息:您可以在“个人中心”页面的“我的资料”菜单中查阅您提交给九猫科技(西安)有限公司的所有个人信息。
</p>
<p>
(2)您的订单信息:您可以通过访问“订单”菜单查看您的所有已经完成、待付款或待售后的订单。
</p>
<p>
(3)您的浏览信息:您可以访问或清除您的搜索历史记录、查看和修改兴趣以及管理其他数据。请通过访问浏览器历史记录进行查看。
</p>
<p>
(4)对于您在使用我们的产品与服务过程中产生的其他个人信息需要访问或更正,请随时联系我们。我们会根据本隐私政策所列明的方式和期限响应您的请求。
</p>
<p>
(5)您无法访问和更正的个人信息:除上述列明的信息外,您的部分个人信息我们还无法为您提供访问和更正的服务,这些信息主要是为了提升您的用户体验和保证交易安全所收集的您的设备信息、您使用附加功能时产生的个人信息。上述信息我们会在您的授权范围内进行使用,您无法访问和更正,但您可联系我们进行删除或做匿名化处理。
</p>
<p style="font-weight: bold">2、删除您的个人信息</p>
<p style="text-indent: 2em">
您在我们的产品与服务页面中可以直接清除或删除的信息,包括订单信息、浏览信息、收
货地址信息;
</p>
<p>在以下情形中,您可以向我们提出删除个人信息的请求:</p>
<P>(1)如果我们处理个人信息的行为违反法律法规;</P>
<p>(2)如果我们收集、使用您的个人信息,却未征得您的同意;</p>
<p>(3)如果我们处理个人信息的行为违反了与您的约定;</p>
<p>(4)如果您不再使用我们的产品与服务,或您注销了账号;</p>
<p>(5)如果我们不再为您提供我们的产品与服务。</p>
<p style="text-indent: 2em">
若我们决定响应您的删除请求,我们还将同时通知从我们获得您的个人信息的实体,要求其及时删除,除非法律法规另有规定,或这些实体获得您的独立授权。当您从我们的服务中删除信息后,因为适用的法律要求或安全技术原因,我们可能无法立即从备份系统中删除相应的信息,但会在备份更新时删除这些信息或实现匿名。
</p>
<p>3、注销账户</p>
<p style="text-indent: 2em">
您可以在我们的官网中直接申请注销账户。您注销账户后,我们将停止为您提供产品与服务,并依据您的要求,除法律法规另有规定外,我们将删除您的个人信息。
</p>
<p>4、关于个性化服务</p>
<p style="text-indent: 2em">
我们提供个性化服务,个性化推荐选项或通过本政策公示的联系方式联系我们。
</p>
<p>5、响应您的请求</p>
<p style="text-indent: 2em">
为了保障安全,我们可能需要您提供书面请求,或以其他方式证明您的身份,我们将在收到您反馈并验证您的身份后的
30
天内答复您的请求。对于您合理的请求,我们原则上不收取费用,但对多次重复、超出合理限度的请求,我们将视情收取一定成本费用。对于那些无端重复、需要过多技术手段(例如,需要开发新系统或从根本上改变现行惯例)、给他人合法权益带来风险或者非常不切实际(例如,涉及备份磁带上存放的信息)的请求,我们可能会予以拒绝。
</p>
<p>在以下情形中,按照法律法规要求,我们将无法响应您的请求:</p>
<p>(1)与国家安全、国防安全有关的;</p>
<p>(2)与公共安全、公共卫生、重大公共利益有关的;</p>
<p>(3)与犯罪侦查、起诉和审判和判决执行等有关的;</p>
<p>(4)有充分证据表明您存在主观恶意或滥用权利的;</p>
<p>
(5)响应您的请求将导致您或其他个人、组织的合法权益受到严重损害的;
</p>
<p>(6)涉及商业秘密的。</p>
<p style="font-size: 20px; font-weight: bold">
六、我们如何保护未成年人的个人信息
</p>
<p style="text-indent: 2em">
1、九猫科技(西安)有限公司非常重视对未成年人个人信息的保护。若您是 18
周岁以下的未成年人,在使用我们的产品与服务前,应事先取得您父母或法定监护人的书面同意。九猫科技(西安)有限公司根据国家相关法律法规的规定保护未成年人的个人信息。
</p>
<p style="text-indent: 2em">
2、对于经父母或法定监护人同意而收集未成年人个人信息的情况,我们只会在受到法律
允许、父母或监护人明确同意或者保护未成年人所必要的情况下使用或公开披露此信息。
</p>
<p style="text-indent: 2em">
3、如果我们发现自己在未事先获得可证实的父母或法定监护人同意的情况下收集了未成年人的个人信息,则会设法尽快删除相关数据。
</p>
<p style="text-indent: 2em">
4、如您是 14
周岁以下的儿童,我们依照本政策保护未成年人信息的同时,还将按照《儿
童个人信息网络保护规定》等相关规定,对 14
周岁以下儿童的个人信息进行保护。
</p>
<p style="font-weight: bold; font-size: 20px">七、本政策如何更新</p>
<p style="text-indent: 2em">
1、我们的隐私政策可能变更。但未经您明确同意,我们不会削减您依据本隐私政策所应享有的权利。当本政策发生变更时,我们会在九猫科技(西安)有限公司网站、九猫科技(西安)有限公司系统上提前以公告、弹窗或以其他适当方式向您展示变更后的政策。未经您同意,我们不会限制您按照政策所应享有的相关权利。
</p>
<p style="text-indent: 2em">
2、对于重大变更,我们还会提供更为显著的通知(我们会通过包括但不限于邮件、短信或在浏览页面做特别提示等方式,说明隐私政策的具体变更内容)。
</p>
<p>本政策所指的重大变更包括但不限于:</p>
<p>
(1)我们的服务模式发生重大变化。如处理个人信息的目的、处理的个人信息类型、个人信息的使用方式等;
</p>
<p>
(2)我们在所有权结构、组织架构等方面发生重大变化。如业务调整、破产并购等引起的所有者变更等;
</p>
<p>(3)个人信息共享、转让或公开披露的主要对象发生变化;</p>
<p>(4)您参与个人信息处理方面的权利及其行使方式发生重大变化;</p>
<p>
(5)我们负责处理个人信息安全的责任部门、联络方式及投诉渠道发生变化时;
</p>
<p>(6)个人信息安全影响评估报告表明存在高风险时。</p>
<p style="text-indent: 2em">
3、请您注意,只有在获取您的同意后,我们才会按照更新后的政策收集、使用、处理和储存您的个人信息。您可以选择不同意,我们向您提供以「访客」身份进行浏览的功能,
但这可能导
</p>
<p style="text-indent: 2em">
4、我们还会将本政策的旧版本存档,您可通过本政策公示的联系方式与我们取得联系查
阅旧版本隐私政策。
</p>
<p style="font-weight: bold; font-size: 20px">八、特别声明</p>
<p style="text-indent: 2em">
谷歌账号广告权限仅限拉取您个人的广告账号花费,九猫不会以任何形式索取您的谷歌账号;用户可以填写到商户名称、授权用户、授权类型、账户ID、开发者令牌、购物网站、客服邮箱、客服电话、公司名称、商家地址信息来绑定对应的广告账户,从而在九猫ERP去统一管理谷歌的广告账号。</p>
<p style="text-indent: 2em">Jomalls ERP使用和向任何其他应用程序传输从 Google API 接收的信息时,将遵守<a href="https://developers.google.com/terms/api-services-user-data-policy">《Google API 服务用户数据政策》</a>,包括有限使用要求。</p>
<p style="text-indent: 2em"><a href="https://console.cloud.google.com/">Google 云控制台-</a></p>
<p style="text-indent: 2em">点击了解谷歌如何帮助用户安全地共享其数据-<a href="https://policies.google.cn/">https://policies.google.cn/</a></p>
<p style="font-weight: bold; font-size: 20px">九、如何联系我们</p>
<p>
1、如您对本隐私政策有任何疑问、意见或建议,请通过以下方式与我们联系:
</p>
<p>电话: 15009153166</p>
<p>邮箱:hjj@jomalls.com</p>
<p>
2、我们设有个人信息保护专职部门,并配有个人信息保护专员和未成年人信息保护专
员,您可以通过以下方式与其系:
</p>
<p>电话:15289287385</p>
<p>邮箱:nina@jomalls.com</p>
<p>
3、一般情况下,我们将在十五天内回复。如果您对我们的回复不满意,特别是我们的个人信息处理行为损害了您的合法权益,您还可以向网信、公安及市场监督等监管部门进行投诉或举报
</p>
<p>注:本政策将于 2022 年 12月 1 日正式生效。</p>
</el-tab-pane>
</el-tabs>
</div> </div>
</template> </template>
<script> <script>
export default {} export default {
data() {
return {
activeName: 'term',
}
},
mounted() {
const { type } = this.$route.params
if (type) {
this.activeName = type
}
},
}
</script> </script>
<style scoped> <style scoped>
.page_main { .page_main {
max-width: 1280px; height: 100%;
margin: 0 auto; }
padding: 0 15px;
.el-tabs {
height: 100%;
display: flex;
flex-direction: column;
}
.el-tabs::v-deep .el-tabs__content {
flex: 1;
overflow-y: auto;
}
.el-tabs::v-deep .el-tab-pane {
padding: 0 20px;
} }
.title { .title {
/* text-align: center; */ /* text-align: center; */
margin-top: 50px;
margin-bottom: 10px; margin-bottom: 10px;
} }
p, p,
......
...@@ -13,25 +13,29 @@ ...@@ -13,25 +13,29 @@
<h2 style="text-align: center; font-weight: 400; color: #4a4c6d"> <h2 style="text-align: center; font-weight: 400; color: #4a4c6d">
用户注册 用户注册
</h2> </h2>
<el-radio-group v-model="labelPosition" class="radioGroup" size="small" @change="clickChange">
<el-radio-button label="mailbox">邮箱注册</el-radio-button>
<el-radio-button label="phone">手机号注册</el-radio-button>
</el-radio-group>
<el-form <el-form
size="medium" size="medium"
:model="registerForm" :model="registerForm"
:rules="rules" :rules="rules"
ref="registerForm" ref="registerForm"
class="login_form"> class="login_form">
<el-form-item prop="email" label=""> <el-form-item v-if="labelPosition==='mailbox'" prop="email" label="">
<el-input <el-input
v-model="registerForm.email" v-model="registerForm.email"
prefix-icon="el-icon-postcard" prefix-icon="el-icon-postcard"
placeholder="请输入邮箱"></el-input> placeholder="请输入邮箱"></el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code" label=""> <el-form-item v-if="labelPosition==='mailbox'" prop="code" label="">
<div style="display: flex; gap: 20px"> <div style="display: flex; gap: 20px">
<div style="flex: 1"> <div style="flex: 1">
<el-input <el-input
v-model="registerForm.code" v-model="registerForm.code"
prefix-icon="el-icon-message" prefix-icon="el-icon-message"
placeholder="请输入验证码"></el-input> placeholder="请输入邮箱验证码"></el-input>
</div> </div>
<div> <div>
<el-button <el-button
...@@ -47,6 +51,51 @@ ...@@ -47,6 +51,51 @@
</div> </div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item v-if="labelPosition==='phone'" prop="phone" label="">
<el-input
v-model="registerForm.phone"
prefix-icon="el-icon-phone"
placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item v-if="labelPosition==='phone'" prop="verifyKey" label="">
<div style="display: flex; gap: 20px; margin-bottom: -10px;">
<div style="flex: 1">
<el-input
v-model="registerForm.verifyKey"
prefix-icon="el-icon-postcard"
placeholder="请输入验证码,区分大小写">
</el-input>
</div>
<div @click="getVerifycode">
<img
style="width: 100px; height: 80%"
:src="VerifyUrl">
</img>
</div>
</div>
</el-form-item>
<el-form-item v-if="labelPosition==='phone'" prop="code" label="">
<div style="display: flex; gap: 20px">
<div style="flex: 1">
<el-input
v-model="registerForm.code"
prefix-icon="el-icon-message"
placeholder="请输入短信验证码"></el-input>
</div>
<div>
<el-button
class="get-code-button"
style="width: 112px"
:disabled="getCodeDisabled"
:class="getCodeDisabled ? 'disabled' : 'code-btn'"
@click="verPhonecode">
{{
codeCountDown === 0 ? '获取验证码' : `${codeCountDown}秒`
}}
</el-button>
</div>
</div>
</el-form-item>
<el-form-item prop="password" label=""> <el-form-item prop="password" label="">
<el-input <el-input
type="password" type="password"
...@@ -80,8 +129,12 @@ ...@@ -80,8 +129,12 @@
<el-checkbox v-model="isRead" label="" :indeterminate="false" /> <el-checkbox v-model="isRead" label="" :indeterminate="false" />
<span class="tos-link"> <span class="tos-link">
阅读并同意 阅读并同意
<a class="link" href="/protocol" target="_blank"> <a class="link" href="/protocol/term" target="_blank">
九猫ERP条款与协议 《九猫ERP条款与协议》
</a>
<span></span>
<a class="link" href="/protocol/privacy" target="_blank">
《隐私协议》
</a> </a>
</span> </span>
</div> </div>
...@@ -102,6 +155,7 @@ ...@@ -102,6 +155,7 @@
<script> <script>
import { get, post } from '../utils/axios' import { get, post } from '../utils/axios'
import md5 from 'js-md5' import md5 from 'js-md5'
import {mapState} from "vuex";
export default { export default {
name: 'register', name: 'register',
components: {}, components: {},
...@@ -116,6 +170,9 @@ export default { ...@@ -116,6 +170,9 @@ export default {
} }
} }
return { return {
VerifyUrl:'',
verifyKeyTime:'',
labelPosition: 'mailbox',
registerForm: {}, registerForm: {},
isRead: false, isRead: false,
agreeAnimate: false, agreeAnimate: false,
...@@ -129,7 +186,16 @@ export default { ...@@ -129,7 +186,16 @@ export default {
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
}, },
], ],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{
pattern: /^1[3,4,5,6,7,8,9][0-9]{9}$/,
message: "请输入正确手机号码",
trigger: ['blur', 'change'],
}
],
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }], code: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
verifyKey: [{ required: true, message: '请输入验证码', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
checkPass: [ checkPass: [
{ required: true, message: '请再次输入密码', trigger: 'blur' }, { required: true, message: '请再次输入密码', trigger: 'blur' },
...@@ -148,6 +214,9 @@ export default { ...@@ -148,6 +214,9 @@ export default {
return this.codeCountDown > 0 return this.codeCountDown > 0
}, },
}, },
mounted(){
this.getVerifycode()
},
methods: { methods: {
async verCode() { async verCode() {
try { try {
...@@ -161,7 +230,35 @@ export default { ...@@ -161,7 +230,35 @@ export default {
} }
try { try {
const res = await get('business/user/emailcode', { const res = await get('business/user/emailcode', {
email: this.registerForm.email, email: this.registerForm.email
})
this.codeCountDown = 60
this.timer = setInterval(() => {
this.codeCountDown--
if (this.codeCountDown <= 0) {
clearInterval(this.timer)
}
}, 1000)
this.$message.success(res.message)
} catch (e) {
console.error(e)
}
},
async verPhonecode(){
try {
await new Promise((resolve, reject) => {
this.$refs.registerForm.validateField('phone', (m) => {
m ? reject() : resolve()
})
})
} catch {
return
}
try {
const res = await post('business/user/phonecode', {
account: this.registerForm.phone,
verifyKey: this.verifyKeyTime,
verifyCode: this.registerForm.verifyKey
}) })
this.codeCountDown = 60 this.codeCountDown = 60
this.timer = setInterval(() => { this.timer = setInterval(() => {
...@@ -172,6 +269,7 @@ export default { ...@@ -172,6 +269,7 @@ export default {
}, 1000) }, 1000)
this.$message.success(res.message) this.$message.success(res.message)
} catch (e) { } catch (e) {
this.getVerifycode()
console.error(e) console.error(e)
} }
}, },
...@@ -185,7 +283,7 @@ export default { ...@@ -185,7 +283,7 @@ export default {
}, 700) }, 700)
return return
} }
const { code, companyName, email, job, password } = this.registerForm const { code, companyName, email, job, password, phone, verifyKey } = this.registerForm
const hash = md5.create() const hash = md5.create()
hash.update(password) hash.update(password)
...@@ -196,6 +294,7 @@ export default { ...@@ -196,6 +294,7 @@ export default {
email: email, email: email,
job: job, job: job,
password: passwordHash, password: passwordHash,
account: email ? email : phone
}).then((res) => { }).then((res) => {
this.$message.success(res.message) this.$message.success(res.message)
if (res.code === 200) { if (res.code === 200) {
...@@ -206,6 +305,19 @@ export default { ...@@ -206,6 +305,19 @@ 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
}
})
},
clickChange(lab){
this.registerForm = {}
}
}, },
} }
</script> </script>
...@@ -308,6 +420,12 @@ export default { ...@@ -308,6 +420,12 @@ export default {
top: 7%; top: 7%;
left: 8%; left: 8%;
} }
.radioGroup{
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
}
@media screen and (max-width: 1100px) { @media screen and (max-width: 1100px) {
.login_bg { .login_bg {
......
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