This commit is contained in:
小鱼开发
2025-06-23 18:17:28 +08:00
commit fbeccda5a0
108 changed files with 40963 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+5
View File
@@ -0,0 +1,5 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
+20302
View File
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- 移动端适配:禁止缩放并固定初始比例 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
<meta name="format-detection" content="telephone=yes" />
<title>平安好车补</title>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
+2579
View File
File diff suppressed because it is too large Load Diff
+26
View File
@@ -0,0 +1,26 @@
{
"name": "pinganbroker",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@vant/area-data": "^2.0.0",
"axios": "^1.9.0",
"pinia": "^3.0.2",
"vant": "^4.9.19",
"vue": "^3.5.13",
"vue-qrcode": "^2.2.2",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.3",
"postcss-px-to-viewport": "^1.1.1",
"sass": "^1.89.0",
"vite": "^6.3.5"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

+30
View File
@@ -0,0 +1,30 @@
{
"item_bottom": [{
"title": "《用户须知》",
"content": "<p>富文本内容</p>",
"type": 1
},{
"title": "《隐私政策》",
"content": "<p>富文本内容</p>",
"type": 1
}],
"allowance_bottom": [{
"title": "《车主信息共享授权书》",
"content": "<p>富文本内容</p>",
"type": 1
},{
"title": "《车主服务个人信息保护声明》",
"content": "<p>富文本内容</p>",
"type": 1
}],
"allowance_invoice": {
"title": "查看示例",
"content": "http://XXXX.jpg",
"type": 2
},
"allowance_insuranc": {
"title": "查看示例",
"content": "http://XXXX.jpg",
"type": 2
}
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+66
View File
@@ -0,0 +1,66 @@
<script setup>
// 路由转发页面无需额外组件引入
import api from './utils/api.js';
// 获取当前URL参数
const urlParams = new URLSearchParams(window.location.search);
// const cfUid = urlParams.get('cfUid');
const friend_account_id = urlParams.get('friend_account_id');
const accountId = urlParams.get('accountId');
// 执行微信授权检查
try {
api.wechatAPI.checkAndLogin(window.location.href, accountId ? accountId : undefined,friend_account_id ? friend_account_id : undefined)
.then(result => {
if (result.redirecting) {
console.log('跳转微信授权中...');
} else if (result.success) {
console.log('微信授权成功,token:', result.token);
}
})
.catch(error => {
console.error('微信授权失败:', error);
});
} catch (error) {
console.error('授权初始化异常:', error);
}
</script>
<template>
<div id="app"
style="--van-button-danger-background:#f84803;--van-button-danger-border-color:#f84803;--van-button-radius:8px;">
<!-- 路由导航链接 -->
<!-- <nav class="nav">
<router-link to="/" class="nav-link">首页</router-link>
<router-link to="/about" class="nav-link">关于</router-link>
</nav> -->
<!-- 路由视图容器 -->
<!-- <transition name="fade" mode="out-in">
<router-view class="view-container" />
</transition> -->
<router-view class="view-container" v-slot="{ Component }">
<transition name="fade">
<component :is="Component" />
</transition>
</router-view>
</div>
</template>
<style scoped lang="scss">
/* 路由切换动画 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
// @import "./style/pages/h5.scss";</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

+149
View File
@@ -0,0 +1,149 @@
<template>
<div class="relative brand-list fn-flex fn-flex-column" style="height: 100%;">
<div class="home-search ulib-r750 overflowhidden inner5 mt30 ml30 mr30 mb20" style="border:1px solid var(--van-button-danger-background)">
<div class="fn-flex fn-flex-center">
<div class="fn-flex-item pl20"><van-field v-model="keywords" label="" placeholder="请输入您想要的车型" style="padding:0" /></div>
<div><van-button style="width:16vw;" type="danger" round size="small" @click="onSearch">搜索</van-button></div>
</div>
</div>
<div v-if="0" class="absolute font-26 right-0 mr30 fn-flex fn-flex-center"><span>只看</span><span class="mr10" :style="'color:'+active_color">新能源</span><van-switch v-model="is_only_new" :active-color="active_color" inactive-color="#dcdee0" size="18px"/></div>
<div class="fn-flex-item relative">
<div class="absolute scroll-y" style="width: 100%;height:100%;left:0;top:0;">
<van-index-bar :sticky="isSticky" ref="indexbar">
<template v-for="(it,idx) in list" :key="idx">
<van-index-anchor :index="idx" />
<van-cell v-for="(item,index) in it" :key="index" @click="handleClickItem(item)">
<template #title>
<div :ref="'indexitem_'+idx+'_'+index" class="fn-flex fn-flex-center">
<van-image class="mr10" :src="item.logo" width="20" height="20" />
<span class="font-26">{{item.name}}</span>
</div>
</template>
<template #value>
<van-tag v-if="0" color="#fff4f4" text-color="#f84803" round >至高2万补贴<van-icon name="play" /></van-tag>
</template>
</van-cell>
</template>
</van-index-bar>
</div>
</div>
</div>
</template>
<script>
import api from '@/utils/api.js';
import { useBrandStore } from '@/stores/brand';
import { showToast } from 'vant'
export default {
name: 'BrandList',
props: {
},
data() {
return {
list: [],
keywords: '', // 搜索关键词
is_only_new:false,
active_color: '#79ccb9', // 选中颜色
isSticky: true,
}
},
mounted() {
this.fetchCarBrands();
},
methods: {
handleClickItem(item){
this.$emit('brandItem',item) // 触发父组件的点击事件,并传递当前项作为参数
},
onSearch() { // 搜索事件处理
console.log('搜索内容:', this.keywords,this.list.length)
if (!this.keywords.trim()) {
return;
}
// 在list中查找匹配的品牌
let targetGroupIndex = -1;
let targetItemIndex = -1;
// for (let groupIndex = 0; groupIndex < this.list.length; groupIndex++) {
for(let groupIndex in this.list){
const group = this.list[groupIndex];
console.log(groupIndex,group)
for (let itemIndex = 0; itemIndex < group.length; itemIndex++) {
const item = group[itemIndex];
if (item.name && item.name.includes(this.keywords.trim())) {
targetGroupIndex = groupIndex;
targetItemIndex = itemIndex;
break;
}
}
if (targetGroupIndex !== -1) break;
}
// 如果找到匹配的品牌,滚动到对应位置
if (targetGroupIndex !== -1) {
console.log(targetGroupIndex,targetItemIndex)
this.$nextTick(() => {
// 使用van-index-bar的scrollTo方法滚动到指定索引
const indexBar = this.$el.querySelector('.van-index-bar');
if (indexBar && indexBar.__vue__) {
indexBar.__vue__.scrollTo(targetGroupIndex);
} else {
// 备用方案:直接滚动到对应的锚点
const anchor = this.$refs.indexbar;
console.log(anchor)
if (anchor) {
anchor.scrollTo(targetGroupIndex);
}
// const anchor = this.$refs['indexitem_'+targetGroupIndex+'_'+targetItemIndex];
// if (anchor) {
// if (anchor && typeof anchor.scrollIntoView === 'function') {
// anchor.scrollIntoView({ behavior: 'smooth', block: 'start' });
// }
// }
}
});
} else {
// 没有找到匹配的品牌
showToast('未找到匹配的品牌');
}
},
async fetchCarBrands() {
const brandStore = useBrandStore();
// 检查store中是否已有数据
if (brandStore.list && Object.keys(brandStore.list).length > 0) {
this.list = brandStore.list;
return brandStore.list;
}
// 没有缓存数据时请求接口
try {
const { data } = await api.get('/auto/car/brand');
if (data) {
this.list = data;
// 将数据存储到store中
brandStore.setList(data);
}
return data;
} catch (error) {
console.error('获取品牌数据失败:', error);
return { code: 500, message: '接口请求异常' };
}
},
}
}
</script>
<style lang="scss" scoped>
.brand-list {
::v-deep{
.van-index-anchor--sticky{
left: 0!important;
}
}
}
</style>
+135
View File
@@ -0,0 +1,135 @@
<template>
<div class="scroll-y city-choose-list" style="height: 100%;">
<div class="fn-flex fn-flex-center font-24 inner30 bg-fa">
<template v-if="city_info.cityName">
<div class="fn-flex-item fn-flex fn-flex-center">
<van-icon name="guide-o" />
<span>当前城市</span>
<span>{{city_info.cityName}}</span>
</div>
<div class="fn-flex fn-flex-center" @click="refreshLocaiton">
<van-icon name="replay" />
<span>定位</span>
</div>
</template>
<template v-else>
<div class="fn-flex-item fn-flex fn-flex-center" @click="refreshLocaiton">
<van-icon name="guide-o" />
<span>定位所在城市</span>
</div>
</template>
</div>
<div class="fn-flex-item">
<!-- <div class="absolute scroll-y" style="left:0;top:0;width:100%;height: 100%;"> -->
<van-index-bar :sticky="isSticky">
<template v-for="(it, idx) in list" :key="idx">
<van-index-anchor :index="idx" />
<van-cell v-for="(item, index) in it" :key="index" @click="handleClickItem(item)">
<template #title>
<div class="fn-flex fn-flex-center">
<!-- <van-image class="mr10" :src="item.logo" width="20" height="20" /> -->
<span class="font-26">{{ item.city_name }}</span>
</div>
</template>
</van-cell>
</template>
</van-index-bar>
<!-- </div> -->
</div>
</div>
</template>
<script>
// import { ref, watch } from 'vue'
import { useUserStore } from '@/stores/user';
import { useCityStore } from '../stores/city';
import api from '@/utils/api';
import WechatUtils,{ WechatLocation } from '@/utils/wechat'
export default {
name: 'CityChooseList',
data() {
return {
list: [],
city_info: {city_name: ''},
isSticky: true
}
},
watch: {
'useUserStore().city_info': function (val) {
this.city_info = val
}
},
mounted() {
this.initCurCity();
},
methods: {
initCurCity() {
console.log('城市信息:', useUserStore().cur_city);
this.city_info = useUserStore().cur_city;
this.getCityList()
},
/**
* 获取城市列表
* /auto/area/city
*/
async getCityList() {
const cityStore = useCityStore();
if(cityStore.listByPinyin.length>0){
this.list = cityStore.listByPinyin;
}else{
const result = await api.get('/auto/area/city');
if (result.code === 200 && result.data) {
this.list = result.data;
cityStore.setByPinyin(result.data);
}
}
},
/**
* 刷新定位
*/
async refreshLocaiton() {
const location = await WechatLocation.getLocation('gcj02');
const result = await api.wechatAPI.getLocationCity(location.latitude, location.longitude);
console.log('刷新定位:', result);
console.log('刷新定位location:', location);
if (result.code === 200 && result.data) {
const userStore = useUserStore();
// this.list = result.data;
this.city_info = {
cityName: result.data.cityName,
cityId: result.data.cityId
};
localStorage.setItem('cityInfo', JSON.stringify(result.data));
localStorage.setItem('userLocation', JSON.stringify({ ...location, time: new Date().getTime() }));
userStore.setCity(result.data);
this.$emit('cityItem',{
cityName: result.data.cityName,
cityId: result.data.cityId
})
}
},
handleClickItem(item){
this.city_info = {
cityName: item.city_name,
cityId: item.city_id
};
this.$emit('cityItem',{
cityName: item.city_name,
cityId: item.city_id
})
}
}
}
</script>
<style lang="scss" scoped>
.city-choose-list {
::v-deep{
.van-index-anchor--sticky{
left: 0!important;
}
}
}
</style>
+81
View File
@@ -0,0 +1,81 @@
<template>
<div class="coupon-component relative">
<div :class="['coupon-bg', isActive?'red':'gray']"></div>
<div class="absolute left-0 top-0 right-0 bottom-0 fn-flex">
<div class="fn-flex fn-flex-item">
<div style="width:36%" class="text-center fn-flex fn-flex-column fn-flex-center justify-center">
<div :class="['coupon-price text-bold text-middle font-28',isActive?' text-color-theme':'color-bbb']"><span class="font-52 mr10">{{priceNum}}</span><span>{{priceUnit}}</span></div>
<div :class="['coupon-desc font-24 mt10',isActive?'color-bd6d6d':'color-bbb']" @click.stop="goLink(index)">{{descLeft}}<van-icon v-if="isDescLink" name="arrow" /></div>
</div>
<div style="width:60%" class="fn-flex-item pl35 text-left fn-flex fn-flex-column justify-center">
<div class="coupon-title text-bold text-italic font-40" style="font-weight: 800;">
<template v-if="typeof title === 'string'">
<template v-for="(item, index) in title" :key="index">
<span v-if="isActive" :class="[title.length>2 && index>title.length-5 ?'text-color-theme':'color-000']">{{item}}</span>
<span v-else :class="[index<4?'color-bbb':'color-888']">{{item}}</span>
</template>
</template>
<template v-else>
<template v-for="(item, index) in title" :key="index">
<span v-if="isActive" :class="[item.is_highlight?'text-color-theme':'color-000']">{{item.text}}</span>
<span v-else :class="[item.is_highlight?'color-bbb':'color-888']">{{item.text}}</span>
</template>
</template>
</div>
<div :class="['coupon-desc font-24 mt20',isActive?'color-bd6d6d':'color-bbb']">{{descRight}}</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
isActive: {
type: [Boolean,Number],
default: true
},
priceNum: {
type: [String,Number],
default: '0'
},
priceUnit: {
type: String,
default: '元'
},
isDescLink: {
type: Boolean,
default: false
},
descLeft: {
type: String,
default: ''
},
title: {
type: [Array,String],
default: () => []
},
descRight: {
type: String,
default: ''
},
index: {
type: Number,
default: 0
},
})
const emit = defineEmits(['goLink'])
const goLink = (index) => {
if(props.isDescLink){
emit('goLink',index)
}
}
const aaa = () => {}
</script>
<style>
/* .color-#bd6d6d{} */
</style>
+44
View File
@@ -0,0 +1,44 @@
<script setup>
import { ref } from 'vue'
defineProps({
msg: String,
})
import { useCounterStore } from '../stores/counter'
const counter = useCounterStore()
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<van-button type="primary" @click="counter.increment">Count: {{ counter.count }}Vant 按钮</van-button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test HMR
</p>
</div>
<p>
Check out
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
>create-vue</a
>, the official Vue + Vite starter
</p>
<p>
Learn more about IDE Support for Vue in the
<a
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
target="_blank"
>Vue Docs Scaling up Guide</a
>.
</p>
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
+17
View File
@@ -0,0 +1,17 @@
<template>
<div style="height:100vh;" class="fn-flex fn-flex-column fn-flex-center justify-center relative">
<div class="pt120"></div>
<van-loading size="24px" vertical>页面加载中...</van-loading>
<div class="fn-flex fn-flex-item"></div>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
+56
View File
@@ -0,0 +1,56 @@
<template>
<div style="--van-popup-background:transparent;--van-cell-background:transparent;">
<van-popup :show="showPop" :position="'center'" :style="{ padding: '0' }">
<div class="pt60 relative">
<div class="bg-fff ulib-r20 inner30" style="width:80vw;">
<h3 class="text-center font-34 pt30" v-if="title">{{title}}</h3>
<div class="mt30" v-if="img">
<van-image :src="img"></van-image>
</div>
<div class="" v-else-if="code">
<qrcode-vue :value="code" :size="size" level="H"></qrcode-vue>
</div>
</div>
<div class="absolute right-0 top-0 mr20" :style="{'margin-top': 0/7.5+'vw'}">
<van-icon @click="handleClose" name="close" color="#fff" size="24"/>
</div>
</div>
</van-popup>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
import QrcodeVue from 'vue-qrcode'
// 声明组件名称(可选,用于devtools)
defineOptions({ name: 'PopCode' })
// 声明propsVue 3推荐使用defineProps宏)
const props = defineProps({
title: { type: String, default: '' },
showPop: { type: Boolean, default: false },
img: { type: String, default: '' },
code: { type: String, default: '' },
})
const size = '10'
// 声明emits事件(与子组件通信)
const emit = defineEmits(['update:showPop'])
// 定义方法(直接在script setup中声明)
function handleClose() {
emit('update:showPop', false)
}
function onCountFinish() {
emit('update:showPop', false)
}
function showCount() {
// 方法逻辑(根据实际需求补充)
}
</script>
<style></style>
+53
View File
@@ -0,0 +1,53 @@
<template>
<div style="--van-popup-background:transparent;--van-cell-background:transparent;">
<van-popup :show="showPop" :position="'center'" :style="{ padding: '0' }">
<div class="pt60 relative">
<div class="bg-fff ulib-r20 inner30" style="width:90vw;">
<h3 class="text-center font-34" v-if="title">{{title}}</h3>
<div class="mt30 scroll-y" style="min-height: 40vh; max-height: 80vh;" v-if="content">
<div class="font-26" style="line-height: 1.5;" v-html="content"></div>
</div>
<div class="mt30" v-if="img">
<van-image style="display: block;" :src="img"></van-image>
</div>
</div>
<div class="absolute right-0 top-0 mr20" :style="{'margin-top': 0/7.5+'vw'}">
<van-icon @click="handleClose" name="close" color="#fff" size="24"/>
</div>
</div>
</van-popup>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
// 声明组件名称(可选,用于devtools)
defineOptions({ name: 'PopCode' })
// 声明propsVue 3推荐使用defineProps宏)
const props = defineProps({
title: { type: String, default: '' },
showPop: { type: Boolean, default: false },
content: { type: String, default: '' },
img: { type: String, default: '' }
})
// 声明emits事件(与子组件通信)
const emit = defineEmits(['update:showPop'])
// 定义方法(直接在script setup中声明)
function handleClose() {
emit('update:showPop', false)
}
function onCountFinish() {
emit('update:showPop', false)
}
function showCount() {
// 方法逻辑(根据实际需求补充)
}
</script>
<style></style>
+213
View File
@@ -0,0 +1,213 @@
<template>
<div style="--van-popup-background:transparent;--van-cell-background:transparent;">
<van-popup :show="showPop" :position="'bottom'" :style="{ padding: '0' }">
<div class="pt60 relative">
<div class="bg-fff ulib-rt20 inner30">
<h3 class="text-center font-34">领取补贴券</h3>
<div class="mt20">
<CouponItem
:price-num="coupons.price"
:desc-left="coupons.getNun>0?'已有' + coupons.getNun + '人领取':''"
:title="coupons.typeCn"
:desc-right="detail.discounts2"
:is-active="true"
/>
</div>
<div v-if="coupons.bizTip" class="text-center mt25 font-26 color-b35a5a" style="color:#b35a5a;">
<p @click.stop="handleShowStores">{{coupons.bizTip}} <van-icon name="arrow" /></p>
</div>
<div class="pop-form mt5">
<div class="bg-f2 ulib-r750 inner5 mt30">
<van-field v-model="mobile" label="" placeholder="请输入您的常用手机号码" />
</div>
<div class="bg-f2 ulib-r750 inner5 mt30">
<van-field v-model="code" label="" placeholder="验证码" >
<template #button>
<span v-if="!is_show_count" @click.stop="getSmsCode" class="text-color-theme font-26">发送验证码</span>
<van-count-down class="color-ccc font-26" v-else :time="count_time" format="ss 秒后重发" @finish="onCountFinish" />
</template>
</van-field>
</div>
<div class="text-center font-24 mt30">领取即同意
<span v-for="(item,index) in item_pop_bottom_info" :key="index" class="color-184ebb" @click="showPopContent(item)">{{ item.title }}</span></div>
<div class="mt30">
<van-button round type="danger" :disabled="!(mobile && code)" block class="w100" @click.stop="bindPostCoupon">立即领取</van-button>
</div>
</div>
</div>
<div class="absolute right-0 top-0 mr20" :style="{'margin-top': 0/7.5+'vw'}">
<van-icon @click="handleClose" name="close" color="#fff" size="24"/>
</div>
</div>
</van-popup>
<PopContent :content="content" :show-pop="showContentPop" @update:show-pop="showContentPop = $event" />
</div>
</template>
<script setup>
import { ref, reactive, defineEmits, watch } from 'vue'
import CouponItem from '@/components/CouponItem.vue' // 导入CouponItem组件
import PopContent from '@/components/PopContent.vue' // 导入PopContent组件
import api from '@/utils/api' // 导入API模块
import { showToast } from 'vant' // 导入Toast组件
import { getBasicConfig } from '@/utils/basicSetting'
const emit = defineEmits(['update:showPop','showStorePop'])
defineOptions({
name: 'PopGetAllowance'
})
// 定义propsVue3推荐使用defineProps宏)
const props = defineProps({
showPop: { type: Boolean, default: false }, // 控制弹窗的显示和隐藏
coupons: { type: Object, default: () => ({}) }, // 补贴信息
detail: { type: Object, default: () => ({}) }, // 补贴信息
})
// Ensure slot 'value' is called inside template/render function
const mobile = ref('');
const code = ref('');
const is_show_count = ref(false);
const count_time = ref(60000);
watch(() => props.showPop, async(val) => {
console.log('showPop', val);
if (val) {
await getBottomInfoAgreeMent();
}
})
/**
* 验证手机号格式
* @param {string} phone - 手机号
* @returns {boolean} - 是否是有效的手机号
*/
const validateMobile = (phone) => {
const reg = /^1[3-9]\d{9}$/;
return reg.test(phone);
};
/**
* 获取短信验证码
*/
const getSmsCode = async () => {
// 验证手机号
if (!mobile.value) {
showToast('请输入手机号');
return;
}
if (!validateMobile(mobile.value)) {
showToast('请输入正确的手机号格式');
return;
}
try {
// 调用获取验证码接口
const result = await api.post('/auto/sms', { mobile: mobile.value });
if (result.code === 200) {
showToast('验证码发送成功');
// 开始倒计时
showCount();
} else {
showToast(result.message || '验证码发送失败');
}
} catch (error) {
console.error('获取验证码失败:', error);
showToast('获取验证码失败,请稍后重试');
}
};
// 防双击状态
const isSubmitting = ref(false);
const bindPostCoupon = async () => {
// 防双击检查
if (isSubmitting.value) {
return;
}
if (!mobile.value) {
showToast('请输入手机号');
return;
}
if (!validateMobile(mobile.value)) {
showToast('请输入正确的手机号格式');
return;
}
if (!code.value) {
showToast('请输入验证码');
return;
}
// 设置提交状态
isSubmitting.value = true;
///auto/car/coupon
try {
const result = await api.post('/auto/car/coupon', {
mobile: mobile.value,
code: code.value,
couponId: props.coupons.coupon_id
});
if (result.code === 200) {
handleSuccess();
} else {
showToast(result.message || '补贴领取失败');
}
} catch (error) {
console.error('补贴领取失败:', error);
showToast('补贴领取失败,请稍后重试');
} finally {
// 重置提交状态
isSubmitting.value = false;
}
}
const showContentPop = ref(false);
const content = ref('');
const item_pop_bottom_info = ref([])
const getBottomInfoAgreeMent = async () => {
item_pop_bottom_info.value = await getBasicConfig('item_bottom')
}
const showPopContent = (item) => {
content.value = item.content;
showContentPop.value = true;
};
function handleSuccess(){
emit('update:showPop', false)
emit('success', true)
}
// 方法直接定义在script setup中(示例,根据业务需求补充逻辑)
function handleClose() {
// 关闭弹窗逻辑
console.log('close')
emit('update:showPop', false)
}
function showCount() {
is_show_count.value = true;
count_time.value = 60000;
}
function onCountFinish() {
is_show_count.value = false;
}
function handleShowStores() {
emit('showStorePop', true)
}
</script>
<style></style>
+203
View File
@@ -0,0 +1,203 @@
<template>
<div style="--van-popup-background:transparent;--van-cell-background:transparent;--van-cell-horizontal-padding:0;">
<van-popup :show="showPop" :position="'center'" :style="{ padding: '0' }">
<div class="pt60 relative">
<div class="bg-fff ulib-r20 inner30" style="width:85vw;">
<h3 class="text-center font-34">适用门店</h3>
<div class="mt20">
<van-field v-model="result" is-link readonly name="area" label="地区选择" placeholder="点击选择省市区"
@click="showArea = true" >
<template #extra>
<span v-if="result" class="ml10 mr10">|</span> <span v-if="result" @click.stop="initList" class="color-999 font-24">清空选择</span>
</template>
</van-field>
</div>
<div class="mt30" style="height:50vh;overflow-y:auto;">
<div v-if="empty" class="text-center font-24 color-666">
<van-empty description="暂无数据" />
</div>
<van-list v-else v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<template v-for="(item, index) in list" :key="index">
<div class="fn-flex">
<div><i class="icon-custom icon-map"></i></div>
<div class="ml10 fn-flex-item">
<h4 class="font-30">{{item.biz_name}}</h4>
<p class="color-666 font-24 mt20">{{item.address}}</p>
</div>
<div class="wp20 text-right" @click.stop="showMapItem(item)">
<span class="inline-block imgsize-60X60 relative ulib-r750" style="border:1px solid #333;"><i
class="icon-custom icon-loc absolute box-center-middle"></i></span>
<p class="font-20 mt5 mr10 color-666">导航</p>
</div>
</div>
<van-divider v-if="index < list.length - 1" />
</template>
</van-list>
</div>
</div>
<div class="absolute right-0 top-0 mr20" :style="{ 'margin-top': 0 / 7.5 + 'vw' }">
<van-icon @click="handleClose" name="close" color="#fff" size="24" />
</div>
</div>
</van-popup>
<van-popup v-model:show="showArea" destroy-on-close position="bottom">
<van-area :area-list="areaList" :model-value="pickerValue" :columns-num="2" @confirm="onConfirm" @cancel="showArea = false" />
</van-popup>
</div>
</template>
<script setup>
import { ref, defineProps, defineEmits, watch } from 'vue'
import { areaList } from '@vant/area-data';
import api from '../utils/api'
import { WechatLocation } from '../utils/wechat'
// 声明组件名称(可选,用于devtools)
defineOptions({ name: 'PopStores' })
// 声明propsVue 3推荐使用defineProps宏)
const props = defineProps({
showPop: { type: Boolean, default: false },
coupons: { type: Object, default: () => ({}) },
id: { type: [Number, String], default: '' },
})
// 声明emits事件(与子组件通信)
const emit = defineEmits(['update:showPop'])
// 定义方法(直接在script setup中声明)
function handleClose() {
emit('update:showPop', false)
}
function onCountFinish() {
emit('update:showPop', false)
}
const initList = async() => {
// 方法逻辑(根据实际需求补充)
result.value =''
provinceId.value = '';
cityId.value = '';
page.value = 1;
finished.value = false;
loading.value = false;
empty.value = false;
await getCouponBizs();
}
watch(() => props.showPop, (val) => {
if (val) {
initList();
}
})
const result = ref('');
const showArea = ref(false);
const pickerValue = ref([]);
const onConfirm = async ({ selectedValues, selectedOptions }) => {
pickerValue.value = selectedValues.length
? selectedValues[selectedValues.length - 1]
: '';
showArea.value = false;
result.value = selectedOptions.map((item) => item.text).join('/');
provinceId.value = selectedValues[0];
cityId.value = selectedValues[1];
page.value = 1;
finished.value = false;
loading.value = false;
empty.value = false;
await getCouponBizs();
};
const provinceId = ref('');
const cityId = ref('');
const list = ref([]);
const loading = ref(false);
const finished = ref(false);
const totalCount = ref(0);
const page = ref(1);
const empty = ref(false);
const isRequesting = ref(false);
const onLoad = async () => {
// 异步更新数据
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
await getCouponBizs()
};
/**
* 请求接口 /auto/car/coupon/bizs
*/
const getCouponBizs = async () => {
console.log('getCouponBizs',isRequesting.value,finished.value,empty.value);
if (isRequesting.value || finished.value || empty.value) return;
isRequesting.value = true;
loading.value = true;
try {
const response = await api.get('/auto/car/coupon/bizs',{
couponId: props.id,
page: page.value,
size: 10,
...provinceId? { provinceId: provinceId.value } : {},
...cityId? { cityId: cityId.value } : {}
});
if (response.code === 200) {
isRequesting.value = false;
loading.value = false;
if (page.value === 1) {
list.value = [];
if(response.data.list.length===0){
empty.value = true;
finished.value = true;
return
}
}
if(response.data.list.length===0){
finished.value = true;
return
}
list.value = response.data.list.concat(list.value);
totalCount.value = response.data.count;
if (list.value.length >= totalCount.value) {
finished.value = true;
return
}
page.value++;
} else {
isRequesting.value = false;
loading.value = false;
showToast(response.message || '获取补贴列表失败');
}
// return response;
} catch (error) {
isRequesting.value = false;
loading.value = false;
console.error('获取优惠券数据失败:', error);
return { code: 500, message: '接口请求异常' };
} finally {
isRequesting.value = false;
loading.value = false;
}
};
/**
* 打开微信地图
*/
const showMapItem = (item) => {
if(item.lat && item.lng){
WechatLocation.openLocation({
latitude: parseFloat(item.lat),
longitude: parseFloat(item.lng),
name: item.biz_name,
address: item.address
});
}
}
</script>
<style></style>
+43
View File
@@ -0,0 +1,43 @@
<template>
<div class="side-menu fixed z-index-1 bottom-0 right-0 mb50 mr30">
<ul class="ulib-r750 bg-000-op60 text-center">
<li class="" v-for="(item, index) in menuItems" :key="index" >
<template v-if="name">
<router-link :to="item.path" v-if="name === item.name">
<div class="imgsize-80X80 fn-flex fn-flex-column fn-flex-center justify-center text-center font-24">
<i :class="[item.icon,'color-fff']"></i>
<span class="color-fff mt10">{{ item.name }}</span>
</div>
</router-link>
</template>
<template v-else>
<router-link :to="item.path" v-if="route.path !== item.path">
<div class="imgsize-80X80 fn-flex fn-flex-column fn-flex-center justify-center text-center font-24">
<i :class="[item.icon,'color-fff']"></i>
<span class="color-fff mt10">{{ item.name }}</span>
</div>
</router-link>
</template>
</li>
</ul>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const props = defineProps({
name: {
type:String,
default: ''
}
});
const menuItems = [
{ name: '首页', icon: 'icon-custom icon-home', path: '/' },
{ name: '我的', icon: 'icon-custom icon-my', path: '/my' }
]
</script>
<style>
</style>
+18
View File
@@ -0,0 +1,18 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router' // 引入路由
import Vant from 'vant'
import 'vant/lib/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia()) // 挂载Pinia
app.use(router)
app.use(Vant)
app.mount('#app')
import './style/pages/h5.scss'
//https://cloud.tencent.com/developer/article/1992189
+13
View File
@@ -0,0 +1,13 @@
<template>
<div>about</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
+534
View File
@@ -0,0 +1,534 @@
<template>
<div>
<div v-if="is_first_load" class="loading relative">
<PageInitLoading />
</div>
<transition name="fade">
<div v-if="!is_first_load" class="home-page relative" style="min-height: 100vh;">
<div class="home-bg absolute left-0 top-0 right-0 bottom-0" ></div>
<div v-if="cityInfo&&cityInfo.cityName" class="absolute right-0 top-0 mr30 mt50 z-index-1">
<div @click.stop="handleShowCityList" class="bg-fff font-24 pl15 pr15 pt10 pb10 ulib-r10">{{ cityInfo.cityName }}<van-icon name="play" /></div>
</div>
<div class="relative pt220 ml30 mr30">
<div class="home-options bg-fff ulib-r20 inner30">
<div class="home-step-bg"></div>
<div class="home-search ulib-r750 overflowhidden inner5 mt30" style="border:1px solid var(--van-button-danger-background)">
<div class="fn-flex fn-flex-center">
<div class="fn-flex-item pl20"><van-field v-model="keywords" label="" placeholder="请输入搜索关键词" style="padding:0" /></div>
<div><van-button style="width:16vw;" type="danger" round size="small" @click="onSearch">搜索</van-button></div>
</div>
</div>
<div class="home-companys mt30 fn-flex">
<div class="fn-flex-item relative">
<div class="absolute left-0 right-0 top-0 scroll-x" style="white-space: nowrap;">
<template v-for="(it,idx) in brand_list" :key="idx">
<template v-if="idx=='A'">
<template v-for="(item,index) in it" :key="index">
<div v-if="index<5" class="text-center inline-block mr20" @click.stop="chooseBrandItem(idx,index)">
<div class="imgsize-52X52" style="margin-left:auto;margin-right:auto;"><van-image class="imgsize-52X52" fit="cover" :src="item.logo" /></div>
<p class="font-24 mt10">{{item.name}}</p>
</div>
</template>
</template>
</template>
</div>
</div>
<div class="text-center" @click="showBrandList= true">
<van-icon name="clock-o" size="25" style="transform: rotate(-135deg);"/>
<p class="font-24 mt10">更多</p>
</div>
</div>
<SideMenu />
<div class="home-filter mt15">
<!-- <div v-if></div> -->
<div>
<ul class="fn-flex fn-flex-wrap">
<li
class="ulib-r10 pl20 pr20 pt10 pb10 mr30 mt15 font-24"
v-for="(item,index) in carProductLabel"
:key="index"
@click.stop="bindChangeTagList(index,'carProductLabel')"
:style="{
backgroundColor: index === cur_carProductLabel ? '#ffeded' : '#f9f9f9',
border:'1px solid ' + (index === cur_carProductLabel ? '#ffcaca' : '#f9f9f9')
}">{{item.name}}</li>
</ul>
</div>
<div>
<ul class="fn-flex fn-flex-wrap">
<li
class="ulib-r10 pl20 pr20 pt10 pb10 mr30 mt15 font-24"
v-for="(item,index) in priceRange"
:key="index"
@click.stop="bindChangeTagList(index,'priceRange')"
:style="{
backgroundColor: index === cur_priceRange ? '#ffeded' : '#f9f9f9',
border:'1px solid '+(index === cur_priceRange ? '#ffcaca' : '#f9f9f9')
}">{{item.name}}</li>
</ul>
</div>
<div>
<ul class="fn-flex fn-flex-wrap">
<li
class="ulib-r10 pl20 pr20 pt10 pb10 mr30 mt15 font-24"
v-for="(item,index) in productLevel"
:key="index"
@click.stop="bindChangeTagList(index,'productLevel')"
:style="{
backgroundColor: index === cur_productLevel ? '#ffeded' : '#f9f9f9',
border:index === cur_productLevel ?'1px solid #ffcaca':'1px solid #f9f9f9'
}">{{item.name}}</li>
</ul>
</div>
</div>
<div class="mt10 fn-flex fn-flex-center">
<div class="fn-flex-item">
<van-tag v-if="cur_brand_list&&cur_brand_list.id" class="mr5" closeable size="mini" color="#f84803" plain @close="bindCloseTag('brand')">{{cur_brand_list.name}}</van-tag>
<van-tag v-if="cur_carProductLabel>-1" class="mr5" closeable size="mini" color="#f84803" plain @close="bindCloseTag('carProductLabel')">{{carProductLabel[cur_carProductLabel].name}}</van-tag>
<van-tag v-if="cur_priceRange>-1" class="mr5" closeable size="mini" color="#f84803" plain @close="bindCloseTag('priceRange')">{{priceRange[cur_priceRange].name}}</van-tag>
<van-tag v-if="cur_productLevel>-1" class="mr5" closeable size="mini" color="#f84803" plain @close="bindCloseTag('productLevel')">{{productLevel[cur_productLevel].name}}</van-tag>
</div>
<span v-if="(cur_brand_list&&cur_brand_list.id)||cur_carProductLabel>-1||cur_priceRange>-1||cur_productLevel>-1" class="font-24 text-middle fn-flex fn-flex-center color-999" @click.stop="bindCloseTag('all')"><span>清空</span><van-icon size="20px" name="delete-o" /></span>
</div>
</div>
<div class="home-list mt10" v-if="empty">
<van-empty description="暂无数据" />
</div>
<div class="home-list mt10" v-else>
<van-list
v-model:loading="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
>
<template v-for="(item, index) in productList" :key="index">
<div class="home-item box-shadow-darkGray inner30 mb40 ulib-r20">
<div class="item" @click.stop="pushLink(`/item/${item.id}`)">
<div class="fn-flex">
<div class="mr20"><van-image class="imgsize-200X152" radius="10px" :src="item.banner" /></div>
<div class="fn-flex-item fn-flex fn-flex-column">
<div class="fn-flex-item">
<div class="fn-flex fn-flex-center justify-between">
<div class="wp50 font-30 line-clamp-1">{{ item.title }}</div>
<div class="tag fn-flex fn-flex-wrap text-right">
<van-tag
v-for="(label, labelIndex) in item.carProductLabel"
:key="labelIndex"
class="ml5"
color="#f6f6f6"
round
text-color="#1a1a1a"
>{{ label }}</van-tag>
</div>
</div>
<div class="mt15 line-clamp-1 color-333"><p class="font-26" v-if="item.guide_price">指导价{{ item.guide_price }}</p></div>
<div class="mt15" style="--van-tag-radius:1vw;--van-tag-font-size:3.4vw;">
<van-tag v-if="item.discounts" color="#f84803" plain style="padding-left:0"><i class="icon-custom icon-redpack mr5"></i>{{ item.discounts }}</van-tag>
</div>
</div>
</div>
</div>
<div class="fn-flex fn-flex-center justify-between">
<div class="wp65 ">
<div v-if="item.discounts2" style="color:#f00;" class="text-color-theme font-28 fn-flex fn-flex-center"><i class="icon-custom icon-money mr5"></i><span class="line-clamp-1">{{ item.discounts2 }}</span></div>
<div v-if="item.discounts3" style="color:#f00;" class="text-color-theme font-28 fn-flex fn-flex-center mt10"><i class="icon-custom icon-gift mr5"></i><span class="line-clamp-1">{{ item.discounts3 }}</span></div>
</div>
<div class="" :style="{'--van-button-default-line-height':(70/7.5)+'vw','--van-button-default-height':(70/7.5)+'vw'}">
<van-button type="danger" class="pl40 pr40">{{ item.btText || '立即领取' }}</van-button>
</div>
</div>
</div>
</div>
</template>
<div v-if="productList.length === 0 && !loading && finished" class="text-center pt30 pb30 color-666">
暂无数据
</div>
</van-list>
</div>
</div>
<van-popup
v-model:show="showBrandList"
position="right"
:style="{ width: '80%', height: '100%' }"
><BrandList :is-sticky="false" @brandItem="handleBrandItem"/></van-popup>
<van-popup
v-model:show="showCityList"
position="right"
:style="{ width: '80%', height: '100%' }"
><CityChooseList @cityItem="handleCityItem"/></van-popup>
</div>
</transition>
</div>
</template>
<script setup>
import { ref, onMounted, reactive } from 'vue'
import { useRouter } from 'vue-router'
import SideMenu from '@/components/SideMenu.vue' // 导入SideMenu组件
import BrandList from '../components/BrandList.vue' // 导入BrandList组件
import CityChooseList from '../components/CityChooseList.vue' // 导入CityChooseList组件
import PageInitLoading from '../components/PageInitLoading.vue'
import WechatUtils,{ WechatLocation } from '@/utils/wechat'
import { useUserStore } from '@/stores/user';
import api from '@/utils/api'
import { useBrandStore } from '@/stores/brand';
import { showToast } from 'vant'
const route = useRouter()
const is_first_load = ref(true)
const keywords = ref('') // 声明响应式搜索关键词变量
const brand_list = ref([]) // 声明品牌列表变量
const showBrandList = ref(false) // 控制品牌列表的显示和隐藏
const cur_brand_list = ref({}) // 声明品牌列表变量
const showCityList = ref(false) // 控制城市列表的显示和隐藏
const carProductLabel = ref([]) // 声明响应式搜索关键词变量
const priceRange = ref([]) // 声明响应式搜索关键词变量
const productLevel = ref([]) // 声明响应式搜索关键词变量
const cur_carProductLabel = ref(-1) // 声明响应式搜索关键词变量
const cur_priceRange = ref(-1) // 声明响应式搜索关键词变量
const cur_productLevel = ref(-1) // 声明响应式搜索关键词变量
// 产品列表数据
const productList = ref([]);
const loading = ref(false);
const finished = ref(false);
const page = ref(1);
const pageSize = ref(10);
const empty = ref(false);
// 查询参数
const query_data = reactive({
page: 1,
size: 10,
title: '',
brandId: '',
labelIds: '',
cityId: ''
});
// 城市信息
const cityInfo = ref(null);
onMounted(async () => {
let appid = localStorage.getItem('app_id')
if(appid) {
const wechat = await WechatUtils.init(appid);
// 初始化完成后获取位置信息
await getCurrentLocation();
}
await bindInitPage()
})
const bindInitPage = async()=>{
// 获取字典列表数据
await getDictionaryList();
await getCarBrands()
try {
empty.value = false
await getProductList()
} catch (error) {
console.log(error)
}
}
/**
* 品牌列表
*/
const getCarBrands = async () => {
const brandStore = useBrandStore();
if (brandStore.list && Object.keys(brandStore.list).length > 0) {
brand_list.value = brandStore.list;
return brandStore.list;
}
try {
const { data } = await api.get('/auto/car/brand');
if (data) {
brand_list.value = data;
brandStore.setList(data);
}
return data;
} catch (error) {
console.error('获取品牌数据失败:', error);
return { code: 500, message: '接口请求异常' };
}
}
/**
* 获取字典列表
* @param {string} dictCode - 字典名称,默认为'carProductLabel'
*/
const getDictionaryList = async (dictCode = 'carProductLabel,priceRange,productLevel') => {
try {
const result = await api.get('/auto/config/dictionaryData', { dictCode });
if (result.code === 200 && result.data) {
carProductLabel.value = result.data.carProductLabel;
priceRange.value = result.data.priceRange;
productLevel.value = result.data.productLevel;
console.log('字典列表:', result.data);
}
} catch (error) {
console.error('获取字典列表失败:', error);
}
};
/**
* 获取当前位置并解析城市编码
*/
const getCurrentLocation = async () => {
try {
// 获取当前位置
const location = localStorage.getItem('userLocation')?JSON.parse(localStorage.getItem('userLocation')):await WechatLocation.getLocation('gcj02');
console.log('当前位置:', location);
const userStore = useUserStore();
// 解析位置获取城市信息
if (location && location.latitude && location.longitude) {
if(localStorage.getItem('cityInfo')){
cityInfo.value = JSON.parse(localStorage.getItem('cityInfo'));
console.log('城市信息:', cityInfo.value);
if (cityInfo.value.cityId) {
userStore.setCity(cityInfo.value);
query_data.cityId = cityInfo.value.cityId;
// 获取产品列表
empty.value = false
await getProductList();
}
}else{
const result = await api.wechatAPI.getLocationCity(location.latitude, location.longitude);
if (result.code === 200 && result.data) {
cityInfo.value = result.data;
console.log('城市信息:', cityInfo.value);
localStorage.setItem('cityInfo', JSON.stringify(cityInfo.value));
localStorage.setItem('userLocation', JSON.stringify({...location,time:new Date().getTime()}));
// 设置城市ID到查询参数
if (cityInfo.value.cityId) {
userStore.setCity(cityInfo.value);
query_data.cityId = cityInfo.value.cityId;
// 获取产品列表
empty.value = false
await getProductList();
}
}
}
}
} catch (error) {
console.error('获取位置或解析城市失败:', error);
}
};
/**
* 获取产品列表
*/
// 防重复请求状态
const isRequesting = ref(false);
const getProductList = async () => {
// 防止同时请求和重复请求
if (isRequesting.value || loading.value || finished.value) {
return;
}
try {
isRequesting.value = true;
loading.value = true;
const result = await api.get('/auto/car/product/list', query_data);
if (result.code === 200 && result.data) {
if(query_data.page === 1&&result.data.list.length === 0){
empty.value = true
finished.value = true;
return
}
if (query_data.page === 1) {
productList.value = result.data.list || [];
} else {
productList.value = [...productList.value, ...(result.data.list || [])];
}
// 判断是否加载完成
if (!result.data.list || result.data.list.length < query_data.size) {
finished.value = true;
return
}
// 更新页码
query_data.page++;
}
} catch (error) {
console.error('获取产品列表失败:', error);
} finally {
loading.value = false;
isRequesting.value = false;
is_first_load.value = false
}
};
// 搜索事件处理
const onSearch = () => {
// 重置查询参数
if(!keywords.value){
showToast('请输入搜索关键字')
return
}
query_data.page = 1;
query_data.title = keywords.value;
finished.value = false;
empty.value = false
// productList.value = [];
// 重新加载数据
getProductList();
};
// 按钮点击处理
const pushLink = (url) => {
route.push(url);
};
// 加载更多数据
const onLoad = () => {
getProductList();
};
// 切换标签
const bindChangeTagList = (index,type) => {
if(type === 'carProductLabel') {
cur_carProductLabel.value = index;
}else if(type === 'priceRange') {
cur_priceRange.value = index;
}else if(type === 'productLevel') {
cur_productLevel.value = index;
}
checkHasLabelIds()
query_data.page = 1;
finished.value = false;
empty.value = false
// productList.value = [];
getProductList();
}
const chooseBrandItem = (findex,cindex) => {
cur_brand_list.value = brand_list.value[findex][cindex];
query_data.brandId = brand_list.value[findex][cindex].id;
query_data.page = 1;
finished.value = false;
empty.value = false
getProductList();
}
const handleBrandItem = (item) => {
cur_brand_list.value = item;
query_data.brandId = item.id;
query_data.page = 1;
finished.value = false;
showBrandList.value = false;
empty.value = false
getProductList();
}
const handleCityItem = (item) => {
const userStore = useUserStore();
query_data.cityId = item.cityId;
query_data.page = 1;
finished.value = false;
empty.value = false
showCityList.value = false;
console.log('item',item);
cityInfo.value = {}
cityInfo.value.cityName = item.cityName;
cityInfo.value.cityId = item.cityId;
userStore.setCity(cityInfo.value);
localStorage.setItem('cityInfo', JSON.stringify(cityInfo.value));
getProductList();
}
const handleShowCityList = () => {
showCityList.value = true;
console.log(1111)
}
const bindCloseTag = (type) => {
if(type === 'brand') {
cur_brand_list.value = {};
query_data.brandId = '';
}else if(type === 'carProductLabel') {
cur_carProductLabel.value = -1;
checkHasLabelIds()
}else if(type === 'priceRange') {
cur_priceRange.value = -1;
checkHasLabelIds()
}else if(type === 'productLevel') {
cur_productLevel.value = -1;
checkHasLabelIds()
}else if(type === 'all') {
cur_brand_list.value = {};
query_data.brandId = '';
cur_carProductLabel.value = -1;
cur_priceRange.value = -1;
cur_productLevel.value = -1;
query_data.labelIds = '';
}
query_data.page = 1;
finished.value = false;
empty.value = false
getProductList();
}
const checkHasLabelIds = () => {
let arr = []
if(cur_carProductLabel.value > -1) {
arr.push(carProductLabel.value[cur_carProductLabel.value].id)
}
if(cur_priceRange.value > -1) {
arr.push(priceRange.value[cur_priceRange.value].id)
}
if(cur_productLevel.value > -1) {
arr.push(productLevel.value[cur_productLevel.value].id)
}
query_data.labelIds = arr.join(',')
}
const removeElement = (arr, value) => {
return arr.filter(function(item) {
return item !== value;
});
}
</script>
<style lang="scss" scoped>
.home-bg{
width: 100vw;
background-size: 100% auto;
background-position: top center;
background-repeat: no-repeat;
background-image: url('/src/assets/index-bg.jpg')
}
.home-step-bg{
width: 630px;
height: 30px;
background-size: 100% auto;
background-position: top center;
background-repeat: no-repeat;
background-image: url('/src/assets/index-steps.png')
}
</style>
+308
View File
@@ -0,0 +1,308 @@
<template>
<div class="detail-page relative" style="min-height: 100vh;">
<van-loading v-if="loading" class="loading-center" size="24px" vertical>加载中...</van-loading>
<template v-else-if="productDetail">
<div class="detail-banner relative">
<van-swipe :autoplay="3000" lazy-render>
<van-swipe-item v-for="(item,index) in banner_list" :key="index">
<van-image fit="cover" :style="'width:100%;height:'+Number(550/7.5)+'vw;'" :src="item.img" />
</van-swipe-item>
</van-swipe>
<div class="wp100 absolute pt140 left-0 right-0 bottom-0"
style="background-image: linear-gradient(to top, rgba(255,255,255,1),rgba(255,255,255,0));"
></div>
</div>
<div class="detail-info ml30 mr30 relative" :style="{'margin-top':Number(-60/7.5)+'vw'}">
<div class="ulib-r20 bg-fff inner30 box-shadow-darkGray">
<div class="fn-flex fn-flex-center">
<div class="mr20"><van-image class="imgsize-200X152" radius="10px" :src="productDetail.banner" /></div>
<div class="fn-flex-item fn-flex fn-flex-column justify-between">
<div class="fn-flex fn-flex-center justify-between">
<div class="wp60 font-30 line-clamp-1">{{ productDetail.title }}</div>
<div class="tag fn-flex fn-flex-wrap">
<van-tag
v-for="(tag, index) in productDetail.carProductLabel"
:key="index"
class="ml5"
color="#f0f0f0"
round
text-color="#666666"
>
{{ tag }}
</van-tag>
</div>
</div>
<div class="mt15 line-clamp-1 color-666"><p class="font-26">指导价{{ productDetail.guide_price }}</p></div>
<div class="fn-flex mt20" v-if="productDetail.discounts">
<div class="text-color-theme font-24 fn-flex fn-flex-center">
<div><i class="icon-custom icon-gift mr5"></i></div>
<span class="line-clamp-1">{{ productDetail.discounts3 }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="detail-coupon ml30 mr30 pt45" v-if="productDetail.coupons&&productDetail.coupons.show">
<CouponItem
:price-num="productDetail.coupons.price"
:desc-left="productDetail.coupons.getNun>0?'已有' + productDetail.coupons.getNun + '人领取':''"
:title="productDetail.coupons.typeCn"
:desc-right="productDetail.discounts2"
:is-active="true"
/>
</div>
<div class="detail-content ml30 mr30 mt40 pb40">
<van-tabs v-model:active="content_active" animated color="#f5500b" line-width="20px">
<van-tab v-for="(item,index) in content_list" :key="index" :title="item.title">
<div class="pt20 font-26 color-666" style="line-height: 1.7;" v-html="item.content"></div>
</van-tab>
</van-tabs>
</div>
<div class="wp100 pb200"></div>
<div class="detail-footer fixed left-0 bottom-0 right-0">
<div v-if="productDetail.coupons&&productDetail.coupons.show" style="background-color:#fff4f4;" class="inner20">
<div v-if="btn_info.status==1" class="text-center text-middle">
<van-count-down :time="count_time">
<template #default="timeData">
<span class="count-down-colon">倒计时</span>
<span v-if="timeData.days!=0" class="count-down-block">{{(timeData.days > 9)?'':'0'}}{{ timeData.days }}</span>
<span v-if="timeData.days!=0" class="count-down-colon">天</span>
<span class="count-down-block">{{(timeData.hours > 9)?'':'0'}}{{ timeData.hours }}</span>
<span class="count-down-colon">时</span>
<span class="count-down-block">{{(timeData.minutes > 9)?'':'0'}}{{ timeData.minutes }}</span>
<span class="count-down-colon">分</span>
<span class="count-down-block">{{(timeData.seconds > 9)?'':'0'}}{{ timeData.seconds }}</span>
<span class="count-down-colon">秒</span>
</template>
</van-count-down>
</div>
<div v-else class="text-center font-28 text-color-theme">{{btn_info.tip}}</div>
<div class="pt20 ml30 mr30">
<van-button round type="danger" :disabled="btn_info.status!=1" block class="w100" @click.stop="showPop=true">{{btn_info.text}}</van-button>
</div>
</div>
</div>
<PopGetAllowance @update:showPop="handleShowPop" @showStorePop="handleShowStorePop" @success="handleSuccess" :detail="productDetail" :coupons="productDetail.coupons" :show-pop="showPop" />
<PopStores @update:showPop="handleShowStorePop" :show-pop="showStorePop" :coupons="productDetail.coupons" :id="productDetail.coupons.coupon_id" />
<SideMenu />
</template>
<template v-else>
<div class="empty-data text-center pt100">
<van-empty description="暂无产品详情" />
</div>
</template>
</div>
</template>
<script setup>
import { ref, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import api from '@/utils/api'
import CouponItem from '@/components/CouponItem.vue'
import PopGetAllowance from '@/components/PopGetAllowance.vue'
import PopStores from '@/components/PopStores.vue'
import SideMenu from '@/components/SideMenu.vue' // 导入SideMenu组件
import { showDialog } from 'vant' // 导入Toast组件
import WechatUtils,{ WechatLocation } from '@/utils/wechat'
import { useUserStore } from '@/stores/user';
// 获取路由参数
const route = useRoute()
const productId = ref(route.params.id)
// 产品详情数据
const productDetail = ref(null)
const loading = ref(true)
// 定义tabs激活状态(初始值根据业务需求设置,示例为'1'
const content_active = ref('1')
const count_time = ref(0);
const content_list = ref([])
const banner_list = ref([])
const btn_info = ref({})
// 获取产品详情
async function getProductDetail() {
try {
loading.value = true
const res = await api.wechatAPI.getProductDetail(productId.value)
if (res.code === 200 && res.data) {
productDetail.value = res.data
// 更新轮播图数据
banner_list.value = productDetail.value.imgs.map((img, index) => ({
img,
id: index
}))
// count_time.value = res.data.timeEnd
count_time.value = Number(30 * 24*60*60*1000)
btn_info.value = productDetail.value.coupons.btn_info
// 更新内容标签页数据
content_list.value = [
{
title: '活动流程',
content: productDetail.value.coupons?.activityProcess || '暂无内容'
},
{
title: '使用规则',
content: productDetail.value.coupons?.rule || '暂无内容'
},
{
title: '审核标准',
content: productDetail.value.coupons?.checkStandard || '暂无内容'
},
{
title: '常见问题',
content: productDetail.value.coupons?.FAQ || '暂无内容'
}
]
} else {
console.error('获取产品详情失败:', res.message)
}
} catch (error) {
console.error('获取产品详情异常:', error)
} finally {
loading.value = false
}
}
function handleSuccess(){
showDialog({
title: '领取成功!',
message: '稍后会有电话客服与您联系,协助您完成补贴申领。',
}).then(() => {
});
getProductDetail()
}
// 页面加载时获取产品详情
onMounted(async () => {
let appid = localStorage.getItem('app_id')
if(appid) {
const wechat = await WechatUtils.init(appid);
// 初始化完成后获取位置信息
await getCurrentLocation();
}
getProductDetail()
})
// 监听 路由
watch(() => route.params.id, async (newId, oldId) => {
if (newId !== oldId) {
productId.value = newId
await getProductDetail()
}
})
const cityInfo = ref({
cityId: '',
cityName: ''
})
/**
* 获取当前位置并解析城市编码
*/
const getCurrentLocation = async () => {
try {
// 获取当前位置
const location = localStorage.getItem('userLocation')?JSON.parse(localStorage.getItem('userLocation')):await WechatLocation.getLocation('gcj02');
console.log('当前位置:', location);
const userStore = useUserStore();
// 解析位置获取城市信息
if (location && location.latitude && location.longitude) {
if(localStorage.getItem('cityInfo')){
// cityInfo.value = JSON.parse(localStorage.getItem('cityInfo'));
// console.log('城市信息:', cityInfo.value);
// if (cityInfo.value.cityId) {
// userStore.setCity(cityInfo.value);
// query_data.cityId = cityInfo.value.cityId;
// // 获取产品列表
// empty.value = false
// await getProductList();
// }}
}else{
const result = await api.wechatAPI.getLocationCity(location.latitude, location.longitude);
if (result.code === 200 && result.data) {
cityInfo.value = result.data;
console.log('城市信息:', cityInfo.value);
localStorage.setItem('cityInfo', JSON.stringify(cityInfo.value));
localStorage.setItem('userLocation', JSON.stringify({...location,time:new Date().getTime()}));
// 设置城市ID到查询参数
if (cityInfo.value.cityId) {
userStore.setCity(cityInfo.value);
// query_data.cityId = cityInfo.value.cityId;
// 获取产品列表
empty.value = false
await getProductList();
}
}
}
}
} catch (error) {
console.error('获取位置或解析城市失败:', error);
}
};
const showPop = ref(false)
function handleShowPop(val) {
showPop.value = val
}
function onCountFinish(e) {
console.log('onCountFinish' ,e);
}
// 补充门店弹窗控制变量
const showStorePop = ref(false)
// 补充门店列表数据(示例数据,根据实际业务调整)
// 补充门店弹窗关闭方法
function handleShowStorePop(val) {
showStorePop.value = val
}
</script>
<style>
.count-down-colon {
display: inline-block;
margin: 0 4px;
color: #f00;
}
.count-down-block {
display: inline-block;
width: 44px;
height: 38px;
color: #fff;
font-size: 24px;
text-align: center;
background-color: #f00;
border-radius: 8px;
}
.loading-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
+70
View File
@@ -0,0 +1,70 @@
<template>
<div class="my-page relative" style="min-height: 100vh;">
<div class="my-bg absolute left-0 top-0 right-0 bottom-0" />
<div class="my-info text-center pt120 relative">
<van-image class="imgsize-160X160" :src="avatar_img" round />
<p class="font-36 mt30">{{user_name}}</p>
</div>
<div class="my-menu inner20 box-shadow-darkGray ulib-r20 ml30 mr30 mt100 overflowhidden">
<template v-for="(item,index) in list" :key="index">
<van-cell v-if="item.type==1" :title="item.title" is-link :to="item.url" />
<van-cell v-if="item.type==2" :title="item.title" is-link @click="handlePhoneCall(item)" />
</template>
</div>
<SideMenu />
</div>
</template>
<script setup>
const handlePhoneCall = (item) => {
// 唤起打电话功能,item.url应为电话号码
if (item.url) {
window.location.href = `tel:${item.url}`;
}
};
import { ref } from 'vue'
import SideMenu from '@/components/SideMenu.vue' // 导入SideMenu组件
import { onMounted } from 'vue'
import api from '@/utils/api'
// 声明组件名称(可选,用于devtools)
defineOptions({ name: 'My' })
// 声明响应式数据(Vue 3使用ref/reactive替代data选项)
const avatar_img = ref('')
const user_name = ref('')
const list = ref([])
const userInfo = ref({})
const loading = ref(true)
async function getUserInfo() {
try {
// const res = await api.getUserInfo()
const res = await api.get('/auto/ucenter');
if(res.code){
userInfo.value = res.data.user_info
avatar_img.value = userInfo.value.avatar
user_name.value = userInfo.value.username
list.value = res.data.menu_list
}
} finally {
loading.value = false
}
}
onMounted(() => {
getUserInfo()
})
</script>
<style>
.my-bg{
width: 100vw;
background-size: 100% auto;
background-position: top center;
background-repeat: no-repeat;
background-image: url('/src/assets/my-bg.jpg')
}
</style>
+195
View File
@@ -0,0 +1,195 @@
<template>
<div class="my-page relative" style="min-height: 100vh;">
<div v-if="is_first_load" class="loading relative">
<PageInitLoading />
</div>
<div v-else class="ml30 mr30 pt30 pb60">
<van-empty v-if="empty" description="暂无数据" />
<!-- <van-list v-else v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad"> -->
<div v-else-if="!is_show">
<template v-for="(item, index) in list" :key="index">
<div class="relative my-allowance-item box-shadow-darkGray mb40 ulib-r20 overflowhidden">
<div class="bg-f2 pl20 pr20 pt15 pb15 color-666">
<p class="font-24" style="word-break:break-all;">订单编号: {{item.sid}}</p>
</div>
<div class="pt20 pb20 pl30 pr30">
<div class="fn-flex">
<div class="ulib-r20 overflowhidden">
<van-image class="imgsize-200X150 block" :fit="'cover'"
:src="item.logo" />
</div>
<div class="fn-flex-item fn-flex fn-flex-column justify-between ml30">
<h4 class="font-28 font-bold" v-if="item.price">补贴金额<span class="font-34 text-color-theme ml10">{{item.price}}</span></h4>
<div>
<p class="font-24 fn-flex" v-if="item.biz"><span class="wp30 color-999">城市门店</span><span
class="fn-flex-item">{{item.biz}}</span></p>
<p class="font-24 fn-flex mt10" v-if="item.car"><span class="wp30 color-999">品牌车型</span><span
class="fn-flex-item">{{item.car}}</span></p>
</div>
</div>
</div>
<div class="mt20">
<van-steps :active="item.step" active-color="#f84803" active-icon="arrow-down">
<van-step v-for="(it,idx) in item.progress" :key="idx" @click.stop="handleClickStep(idx,item.step,item.id)">{{it}}</van-step>
</van-steps>
</div>
<div class="mt20 text-right" v-if="item.btn_info&&Number(item.btn_info.show)">
<van-button class="pl35 pr35" type="danger" plain size="small" round @click="handleGoToLink(item.btn_info.id)">提交资料</van-button>
</div>
</div>
</div>
</template>
</div>
<van-list v-else v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<template v-for="(item, index) in list" :key="index">
<div class="relative my-allowance-item box-shadow-darkGray mb40 ulib-r20 overflowhidden">
<div class="bg-f2 pl20 pr20 pt15 pb15 color-666">
<p class="font-24" style="word-break:break-all;">订单编号: {{item.sid}}</p>
</div>
<div class="pt20 pb20 pl30 pr30">
<div class="fn-flex">
<div class="ulib-r20 overflowhidden">
<van-image class="imgsize-200X150 block" :fit="'cover'"
:src="item.logo" />
</div>
<div class="fn-flex-item fn-flex fn-flex-column justify-between ml30">
<h4 class="font-28 font-bold" v-if="item.price">补贴金额<span class="font-34 text-color-theme ml10">{{item.price}}</span></h4>
<div>
<p class="font-24 fn-flex" v-if="item.biz"><span class="wp30 color-999">城市门店</span><span
class="fn-flex-item">{{item.biz}}</span></p>
<p class="font-24 fn-flex mt10" v-if="item.car"><span class="wp30 color-999">品牌车型</span><span
class="fn-flex-item">{{item.car}}</span></p>
</div>
</div>
</div>
<div class="mt20">
<van-steps :active="item.step" active-color="#f84803" active-icon="arrow-down">
<van-step v-for="(it,idx) in item.progress" :key="idx" @click.stop="handleClickStep(idx,item.step,item.id)">{{it}}</van-step>
</van-steps>
</div>
<div class="mt20 text-right" v-if="item.btn_info&&Number(item.btn_info.show)">
<van-button class="pl35 pr35" type="danger" plain size="small" round @click="handleGoToLink(item.btn_info.id)">提交资料</van-button>
</div>
</div>
</div>
</template>
</van-list>
</div>
<SideMenu :name="'我的'"/>
</div>
</template>
<script setup>
import api from '@/utils/api'
import { ref, onMounted } from 'vue'
import PageInitLoading from '@/components/PageInitLoading.vue'
import SideMenu from '@/components/SideMenu.vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const list = ref([]);
const loading = ref(false);
const finished = ref(false);
const totalCount = ref(0);
const page = ref(1);
const empty = ref(false);
const is_show = ref(0)
const is_first_load = ref(true)
const onLoad = async () => {
await getMySubidy()
};
const getMySubidy = async () => {
loading.value = true;
try {
const response = await api.get('/auto/ucenter/subsidy', {
page: page.value,
size: 100
});
if (response.code === 200) {
if (page.value === 1) {
list.value = [];
if(response.data.list.length===0){
empty.value = true;
}
}
list.value = response.data.list.concat(list.value);
totalCount.value = response.data.count;
is_show.value = Number(response.data.show)
if (list.value.length >= totalCount.value) {
finished.value = true;
}
page.value++;
} else {
showToast(response.message || '获取补贴列表失败');
}
} catch (error) {
console.error('获取补贴列表异常:', error);
showToast('网络异常,请稍后重试');
} finally {
is_first_load.value = false;
loading.value = false;
}
};
// 在组件挂载时调用
onMounted( async () => {
await getMySubidy()
});
const handleClickStep = (index,cur_step,id) => {
if (Number(cur_step) === Number(index)&&Number(index)===1) {
handleGoToLink(id)
}
};
const handleGoToLink = (id) => {
if(id){
router.push({ path: '/my/allowance/form', query: { id } })
}
}
const aaa = (e) => {
console.log(e);
}
</script>
<style scoped lang="scss">
.ulib-rtl20 {
border-top-left-radius: 20px;
}
.ulib-rbr20 {
border-bottom-right-radius: 20px;
}
.my-allowance-item {
::v-deep {
.van-steps {
.van-step {
padding-top: 20px;
/* .van-step__title{
font-size: 24px;
} */
}
}
.van-steps--horizontal{
.van-steps__items{
padding-bottom: 0;
}
.van-step__circle-container{
top: 0;
}
.van-step__line{
top: 0;
}
}
}
}
</style>
+663
View File
@@ -0,0 +1,663 @@
<template>
<div class="ml30 mr30" style="min-height:100vh;">
<div class="">
<van-form @submit="onSubmit" :rules="rules">
<div class="fn-flex fn-flex-column" style="min-height:100vh;">
<div class="fn-flex-item pt30">
<div class="box-shadow-darkGray inner10 ulib-r20 pb30">
<!-- 购车城市 -->
<van-field label="购车城市" :border="false" input-align="right" placeholder="请选择购车城市" v-model="form.city" name="area" readonly
is-link @click="showCityPicker" />
<!-- 购车门店必填 -->
<van-field name="store" :border="false" label="购车门店" input-align="right" placeholder="请选择购车门店" v-model="form.store" readonly is-link
@click="showStorePicker" :rules="[{ required: true, message: '请选择购车门店' }]" />
<!-- 品牌车型必填 -->
<van-field name="model" :border="false" label="品牌车型" input-align="right" placeholder="请选择品牌车型" v-model="form.model" readonly is-link
@click="showModelPicker" :rules="[{ required: true, message: '请选择品牌车型' }]" />
<!-- 上传发票必填 -->
<van-cell title="上传发票" :border="false">
<template #value>
<a href="javascript:void(0)" @click="showPopContent(allowance_invice_info,2)" class="view-example"><span class="font-26 mr10">查看示例</span><van-icon size="16" name="arrow" /></a>
</template>
</van-cell>
<div class="upload-box ml20 mr20">
<van-uploader v-model="form.invoiceFile" :multiple="false" :max-count="1" accept="image/*" :after-read="onInvoiceRead">
<template #preview-cover="{ file }">
<div class="preview-cover van-ellipsis">{{ file.name }}</div>
</template>
<div class="fn-flex fn-flex-column fn-flex-center mt30">
<i class="icon-custom icon-file"></i>
<div class="fn-flex fn-flex-center mt10" style="gap: 10px;">
<van-button type="default" size="mini" round style="padding:1.2vw 2vw;">上传发票</van-button>
<!-- <van-button type="primary" size="mini" round style="padding:1.2vw 2vw;" @click="onWechatInvoiceUpload">微信上传</van-button> -->
</div>
</div>
</van-uploader>
</div>
<!-- 上传商业保险单必填 -->
<van-cell title="上传商业保险单" :border="false">
<template #value>
<a href="javascript:void(0)" @click="showPopContent(allowance_insuranc_info,2)" class="view-example"><span class="font-26 mr10">查看示例</span><van-icon size="16" name="arrow" /></a>
</template>
</van-cell>
<div class="upload-box ml20 mr20">
<van-uploader v-model="form.insuranceFile" :multiple="false" :max-count="1" accept="image/*" :after-read="onInsuranceRead">
<template #preview-cover="{ file }">
<div class="preview-cover van-ellipsis">{{ file.name }}</div>
</template>
<div class="fn-flex fn-flex-column fn-flex-center mt30">
<i class="icon-custom icon-file"></i>
<div class="fn-flex fn-flex-center mt10" style="gap: 10px;">
<van-button type="default" size="mini" round style="padding:1.2vw 2vw;">上传保险单</van-button>
<!-- <van-button type="primary" size="mini" round style="padding:1.2vw 2vw;" @click="onWechatInsuranceUpload">微信上传</van-button> -->
</div>
</div>
</van-uploader>
</div>
</div>
</div>
<div class="text-center pt40 pb30">
<!-- 协议 -->
<div class="agreement ml100 mr100 pb20" style="line-height: 1.6;">
提交即同意
<a v-for="(item,index) in allowance_bottom_info" :key="index" href="javascript:void(0)" @click="showPopContent(item,1)" class="agreement-link">{{item.title}}</a>
</div>
<!-- 提交按钮 -->
<van-button type="danger" round block native-type="submit" :loading="submitting">{{ submitting ? '提交中...' : '提交' }}</van-button>
</div>
</div>
<!-- 使用van-popup包装van-picker -->
<!-- <van-popup v-model="cityPickerVisible" position="bottom">
<van-picker :columns="cityColumns" @confirm="onCityConfirm" @cancel="cityPickerVisible = false" />
</van-popup> -->
<van-popup v-model:show="cityPickerVisible" destroy-on-close position="bottom">
<van-area :area-list="areaList" :model-value="pickerValue" :columns-num="2" @confirm="onConfirm" @cancel="showArea = false" />
</van-popup>
<van-popup v-model:show="storePickerVisible" destroy-on-close position="bottom">
<van-picker :columns="storeColumns" @confirm="onStoreConfirm" @cancel="storePickerVisible = false" />
</van-popup>
<van-popup v-model:show="modelPickerVisible" destroy-on-close position="right" :style="{ width: '80%', height: '100%' }">
<BrandList :is-sticky="false" @brandItem="handleBrandItem"/>
</van-popup>
<!-- 车系选择弹窗 -->
<van-popup v-model:show="seriesPickerVisible" destroy-on-close position="bottom">
<van-picker :columns="seriesColumns" @confirm="onSeriesConfirm" @cancel="seriesPickerVisible = false" />
</van-popup>
</van-form>
</div>
<PopContent :content="content" :img="guide_img" :show-pop="showContentPop" @update:show-pop="showContentPop = $event" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { showConfirmDialog, showToast } from 'vant';
import { areaList } from '@vant/area-data';
import BrandList from '../components/BrandList.vue' // 导入BrandList组件
import PopContent from '@/components/PopContent.vue' // 导入PopContent组件
import api from '../utils/api.js' // 导入API
import WechatUtils, { WechatImage } from '../utils/wechat.js' // 导入微信工具
import { getBasicConfig } from '@/utils/basicSetting'
const route = useRoute();
const router = useRouter();
// 获取补贴ID(从路由参数或查询参数中获取)
const subsidyId = ref(route.params.id || route.query.id || '');
// 表单数据
const form = reactive({
city: '',
cityId: '',
store: '',
storeId: '',
model: '',
brandId: '',
seriesId: '',
invoiceFile: [],
insuranceFile: [],
invoiceUrl: '',
insuranceUrl: ''
});
// 选择器可见性
const cityPickerVisible = ref(false);
const storePickerVisible = ref(false);
const modelPickerVisible = ref(false);
const seriesPickerVisible = ref(false);
// 提交状态
const submitting = ref(false);
// 选择器选项
const cityColumns = ref([]);
const storeColumns = ref([]);
const modelColumns = ref([]);
const seriesColumns = ref([]);
// 校验规则
const rules = {
store: [{ required: true, message: '请选择购车门店' }],
model: [{ required: true, message: '请选择品牌车型' }],
invoiceFile: [{ validator: (val) => val && val.length > 0, message: '请上传发票' }],
insuranceFile: [{ validator: (val) => val && val.length > 0, message: '请上传商业保险单' }],
};
// 组件挂载时检查补贴ID
onMounted( async() => {
if (!subsidyId.value) {
showToast('缺少补贴ID参数');
console.warn('补贴ID未找到,请检查路由参数');
}
await getGuideInfo()
});
// API方法定义
/**
* 获取门店列表
* @param {number} cityId - 城市ID
*/
const getStoreList = async (cityId) => {
try {
const response = await api.get('/auto/biz', { cityId });
if (response.code === 200) {
return response.data;
} else {
console.error('获取门店列表失败:', response.message);
return [];
}
} catch (error) {
console.error('获取门店列表异常:', error);
return [];
}
};
/**
* 获取品牌列表
*/
const getBrandList = async () => {
try {
const response = await api.get('/auto/car/brand');
if (response.code === 200) {
return response.data;
} else {
console.error('获取品牌列表失败:', response.message);
return {};
}
} catch (error) {
console.error('获取品牌列表异常:', error);
return {};
}
};
/**
* 获取车系列表
* @param {number} brandId - 品牌ID
* @param {number} page - 页码
* @param {number} size - 分页大小
*/
const getSeriesList = async (brandId, page = 1, size = 100) => {
try {
const response = await api.get('/auto/brand/series', {
brand_id: brandId,
page,
size
});
if (response.code === 200) {
return response.data;
} else {
console.error('获取车系列表失败:', response.message);
return { list: [], count: 0 };
}
} catch (error) {
console.error('获取车系列表异常:', error);
return { list: [], count: 0 };
}
};
/**
* 上传图片
* @param {File} file - 图片文件
*/
const uploadImage = async (file) => {
try {
const formData = new FormData();
formData.append('file', file);
const response = await api.upload(formData, { headers: { 'Content-Type': 'multipart/form-data' } });
if (response.code === 200) {
return response.data;
} else {
console.error('上传图片失败:', response.message);
return null;
}
} catch (error) {
console.error('上传图片异常:', error);
return null;
}
};
/**
* 使用微信JS-SDK选择并上传图片
* @param {string} type - 图片类型 'invoice' | 'insurance'
*/
const chooseAndUploadWechatImage = async (type) => {
try {
// 检查是否在微信浏览器中
if (!window.wx) {
showToast('请在微信中打开');
return;
}
// 选择图片
const localIds = await WechatImage.chooseImage({
count: 1, // 只选择一张图片
sizeType: ['compressed'], // 使用压缩图
sourceType: ['album', 'camera'] // 可以指定来源是相册还是相机
});
if (localIds && localIds.length > 0) {
const localId = localIds[0];
// 上传图片到微信服务器
const serverId = await WechatImage.uploadImage(localId);
if (serverId) {
// 调用后端接口,将微信服务器的图片下载到自己的服务器
const response = await api.post('/auto/upload/wechat', {
serverId: serverId
});
if (response.code === 0) {
// 根据类型更新对应的表单字段
if (type === 'invoice') {
form.invoiceUrl = response.data.url;
form.invoiceFile = [{
url: response.data.url,
name: '发票图片',
isImage: true
}];
showToast('发票上传成功');
} else if (type === 'insurance') {
form.insuranceUrl = response.data.url;
form.insuranceFile = [{
url: response.data.url,
name: '保险单图片',
isImage: true
}];
showToast('保险单上传成功');
}
console.log(`${type}上传成功:`, response.data);
} else {
showToast(response.message || '图片上传失败');
}
} else {
showToast('图片上传到微信服务器失败');
}
}
} catch (error) {
console.error('微信图片上传失败:', error);
showToast('图片上传失败,请重试');
}
};
/**
* 发票微信上传处理
*/
const onWechatInvoiceUpload = () => {
chooseAndUploadWechatImage('invoice');
};
/**
* 保险单微信上传处理
*/
const onWechatInsuranceUpload = () => {
chooseAndUploadWechatImage('insurance');
};
/**
* 提交审核资料
* @param {Object} submitData - 提交的数据
*/
const submitSubsidyData = async (submitData) => {
try {
const response = await api.post('/auto/subsidy', {
...submitData
});
if (response.code === 200) {
return response;
} else {
throw new Error(response.message || '提交失败');
}
} catch (error) {
console.error('提交审核资料异常:', error);
throw error;
}
};
// 城市选择确认
// const onCityConfirm = (value) => {
// form.city = value[0];
// cityPickerVisible.value = false;
// loadStoresByCity(form.city);
// };
// 门店选择确认
const onStoreConfirm = (value) => {
form.store = value.selectedOptions[0].text;
form.storeId = value.selectedOptions[0].value;
storePickerVisible.value = false;
};
// 品牌选择确认
const handleBrandItem = async (brandInfo) => {
form.model = brandInfo.name || brandInfo;
form.brandId = brandInfo.id;
modelPickerVisible.value = false;
// 选择品牌后,加载对应的车系列表
if (brandInfo.id) {
await loadSeriesByBrand(brandInfo.id);
seriesPickerVisible.value = true;
}
};
// 车系选择确认
const onSeriesConfirm = (value) => {
const seriesName = value.selectedOptions[0].text;
const seriesId = value.selectedOptions[0].value;
// 将品牌和车系组合显示
form.model = `${form.model} ${seriesName}`;
form.seriesId = seriesId;
seriesPickerVisible.value = false;
};
// 显示选择器
const showCityPicker = () => (cityPickerVisible.value = true);
const pickerValue = ref('');
const onConfirm = async ({ selectedValues, selectedOptions }) => {
console.log('选择的值:', selectedValues);
console.log('选择的选项:', selectedOptions);
pickerValue.value = selectedValues.length
? selectedValues[selectedValues.length - 1]
: '';
cityPickerVisible.value = false;
form.city = selectedOptions.map((item) => item.text).join('/');
form.cityId = selectedValues[selectedValues.length - 1]; // 获取最后一级的城市ID
console.log(form.city); // 打印选择的城市
// 选择城市后加载门店列表
await loadStoresByCity(form.cityId);
};
const showStorePicker = () => {
if (!form.cityId) {
showToast('请先选择城市');
return;
}
if(!storeColumns.value.length){
showToast('当前城市无可用门店');
return;
}
storePickerVisible.value = true;
};
const showModelPicker = () => (modelPickerVisible.value = true);
// 加载门店列表
const loadStoresByCity = async (cityId) => {
if (!cityId) return;
const storeData = await getStoreList(cityId);
if (storeData && storeData.list) {
storeColumns.value = storeData.list.map(store => ({
text: store.name,
value: store.id
}));
} else {
storeColumns.value = [];
}
};
// 加载车系列表
const loadSeriesByBrand = async (brandId) => {
if (!brandId) return;
const seriesData = await getSeriesList(brandId);
if (seriesData && seriesData.list) {
seriesColumns.value = seriesData.list.map(series => ({
text: series.name,
value: series.id
}));
} else {
seriesColumns.value = [];
}
};
// 发票上传处理
const onInvoiceRead = async (file) => {
console.log('上传发票:', file);
const uploadResult = await uploadImage(file.file);
if (uploadResult) {
form.invoiceUrl = uploadResult.url;
console.log('发票上传成功:', uploadResult);
} else {
showToast('发票上传失败');
}
};
// 保险单上传处理
const onInsuranceRead = async (file) => {
console.log('上传保险单:', file);
const uploadResult = await uploadImage(file.file);
if (uploadResult) {
form.insuranceUrl = uploadResult.url;
console.log('保险单上传成功:', uploadResult);
} else {
showToast('保险单上传失败');
}
};
// 验证表单数据
const validateForm = () => {
const errors = [];
if (!subsidyId.value) {
errors.push('缺少补贴ID');
}
if (!form.cityId) {
errors.push('请选择购车城市');
}
if (!form.storeId) {
errors.push('请选择购车门店');
}
if (!form.brandId) {
errors.push('请选择品牌');
}
if (!form.seriesId) {
errors.push('请选择车系');
}
if (!form.invoiceUrl) {
errors.push('请上传发票');
}
if (!form.insuranceUrl) {
errors.push('请上传商业保险单');
}
return errors;
};
// 提交处理
const onSubmit = async (values) => {
console.log('提交数据:', values);
console.log('完整表单数据:', form);
// 验证表单
const errors = validateForm();
if (errors.length > 0) {
showToast(errors[0]);
return;
}
// 显示确认弹窗
try {
await showConfirmDialog({
title: '确认提交',
message: '确定要提交审核资料吗?提交后将无法修改。',
confirmButtonText: '确定提交',
cancelButtonText: '取消',
});
// 用户确认后开始提交
submitting.value = true;
const submitData = {
id: subsidyId.value,
bizId: form.storeId,
cityId: form.cityId,
brandId: form.brandId,
seriesId: form.seriesId,
billImg: form.invoiceUrl,
businessImg: form.insuranceUrl
};
console.log('提交参数:', submitData);
const result = await submitSubsidyData(submitData);
showToast('提交成功!');
// 提交成功后跳转到我的补贴页面
setTimeout(() => {
router.replace('/my/allowance');
}, 1500);
} catch (error) {
if (error === 'cancel') {
// 用户取消了提交
return;
}
console.error('提交失败:', error);
showToast(error.message || '提交失败,请重试');
} finally {
submitting.value = false;
}
};
const showContentPop = ref(false);
const content = ref('');
const allowance_bottom_info = ref([])
const allowance_invice_info = ref({})
const allowance_insuranc_info = ref({})
const guide_img = ref('')
const getGuideInfo = async () => {
allowance_bottom_info.value = await getBasicConfig('allowance_bottom')
allowance_invice_info.value = await getBasicConfig('allowance_invoice')
allowance_insuranc_info.value = await getBasicConfig('allowance_insuranc')
}
const showPopContent = (item,type=1) => {
if(!item.content) return
showContentPop.value = true;
content.value = ''
guide_img.value = ''
if(type==1){
content.value = item.content;
guide_img.value = '';
}else if(type==2){
content.value = '';
guide_img.value = item.content;
}
};
</script>
<style scoped lang="scss">
.upload-box {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
/* width: 100%; */
height: 260px;
background-color: #f9f9f9;
::v-deep{
.van-uploader{
width:100%;
height: 100%;
.van-uploader__wrapper{
width: 100%;height: 100%;
overflow: hidden;
}
.van-uploader__preview{
// margin-top: 3vw;
margin: 0;
}
.van-uploader__preview-image{
width: 100%;
height: 100%;
}
.van-uploader__input-wrapper{
width: 100%;
}
// width: 100%;
}
}
}
.upload-text {
margin-top: 10px;
}
.view-example {
color: #527acc;
font-size: 26px;
display: block;
}
.agreement {
text-align: center;
// margin: 20px 0;
font-size: 26px;
}
.agreement-link {
color: #527acc;
margin: 0 5px;
display: inline-block;
}
.van-field__label {
width: 100px;
}
</style>
+175
View File
@@ -0,0 +1,175 @@
<template>
<div class="my-page relative" style="min-height: 100vh;">
<div v-if="is_first_load" class="loading relative">
<PageInitLoading />
</div>
<div v-else class="ml30 mr30 pt30 pb60">
<van-empty v-if="empty" description="暂无数据" />
<div v-else-if="!is_show">
<template v-for="(item, index) in list" :key="index">
<div class="my-coupon-item box-shadow-darkGray mb30 inner30 ulib-r20">
<CouponItem
:price-num="item.price"
:desc-left="'活动规则'"
:is-desc-link="true"
:title="item.typeCn"
:desc-right="item.timeStart+'-'+item.timeEnd"
:is-active="!Number(item.btText.status)"
:date-rule="item.rule"
:data-index="index"
:index="index"
@goLink="goLink"
/>
<div class="fn-flex fn-flex-center mt30">
<div class="fn-flex-item">
<h4 :class="['font-30',!Number(item.btText.status)?'':'color-666']">{{ item.title }}</h4>
<p class="font-24 mt15" @click="handleShowStores(item)">
<span class="color-999">{{item.bizTip}}</span>
<span v-if="0" :class="[!Number(item.btText.status)?'text-color-theme':'color-999']">5</span>
<span v-if="0" :class="[!Number(item.btText.status)?'':'color-666']">家门店</span><van-icon name="arrow" />
</p>
</div>
<div class="ml15">
<van-button class="ulib-r100" size="small" :disabled="Number(item.btText.status)" :type="!Number(item.btText.status)?'danger':'info'" round @click.stop="bindShowCode(item)">{{ item.btText.txt }}</van-button>
</div>
</div>
</div>
</template>
</div>
<van-list v-else v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<template v-for="(item, index) in list" :key="index">
<div class="my-coupon-item box-shadow-darkGray mb30 inner30 ulib-r20">
<CouponItem
:price-num="item.price"
:desc-left="'活动规则'"
:is-desc-link="true"
:title="item.typeCn"
:desc-right="item.timeStart+'-'+item.timeEnd"
:is-active="!Number(item.btText.status)"
:date-rule="item.rule"
:data-index="index"
:index="index"
@goLink="goLink"
/>
<div class="fn-flex fn-flex-center mt30">
<div class="fn-flex-item">
<h4 :class="['font-30',!Number(item.btText.status)?'':'color-666']">{{ item.title }}</h4>
<p class="font-24 mt15" @click="handleShowStores(item)">
<span class="color-999">{{item.bizTip}}</span>
<span v-if="0" :class="[!Number(item.btText.status)?'text-color-theme':'color-999']">5</span>
<span v-if="0" :class="[!Number(item.btText.status)?'':'color-666']">家门店</span><van-icon name="arrow" />
</p>
</div>
<div class="ml15">
<van-button class="ulib-r100" size="small" :disabled="Number(item.btText.status)" :type="!Number(item.btText.status)?'danger':'info'" round @click.stop="bindShowCode(item)">{{ item.btText.txt }}</van-button>
</div>
</div>
</div>
</template>
</van-list>
<PopCode :title="popCodeTitle" :code="code" :show-pop="showCodePop" @update:show-pop="showCodePop = $event" />
<PopContent :content="content" :show-pop="showContentPop" @update:show-pop="showContentPop = $event" />
<PopStores @update:showPop="handleShowStorePop" :show-pop="showStorePop" :coupons="cur_coupons" :id="cur_coupon_id" />
</div>
<SideMenu :name="'我的'"/>
</div>
</template>
<script setup>
import CouponItem from '@/components/CouponItem.vue'
import PopCode from '@/components/PopCode.vue'
import PopContent from '../components/PopContent.vue'
import PopStores from '@/components/PopStores.vue'
import PageInitLoading from '@/components/PageInitLoading.vue'
import SideMenu from '@/components/SideMenu.vue' // 导入SideMenu组件
import api from '@/utils/api'
import { ref, onMounted } from 'vue'
const showCodePop = ref(false);
const showContentPop = ref(false);
const popCodeTitle = ref('');
const code = ref('');
const content = ref('');
const list = ref([]);
const loading = ref(false);
const finished = ref(false);
const totalCount = ref(0);
const page = ref(1);
const empty = ref(false);
const is_show = ref(0)
const is_first_load = ref(true)
onMounted(async () => {
await getMyCoupon()
});
const onLoad = async () => {
await getMyCoupon()
};
const getMyCoupon = async () => {
loading.value = true;
try {
const response = await api.get('/auto/ucenter/coupons', {
page: page.value,
size: 20
});
if (response.code === 200) {
if (page.value === 1) {
list.value = [];
if(response.data.list.length === 0){
empty.value = true;
}
}
list.value = response.data.list.concat(list.value);
totalCount.value = response.data.count;
is_show.value = Number(response.data.show)
if (list.value.length >= totalCount.value) {
finished.value = true;
}
page.value++;
} else {
showToast(response.message || '获取补贴列表失败');
}
} catch (error) {
console.error('获取补贴列表异常:', error);
showToast('网络异常,请稍后重试');
} finally {
is_first_load.value = false;
loading.value = false;
}
};
const goLink = (index) => {
content.value = list.value[index].rule;
showContentPop.value = true;
};
const bindShowCode = (item) => {
code.value = item.sid;
popCodeTitle.value = item.title;
showCodePop.value = true;
};
const cur_coupons = ref(null)
const cur_coupon_id = ref(0)
// 补充门店弹窗控制变量
const showStorePop = ref(false)
// 补充门店列表数据(示例数据,根据实际业务调整)
// 补充门店弹窗关闭方法
function handleShowStorePop(val) {
showStorePop.value = val
}
const handleShowStores = (item) => {
cur_coupons.value = item.coupons
cur_coupon_id.value = item.couponId
showStorePop.value = true
};
</script>
<style></style>
+136
View File
@@ -0,0 +1,136 @@
<template>
<div class="my-page relative" style="min-height: 100vh;">
<div v-if="is_first_load" class="loading relative">
<PageInitLoading />
</div>
<div v-elsed class="ml30 mr30 pt30 pb60">
<van-empty v-if="empty" description="暂无数据" />
<div v-else-if="!is_show">
<template v-for="(item, index) in list" :key="index">
<div class="relative my-order-item box-shadow-darkGray mb40 ulib-r20 overflowhidden">
<div class="bg-f2 pl20 pr20 pt15 pb15 color-666"><p class="font-24" style="word-break:break-all;">订单编号: {{item.sid}}</p></div>
<div class="pt20 pb20 pl30 pr30">
<div class="fn-flex">
<div class="ulib-r20 overflowhidden">
<van-image class="imgsize-200X150 block" :fit="'cover'" :src="item.logo" />
</div>
<div class="fn-flex-item fn-flex fn-flex-column justify-between ml30">
<h4 class="font-30 font-bold">{{item.title}}</h4>
<div>
<p v-if="item.guide_price" class="font-24">指导价{{item.guide_price}}</p>
<p v-if="item.bill_price" class="font-24 mt10">开票价格<span class="font-34 text-color-theme">{{item.bill_price}}</span></p>
</div>
</div>
</div>
</div>
<div v-if="item.status" class="absolute right-0 bottom-0">
<div
class="pt10 pb10 pl20 pr20 ulib-rtl20 ulib-rbr20 font-20"
:style="{'background-color':'#79ccb9',color:'#fff'}"
>{{item.status}}</div>
</div>
</div>
</template>
</div>
<van-list v-else v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<template v-for="(item, index) in list" :key="index">
<div class="relative my-order-item box-shadow-darkGray mb40 ulib-r20 overflowhidden">
<div class="bg-f2 pl20 pr20 pt15 pb15 color-666"><p class="font-24" style="word-break:break-all;">订单编号: {{item.sid}}</p></div>
<div class="pt20 pb20 pl30 pr30">
<div class="fn-flex">
<div class="ulib-r20 overflowhidden">
<van-image class="imgsize-200X150 block" :fit="'cover'" :src="item.logo" />
</div>
<div class="fn-flex-item fn-flex fn-flex-column justify-between ml30">
<h4 class="font-30 font-bold">{{item.title}}</h4>
<div>
<p v-if="item.guide_price" class="font-24">指导价{{item.guide_price}}</p>
<!--
<p v-if="item.bill_price" class="font-24 mt10">开票价格<span class="font-34 text-color-theme">{{item.bill_price}}</span></p>
-->
</div>
</div>
</div>
</div>
<div v-if="item.status" class="absolute right-0 bottom-0">
<div
class="pt10 pb10 pl20 pr20 ulib-rtl20 ulib-rbr20 font-20"
:style="{'background-color':'#79ccb9',color:'#fff'}"
>{{item.status}}</div>
</div>
</div>
</template>
</van-list>
</div>
<SideMenu :name="'我的'"/>
</div>
</template>
<script setup>
import api from '@/utils/api'
import { ref, onMounted } from 'vue'
import PageInitLoading from '@/components/PageInitLoading.vue'
import SideMenu from '@/components/SideMenu.vue'
const list = ref([]);
const loading = ref(false);
const finished = ref(false);
const totalCount = ref(0);
const page = ref(1);
const empty = ref(false);
const is_show = ref(0)
const is_first_load = ref(true)
onMounted(async () => {
await getMyOrder()
});
const onLoad = async() => {
// 异步更新数据
await getMyOrder()
};
const getMyOrder = async() => {
loading.value = true;
try {
const response = await api.get('/auto/ucenter/orders', {
page: page.value,
size: 100
});
if (response.code === 200) {
if (page.value === 1) {
list.value = [];
if(response.data.list.length === 0){
empty.value = true;
}
}
list.value = response.data.list.concat(list.value);
totalCount.value = response.data.count;
is_show.value = Number(response.data.show)
if (list.value.length >= totalCount.value) {
finished.value = true;
}
page.value++;
} else {
showToast(response.message || '获取补贴列表失败');
}
} catch (error) {
console.error('获取补贴列表异常:', error);
showToast('网络异常,请稍后重试');
} finally {
is_first_load.value = false;
loading.value = false;
}
};
</script>
<style>
.ulib-rtl20{
border-top-left-radius: 20px;
}
.ulib-rbr20{
border-bottom-right-radius: 20px;
}
</style>
+23
View File
@@ -0,0 +1,23 @@
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../pages/Home.vue'
import About from '../pages/About.vue'
import My from '../pages/My.vue'
import Item from '../pages/Item.vue'
import MyCoupon from '../pages/MyCoupon.vue'
import MyOrder from '../pages/MyOrder.vue'
import MyAllowance from '../pages/MyAllowance.vue'
import MyAllowanceForm from '../pages/MyAllowanceForm.vue'
const routes = [
{ path: '/', name: 'Home', component: Home },
{ path: '/about', name: 'About', component: About },
{ path: '/my', name: 'My', component: My },
{ path: '/item/:id', name: 'Item', component: Item },
{ path: '/my/coupon', name: 'MyCoupon', component: MyCoupon },
{ path: '/my/order', name: 'MyOrder', component: MyOrder },
{ path: '/my/allowance', name: 'MyAllowance', component: MyAllowance },
{ path: '/my/allowance/form', name: 'MyAllowanceForm', component: MyAllowanceForm },
]
const router = createRouter({ history: createWebHistory(), routes })
export default router
+19
View File
@@ -0,0 +1,19 @@
import { defineStore } from 'pinia'
export const useBasicSettingStore = defineStore('basicSetting', {
state: () => ({ item_bottom: null, allowance_bottom: null, allowance_invoice: null, allowance_insuranc:null}),
actions: {
setItemBottom(data) {
this.item_bottom = data
},
setAllowanceBottom(data) {
this.allowance_bottom = data
},
setAllowanceInvoice(data) {
this.allowance_invoice = data
},
setAllowanceInsuranc(data) {
this.allowance_insuranc = data
}
}
})
+10
View File
@@ -0,0 +1,10 @@
import { defineStore } from 'pinia'
export const useBrandStore = defineStore('brand', {
state: () => ({ list: [] }),
actions: {
setList(list) {
this.list = list
}
}
})
+13
View File
@@ -0,0 +1,13 @@
import { defineStore } from 'pinia'
export const useCityStore = defineStore('city', {
state: () => ({ listByPinyin: [], listBySort: [] }),
actions: {
setByPinyin(list) {
this.listByPinyin = list
},
setBySort(list) {
this.listBySort = list
}
}
})
+20
View File
@@ -0,0 +1,20 @@
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({ cur_city:{}, user_info: {}, accountId:'',friend_account_id:'' }),
actions: {
setCity(data) {
this.cur_city = data
},
setUserInfo(data) {
this.user_info = data
},
setAccountId(data) {
this.accountId = data
},
setFriendAccountId(data) {
this.friend_account_id = data
},
}
})
+79
View File
@@ -0,0 +1,79 @@
/* :root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
} */
File diff suppressed because it is too large Load Diff
+349
View File
@@ -0,0 +1,349 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
+3
View File
@@ -0,0 +1,3 @@
$defaultFont: 16px;
// $defaultColor: #a90000;
$defaultColor: #4ca6ff;
+14
View File
@@ -0,0 +1,14 @@
@use '../base/_variable';
@use '../base/_reset';
@use '../base/_animate';
@use 'mobile/_border';
@use 'mobile/_box';
@use 'mobile/_btn';
@use 'mobile/_color';
@use 'mobile/_layout';
@use 'mobile/_text';
@use 'mobile/_font';
@use 'mobile/_iconfont';
@use 'mobile/_img';
@use 'mobile/mDialog';
@use 'mobile/_toast';
+38
View File
@@ -0,0 +1,38 @@
/*border*/
@use "sass:list";
.last-b-none:last-child{border-bottom:none;}
// .bts-20-f2{border-top: 20px solid #f2f2f2;}
$defaultBorderColorUnit: #{'#'};
@mixin border($dir,$color,$size,$type:solid) {
@if $dir == d {
.b#{$dir}s-#{$size}-#{$color}{border:$defaultBorderColorUnit+#{$color} #{$size}px #{$type};}
}
@else if $dir == l{
.b#{$dir}s-#{$size}-#{$color}{border-left:$defaultBorderColorUnit+#{$color} #{$size}px #{$type};}
}
@else if $dir == t{
.b#{$dir}s-#{$size}-#{$color}{border-top:$defaultBorderColorUnit+#{$color} #{$size}px #{$type};}
}
@else if $dir == r{
.b#{$dir}s-#{$size}-#{$color}{border-right:$defaultBorderColorUnit+#{$color} #{$size}px #{$type};}
}
@else if $dir == b{
.b#{$dir}s-#{$size}-#{$color}{border-bottom:$defaultBorderColorUnit+#{$color} #{$size}px #{$type};}
}
}
/*
增加需要的数值
(dir color size type)
*/
$defaultBorderArray:(d eb6100 1 solid)(d 00a58f 1 solid)(d ddd 1 solid)(d fff 1 solid)(t ddd 1 solid)(l ddd 1 solid)(r ddd 1 solid)(b ddd 1 solid)
(d eee 1 solid)(t eee 1 solid)(l eee 1 solid)(r eee 1 solid)(b eee 1 solid)
(d ff9393 2 solid)(t f6f6f6 20 solid)
(t f9f9f9 20 solid)(b fff 1 solid)(b f8f4df 1 solid)(t f2f2f2 20 solid)(d ffe3af 1 solid)(t f6b37f 1 solid)(d f6b07d 1 solid);
@each $i in $defaultBorderArray{
@include border(list.nth($i, 1),list.nth($i, 2),list.nth($i, 3),list.nth($i, 4))
}
+65
View File
@@ -0,0 +1,65 @@
/*layout con*/
@use "sass:list";
.inner5{padding:5px;}
.inner10{padding:10px;}
.inner20{padding:20px;}
.inner30{padding:30px;}
.inner40{padding:40px;}
.inner50{padding:50px;}
.ulib-r0{-webkit-border-radius:0 !important;border-radius:0 !important;}
.ulib-r5{-webkit-border-radius:5px;border-radius:5px;}
.ulib-r10{-webkit-border-radius:10px;border-radius:10px;}
.ulib-r20{-webkit-border-radius:20px;border-radius:20px;}
.ulib-rt20{
border-top-left-radius: 20px;
border-top-right-radius: 20px;
}
.ulib-r750{-webkit-border-radius:750px;border-radius:750px;}
@mixin box($type,$size) {
@if $type == m{
.#{$type}l#{$size}{
margin-left: #{$size * 1px};
}
.#{$type}t#{$size}{
margin-top: #{$size * 1px};
}
.#{$type}r#{$size}{
margin-right: #{$size * 1px};
}
.#{$type}b#{$size}{
margin-bottom: #{$size * 1px};
}
}
@else if $type == p{
.#{$type}l#{$size}{
padding-left: #{$size * 1px};
}
.#{$type}t#{$size}{
padding-top: #{$size * 1px};
}
.#{$type}r#{$size}{
padding-right: #{$size * 1px};
}
.#{$type}b#{$size}{
padding-bottom: #{$size * 1px};
}
}
}
@for $i from 0 through 14{
@include box(m,5 * $i);
@include box(p,5 * $i);
}
/*
增加需要的数值
(type size)
*/
$defaultBoxArray: (p 80)(p 90)(p 110)(p 120)(p 130)(p 140)(p 160)(p 170)(p 180)(p 190)(p 200)(p 220)(m 130)(m 70)(m 75)(m 80)(m 90)(m 95)(m 100)(m 110)(m 140)(m 160)(m 170)(m 180)(m 200)(m 210)(m 230)(m 260)(m 280)(m 310)(m 180)(m 430);
@each $i in $defaultBoxArray{
@include box(list.nth($i, 1),list.nth($i, 2));
}
+3
View File
@@ -0,0 +1,3 @@
.btn{display:inline-block;font-size:15px;text-align:center;border:none;vertical-align:middle;cursor:pointer;-moz-transition:all .15s ease 0s;-webkit-transition:all .15s ease 0s;-o-transition:all .15s ease 0s;transition:all .15s ease 0s;}
.btn:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125);}
.btn[disabled]{background-color:#aaa;color:#777;}
+16
View File
@@ -0,0 +1,16 @@
/*bg*/
.bg-fff-op30{background-color: rgba($color: #fff, $alpha: .3);}
.bg-000-op60{background-color: rgba($color: #000, $alpha: .6);}
.bg-000-op50{background-color: rgba($color: #000, $alpha: .5);}
.bg-fa{background-color:#fafafa;}
.bg-f5{background-color:#f5f5f5;}
.bg-f7{background-color:#f7f7f7;}
.bg-f2{background-color:#f2f2f2;}
$defaultColorSingle: #{'#'};
$defaultColorArray: '184ebb','bd6d6d','9b7049','d5120b','fffbef','eb6100','00a58f','742918','f9381b','1f4764','4c4c4c','0b9ddb','aa6e27','f9efea','fcf5ef','d29a48','ee5a31','ffeacb','e75a3e','fce899','ffecca','fee9c5','fdd38e','da4b29','fbdcb4','ef979b','e8666d','ea747a','f6c0c3','e97076','041f63','fc692d','000','333','666','888','999','aaa','bbb','ccc','ddd','fff','13dbe6', 'ffa800', '12dce6', '00fcff','099d9f', 'ffae00','196669','ff8a00','09a0a2','15c1bc','ffe3af','d0171e','f6422f','f59c00','cfd0d5','e02925','d58445','f84330','f6462d','ff1f1f','ffd7b3','ffecd0','8c0115','f23d2d','e8845b';
@each $i in $defaultColorArray{
.color-#{$i}{color:$defaultColorSingle+#{$i};}
.bg-#{$i}{background-color: $defaultColorSingle+#{$i};}
}
+22
View File
@@ -0,0 +1,22 @@
@mixin font($num) {
.font-#{$num}
{
font-size:#{$num}px;
}
}
@for $i from 8 through 50
{
@include font($i*2)
}
/*
增加需要的数值
(width height)
*/
$defaultFontSizeArray: 70,80,100;
@each $i in $defaultFontSizeArray{
@include font($i)
}
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
@use "sass:list";
@mixin imgsize($width,$height) {
.imgsize-#{$width}X#{$height}{
width: $width * 1px;
height: $height * 1px;
}
}
/*
增加需要的数值
(width height)
*/
$defaultImgSizeArray: (200 150)(200 152)(52 52)(750 130)(326 200)(750 750)(400 120)(160 160)(170 170)(175 175)(274 200)(90 90)(200 200)(230 136)(70 70)(190 190)(116 116)(28 28)(750 450)(750 20)(750 820)(610 730)(565 39)(566 56)(628 114)(628 652)(590 340)(180 110)(44 44)(44 65)(495 61)(146 146)(750 540)(650 300)(214 160)(220 170)(280 280)(280 50)(60 60)(80 80)(100 100)(105 105)(315 200)(130 130)(140 140)(170 40)(210 40)(40 40)(55 71)(32 32)(150 135)(160 142)(206 266)(240 220)(686 652);
@each $i in $defaultImgSizeArray{
@include imgsize(list.nth($i, 1),list.nth($i, 2));
}
+83
View File
@@ -0,0 +1,83 @@
/*
layer mobile
*/
.layui-m-layer{position:relative; z-index: 19891014;}
.layui-m-layer *{-webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box;}
.layui-m-layershade,
.layui-m-layermain{position:fixed; left:0; top:0; width:100%; height:100%;}
.layui-m-layershade{background-color:rgba(0,0,0, .7); pointer-events:auto;}
.layui-m-layermain{display:table; font-family: Helvetica, arial, sans-serif; pointer-events: none;}
.layui-m-layermain .layui-m-layersection{display:table-cell; vertical-align:middle; text-align:center;}
.layui-m-layerchild{position:relative; display:inline-block; text-align:left; background-color:#fff; font-size:14px; border-radius: 5px; box-shadow: 0 0 8px rgba(0, 0, 0, 0.1); pointer-events:auto; -webkit-overflow-scrolling: touch;}
.layui-m-layerchild{-webkit-animation-fill-mode: both; animation-fill-mode: both; -webkit-animation-duration: .2s; animation-duration: .2s;}
/* 弹出动画 */
@-webkit-keyframes layui-m-anim-scale { /* 默认 */
0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}
100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}
}
@keyframes layui-m-anim-scale { /* 默认 */
0% {opacity: 0; -webkit-transform: scale(.5); transform: scale(.5)}
100% {opacity: 1; -webkit-transform: scale(1); transform: scale(1)}
}
.layui-m-anim-scale{animation-name: layui-m-anim-scale; -webkit-animation-name: layui-m-anim-scale;}
@-webkit-keyframes layui-m-anim-up{
0%{opacity: 0; -webkit-transform: translateY(800px); transform: translateY(800px)}
100%{opacity: 1; -webkit-transform: translateY(0); transform: translateY(0)}
}
@keyframes layui-m-anim-up{
0%{opacity: 0; -webkit-transform: translateY(800px); transform: translateY(800px)}
100%{opacity: 1; -webkit-transform: translateY(0); transform: translateY(0)}
}
.layui-m-anim-up{-webkit-animation-name: layui-m-anim-up;animation-name: layui-m-anim-up}
.layui-m-layer0 .layui-m-layerchild{width: 90%; max-width: 640px;}
.layui-m-layer1 .layui-m-layerchild{border:none; border-radius:0;}
.layui-m-layer2 .layui-m-layerchild{width:auto; max-width:260px; min-width:40px; border:none; background: none; box-shadow: none; color:#fff;}
.layui-m-layerchild h3{padding: 0 10px; height: 60px; line-height: 60px; font-size:16px; font-weight: 400; border-radius: 5px 5px 0 0; text-align: center;}
.layui-m-layerchild h3,
.layui-m-layerbtn span{ text-overflow:ellipsis; overflow:hidden; white-space:nowrap;}
.layui-m-layercont{padding: 50px 30px; line-height: 22px; text-align:center;}
.layui-m-layer1 .layui-m-layercont{padding:0; text-align:left;}
.layui-m-layer2 .layui-m-layercont{text-align:center; padding: 0; line-height: 0;}
.layui-m-layer2 .layui-m-layercont i{width:25px; height:25px; margin-left:8px; display:inline-block; background-color:#fff; border-radius:100%;}
.layui-m-layer2 .layui-m-layercont p{margin-top: 20px;}
/* loading */
@-webkit-keyframes layui-m-anim-loading{
0%,80%,100%{transform:scale(0); -webkit-transform:scale(0)}
40%{transform:scale(1); -webkit-transform:scale(1)}
}
@keyframes layui-m-anim-loading{
0%,80%,100%{transform:scale(0); -webkit-transform:scale(0)}
40%{transform:scale(1); -webkit-transform:scale(1)}
}
.layui-m-layer2 .layui-m-layercont i{-webkit-animation: layui-m-anim-loading 1.4s infinite ease-in-out; animation: layui-m-anim-loading 1.4s infinite ease-in-out; -webkit-animation-fill-mode: both; animation-fill-mode: both;}
.layui-m-layer2 .layui-m-layercont i:first-child{margin-left:0; -webkit-animation-delay: -.32s; animation-delay: -.32s;}
.layui-m-layer2 .layui-m-layercont i.layui-m-layerload{-webkit-animation-delay: -.16s; animation-delay: -.16s;}
.layui-m-layer2 .layui-m-layercont>div{line-height:22px; padding-top:7px; margin-bottom:20px; font-size: 14px;}
.layui-m-layerbtn{display: box; display: -moz-box; display: -webkit-box; width: 100%; position:relative; height: 50px; line-height: 50px; font-size: 0; text-align:center; border-top:1px solid #D0D0D0; background-color: #F2F2F2; border-radius: 0 0 5px 5px;}
.layui-m-layerbtn span{position:relative; display: block; -moz-box-flex: 1; box-flex: 1; -webkit-box-flex: 1; text-align:center; font-size:14px; border-radius: 0 0 5px 5px; cursor:pointer;}
.layui-m-layerbtn span[yes]{color: #40AFFE;}
.layui-m-layerbtn span[no]{border-right: 1px solid #D0D0D0; border-radius: 0 0 0 5px;}
.layui-m-layerbtn span:active{background-color: #F6F6F6;}
.layui-m-layerend{position:absolute; right:7px; top:10px; width:30px; height:30px; border: 0; font-weight:400; background: transparent; cursor: pointer; -webkit-appearance: none; font-size:30px;}
.layui-m-layerend::before, .layui-m-layerend::after{position:absolute; left:5px; top:15px; content:''; width:18px; height:1px; background-color:#999; transform:rotate(45deg); -webkit-transform:rotate(45deg); border-radius: 3px;}
.layui-m-layerend::after{transform:rotate(-45deg); -webkit-transform:rotate(-45deg);}
/* 底部对话框风格 */
body .layui-m-layer .layui-m-layer-footer{position: fixed; width: 95%; max-width: 100%; margin: 0 auto; left:0; right: 0; bottom: 10px; background: none;}
.layui-m-layer-footer .layui-m-layercont{padding: 20px; border-radius: 5px 5px 0 0; background-color: rgba(255,255,255,.8);}
.layui-m-layer-footer .layui-m-layerbtn{display: block; height: auto; background: none; border-top: none;}
.layui-m-layer-footer .layui-m-layerbtn span{background-color: rgba(255,255,255,.8);}
.layui-m-layer-footer .layui-m-layerbtn span[no]{color: #FD482C; border-top: 1px solid #c2c2c2; border-radius: 0 0 5px 5px;}
.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top: 10px; border-radius: 5px;}
/* 通用提示 */
body .layui-m-layer .layui-m-layer-msg{width: auto; max-width: 90%; margin: 0 auto; bottom: -150px; background-color: rgba(0,0,0,.7); color: #fff;}
.layui-m-layer-msg .layui-m-layercont{padding: 10px 20px;}
+1
View File
@@ -0,0 +1 @@
.clear:before,.clear:after{content:"";display:table}.clear:after{clear:both}.clear{zoom:1}.fl{float:left}.fr{float:right}.fn-clear:before,.fn-clear:after{content:"";display:table}.fn-clear:after{clear:both}.fn-clear{zoom:1}.fn-fl{float:left}.fn-fr{float:right}.fn-flex{display:-webkit-flex;display:-ms-flexbox;display:-webkit-box;display:flex;flex-flow:row;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch}.fn-flex-baseline{-webkit-box-align:baseline;-webkit-align-items:baseline;-ms-flex-align:baseline;align-items:baseline}.fn-flex-center{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.fn-flex-item{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.fn-flex-item[flexsize="2"]{-webkit-box-flex:2;-webkit-flex:2;-ms-flex:2;flex:2}.fn-flex-item[flexsize="3"]{-webkit-box-flex:3;-webkit-flex:3;-ms-flex:3;flex:3}.fn-flex-item[flexsize="4"]{-webkit-box-flex:4;-webkit-flex:4;-ms-flex:4;flex:4}.fn-flex-item[flexsize="5"]{-webkit-box-flex:5;-webkit-flex:5;-ms-flex:5;flex:5}.fn-flex-item[flexsize="6"]{-webkit-box-flex:6;-webkit-flex:6;-ms-flex:6;flex:6}.fn-flex-item[flexsize="7"]{-webkit-box-flex:7;-webkit-flex:7;-ms-flex:7;flex:7}.fn-flex-item[flexsize="8"]{-webkit-box-flex:8;-webkit-flex:8;-ms-flex:8;flex:8}.fn-flex-item[flexsize="9"]{-webkit-box-flex:9;-webkit-flex:9;-ms-flex:9;flex:9}.fn-flex-wrap{flex-wrap:wrap}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.block{display:block}.inline-block{display:inline-block}.fn-hide{display:none !important}.overflowhidden{overflow:hidden}.scroll-x{overflow-x:auto}.scroll-y{overflow-y:auto}.relative{position:relative}.absolute{position:absolute}.fixed{position:fixed}.top-0{top:0}.left-0{left:0}.bottom-0{bottom:0}.right-0{right:0}.z-index--1{z-index:-1 !important}.z-index-0{z-index:0}.z-index-1{z-index:1}.z-index-2{z-index:2}.z-index-3{z-index:3}.z-index-4{z-index:4}.z-index-10{z-index:10}.box-center-middle{top:50%;left:50%;transform:translate(-50%, -50%)}.box-middle{top:50%;transform:translate(0, -50%)}.box-center{left:50%;transform:translate(-50%, 0)}.box-border{box-sizing:border-box}.wp10{width:10%;box-sizing:border-box}.wp20{width:20%;box-sizing:border-box}.wp25{width:25%;box-sizing:border-box}.wp30{width:30%;box-sizing:border-box}.wp33{width:33%;box-sizing:border-box}.wp40{width:40%;box-sizing:border-box}.wp45{width:45%;box-sizing:border-box}.wp48{width:48%;box-sizing:border-box}.wp49{width:49%;box-sizing:border-box}.wp50{width:50%;box-sizing:border-box}.wp60{width:60% !important;box-sizing:border-box}.wp65{width:65% !important;box-sizing:border-box}.wp70{width:70% !important;box-sizing:border-box}.wp80{width:80% !important;box-sizing:border-box}.wp90{width:90%;box-sizing:border-box}.wp100{width:100%;box-sizing:border-box}.w100vw{width:100vw}.h100vh{height:100vh}.transition-all{transition:all ease .2s}.op90{opacity:.9}.op70{opacity:.7}.op50{opacity:.5}.op40{opacity:.4}.op20{opacity:.2}.op0{opacity:0}.bg-size-cover{background-size:cover}.bg-size-fullwidth{background-size:100% auto}.bg-size-fullheight{background-size:auto 100%}.bg-no-repeat{background-repeat:no-repeat}.bg-repeat-x{background-repeat:repeat-x}.bg-repeat-y{background-repeat:repeat-y}.bg-pos-top{background-position:top center}.bg-pos-bottom{background-position:bottom center}.bg-pos-center{background-position:center}.box-shadow-darkGray{box-shadow:0 0 10px rgba(0,0,0,0.1)}.box-shadow-lightGray{box-shadow:0 0 20px rgba(0,0,0,0.08)}.box-shadow-green{box-shadow:0 0 20px rgba(55,190,77,0.15)}.box-shadow-darkGreen{box-shadow:0 0 20px rgba(55,190,77,0.25)}
+107
View File
@@ -0,0 +1,107 @@
.clear:before,.clear:after{content:"";display:table;}
.clear:after{clear:both;}
.clear{zoom:1;}
.fl{float:left;}
.fr{float:right;}
.fn-clear:before,.fn-clear:after{content:"";display:table;}
.fn-clear:after{clear:both;}
.fn-clear{zoom:1;}
.fn-fl{float:left;}
.fn-fr{float:right;}
.fn-flex{display:-webkit-flex;display:-ms-flexbox;display:-webkit-box;display:flex;flex-flow:row;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;}
.fn-flex-baseline{-webkit-box-align:baseline;-webkit-align-items:baseline;-ms-flex-align:baseline;align-items:baseline;}
.fn-flex-center{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;}
.fn-flex-item{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;}
.fn-flex-item[flexsize="2"]{-webkit-box-flex:2;-webkit-flex:2;-ms-flex:2;flex:2;}
.fn-flex-item[flexsize="3"]{-webkit-box-flex:3;-webkit-flex:3;-ms-flex:3;flex:3;}
.fn-flex-item[flexsize="4"]{-webkit-box-flex:4;-webkit-flex:4;-ms-flex:4;flex:4;}
.fn-flex-item[flexsize="5"]{-webkit-box-flex:5;-webkit-flex:5;-ms-flex:5;flex:5;}
.fn-flex-item[flexsize="6"]{-webkit-box-flex:6;-webkit-flex:6;-ms-flex:6;flex:6;}
.fn-flex-item[flexsize="7"]{-webkit-box-flex:7;-webkit-flex:7;-ms-flex:7;flex:7;}
.fn-flex-item[flexsize="8"]{-webkit-box-flex:8;-webkit-flex:8;-ms-flex:8;flex:8;}
.fn-flex-item[flexsize="9"]{-webkit-box-flex:9;-webkit-flex:9;-ms-flex:9;flex:9;}
.fn-flex-wrap{flex-wrap:wrap}/*多行*/
.justify-between{justify-content: space-between;}
.justify-center{justify-content:center;}
/*layout display*/
.block{display:block;}
.inline-block{display:inline-block;}
.fn-hide{display:none !important;}
.overflowhidden{overflow:hidden;}
.scroll-x{overflow-x:auto;}
.scroll-y{overflow-y:auto;}
/*layout position*/
.relative{position:relative;}
.absolute{position:absolute;}
.fixed{position:fixed;}
.top-0{top:0;}
.left-0{left:0;}
.bottom-0{bottom:0;}
.right-0{right:0;}
.z-index--1{z-index:-1!important;}
.z-index-0{z-index:0;}
.z-index-1{z-index:1;}
.z-index-2{z-index:2;}
.z-index-3{z-index:3;}
.z-index-4{z-index:4;}
.z-index-10{z-index: 10;}
.box-center-middle{top:50%;left:50%;transform:translate(-50%,-50%);}
.box-middle{top:50%;transform:translate(0,-50%);}
.box-center{left:50%;transform:translate(-50%,0);}
.box-border{box-sizing: border-box;}
// html,body{height:100%;background: #f0f0f0;}
// #stage{min-height:100%;_display:table;_height:100%;min-width:1200px;}
// #main{overflow:auto;padding-bottom:145px;padding-top:60px;}
// #footer{position:relative;margin-top:-145px;height:145px;clear:both;}
// body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
.wp10{width:10%;box-sizing:border-box;}
.wp20{width:20%;box-sizing:border-box;}
.wp25{width:25%;box-sizing:border-box;}
.wp30{width:30%;box-sizing:border-box;}
.wp33{width:33%;box-sizing:border-box;}
.wp40{width:40%;box-sizing:border-box;}
.wp45{width:45%;box-sizing:border-box;}
.wp48{width:48%;box-sizing:border-box;}
.wp49{width:49%;box-sizing:border-box;}
.wp50{width:50%;box-sizing:border-box;}
.wp60{width:60%!important;box-sizing:border-box;}
.wp65{width:65%!important;box-sizing:border-box;}
.wp70{width:70%!important;box-sizing:border-box;}
.wp80{width:80%!important;box-sizing:border-box;}
.wp90{width:90%;box-sizing:border-box;}
.wp100{width:100%;box-sizing:border-box;}
.w100vw{width: 100vw;}
.h100vh{height: 100vh;}
.transition-all{transition: all ease .2s;}
.op90{opacity: .9;}
.op70{opacity: .7;}
.op50{opacity: .5;}
.op40{opacity: .4;}
.op20{opacity: .2;}
.op0{opacity: 0;}
.bg-size-cover{background-size: cover;}
.bg-size-fullwidth{background-size: 100% auto;}
.bg-size-fullheight{background-size: auto 100%;}
.bg-no-repeat{background-repeat: no-repeat;}
.bg-repeat-x{background-repeat:repeat-x;}
.bg-repeat-y{background-repeat: repeat-y;}
.bg-pos-top{background-position: top center;}
.bg-pos-bottom{background-position: bottom center;}
.bg-pos-center{background-position: center;}
.box-shadow-darkGray{box-shadow:0 0 10px rgba(0,0,0,.1);}
.box-shadow-lightGray{box-shadow:0 0 20px rgba(0,0,0,.08);}
.box-shadow-green{box-shadow:0 0 20px rgba(55,190,77,.15);}
.box-shadow-darkGreen{box-shadow:0 0 20px rgba(55,190,77,.25);}
+320
View File
@@ -0,0 +1,320 @@
/******************************************************************
* mDialog 默认的动画效果
*/
/**
* 淡入效果
*/
@keyframes mDialogFadeIn {
from {
opacity: 0; }
to {
opacity: 1; } }
.mDialogFadeIn {
animation-name: mDialogFadeIn; }
/**
* 淡出效果
*/
@keyframes mDialogFadeOut {
from {
opacity: 1; }
to {
opacity: 0; } }
.mDialogFadeOut {
animation-name: mDialogFadeOut; }
/**
* 类似zoomIn
*/
@keyframes mDialogZoomIn {
from {
opacity: 0;
transform: scale3d(0.3, 0.3, 0.3); }
50% {
opacity: 1; } }
.mDialogZoomIn {
animation-name: mDialogZoomIn; }
/**
* 类似zoomOut
*/
@keyframes mDialogZoomOut {
from {
opacity: 1; }
50% {
opacity: 0;
transform: scale3d(0.3, 0.3, 0.3); }
to {
opacity: 0; } }
.mDialogZoomOut {
animation-name: mDialogZoomOut; }
/**
* 类似苹果确认提示框效果也是comfirm的默认的效果
*/
@keyframes mDialogBigIn {
0% {
opacity: 0;
transform: scale(1.2, 1.2); }
100% {
opacity: 1;
transform: scale(1, 1); } }
.mDialogBigIn {
animation-name: mDialogBigIn; }
/**
* 类似苹果确认提示框效果也是comfirm的默认的效果
*/
@keyframes mDialogBigOut {
0% {
opacity: 1; }
100% {
opacity: 0;
transform: scale(1.2, 1.2); } }
.mDialogBigOut {
animation-name: mDialogBigOut; }
/******************************************************************
* mDialog container 容器
*/
.mDialog-layer-container {
visibility: hidden;
position: fixed;
animation-timing-function: ease-out;
box-sizing: border-box; }
.mDialog-layer-container * {
box-sizing: border-box; }
.mDialog-layer-container.mDialog-layer-container-full > .mDialog-layer-title {
border-radius: 0; }
.mDialog-layer-container.mDialog-layer-container-full > .mDialog-layer-main {
border-radius: 0; }
.mDialog-layer-container.mDialog-layer-container-full > .mDialog-layer-btns {
border-radius: 0; }
/******************************************************************
* mDialog title 标题
*/
.mDialog-layer-title {
border-radius: 2.6667vw 2.6667vw 0 0;
background: #F5f5f5;
clear: both;
border-bottom: 1px solid #d5d5d5;
padding: 2.6667vw;
overflow: hidden;
font-size: 4.8vw; }
/******************************************************************
* mDialog main 主题内容
*/
.mDialog-layer-main {
word-break: break-all;
word-wrap: break-word;
overflow: hidden;
font-size: 4.2667vw; }
.mDialog-layer-main:after {
content: "";
display: table;
clear: both; }
.mDialog-layer-main.mDialog-layer-main-full > div {
height: 100%;
overflow: hidden; }
.mDialog-layer-main > div {
position: relative; }
/******************************************************************
* mDialog btns 底部按钮集
*/
.mDialog-layer-btns {
clear: both;
border-top: 1px solid #e8e8e8;
background: #fff;
border-radius: 0 0 2.6667vw 2.6667vw;
display: flex; }
.mDialog-layer-btns > .mDialog-btn {
flex: 1;
display: block;
text-align: center;
position: relative;
color: #007aff;
font-size: 4.8vw;
padding: 2.6667vw 0; }
.mDialog-layer-btns > .mDialog-btn:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 1px;
height: 100%;
border-left: 1px solid #d5d5d5;
color: #d5d5d5; }
.mDialog-layer-btns > .mDialog-btn:active {
background-color: rgba(0, 0, 0, 0.05); }
.mDialog-layer-btns > .mDialog-btn:first-child:after {
border-left: 0; }
/******************************************************************
* mDialog close 关闭按钮
*/
.mDialog-close {
position: absolute;
width: 8.667vw;
height: 8.667vw;
overflow: hidden;
right: 0;
top: 0;
margin-top: -4.3333vw;
margin-right: -4.3333vw;
border-radius: 100%;
background-color: black; }
.mDialog-close:before {
transform: rotate(45deg);
content: '';
position: absolute;
top: 50%;
left: 1.3333vw;
right: 1.3333vw;
background: #fff;
height: 0.8vw;
margin-top: -0.4vw;
border-radius: 1.0667vw; }
.mDialog-close:after {
transform: rotate(-45deg);
content: '';
position: absolute;
top: 50%;
left: 1.3333vw;
right: 1.3333vw;
background: #fff;
height: 0.8vw;
margin-top: -0.4vw;
border-radius: 1.0667vw; }
/******************************************************************
* mDialog 遮罩层
*/
.mDialog-shade {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
animation-fill-mode: both;
animation-timing-function: ease-out; }
.mDialog-shade.in {
animation-name: mDialogFadeIn; }
.mDialog-shade.out {
animation-name: mDialogFadeOut; }
/******************************************************************
* mDialog open方法 content是内容
*/
.mDialog-default-section {
background: #fff;
font-size: 4.2667vw;
padding: 2.6667vw; }
/******************************************************************
* mDialog msg 信息提示框
*/
.mDialog-msg-section {
background-color: rgba(0, 0, 0, 0.9);
border-radius: 2.6667vw;
padding: 4vw;
color: #fff; }
/******************************************************************
* mDialog 加载提示框
*/
@keyframes line-spin-fade-loader {
50% {
opacity: 0.3; }
100% {
opacity: 1; } }
.mDialog-loading-section {
background-color: rgba(0, 0, 0, 0.7);
border-radius: 2vw;
padding: 4vw 8vw;
overflow: hidden; }
.mDialog-loading-section .loading-txt {
font-size: 4.2667vw;
color: #fff;
text-align: center;
margin-top: 2.6667vw;
white-space: nowrap; }
.mDialog-loading-section .loading-icon {
position: relative;
width: 16.533vw;
height: 16.533vw;
margin: 0 auto; }
.mDialog-loading-section .loading-icon > div {
background-color: #fff;
border-radius: 0.5333vw;
animation-fill-mode: both;
position: absolute;
width: 1.0667vw;
height: 4.8vw;
margin-left: -0.5333vw; }
.mDialog-loading-section .loading-icon > div:nth-child(1) {
top: 11.733vw;
left: 50%;
animation: line-spin-fade-loader 1.2s 0.12s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(2) {
top: 10.7173vw;
left: 10.7173vw;
transform: rotate(-45deg);
transform-origin: top center;
animation: line-spin-fade-loader 1.2s 0.24s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(3) {
top: 8.533vw;
left: 11.733vw;
transform-origin: top center;
transform: rotate(-90deg);
animation: line-spin-fade-loader 1.2s 0.36s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(4) {
top: 5.816vw;
left: 11.733vw;
transform: rotate(-135deg);
transform-origin: top center;
animation: line-spin-fade-loader 1.2s 0.48s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(5) {
top: 0px;
left: 50%;
animation: line-spin-fade-loader 1.2s 0.6s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(6) {
top: 5.816vw;
left: 5.816vw;
transform-origin: top center;
transform: rotate(135deg);
animation: line-spin-fade-loader 1.2s 0.72s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(7) {
top: 8.2667vw;
left: 4.8vw;
margin-left: -0.5333vw;
transform: rotate(90deg);
transform-origin: top center;
animation: line-spin-fade-loader 1.2s 0.84s infinite ease-in-out; }
.mDialog-loading-section .loading-icon > div:nth-child(8) {
top: 10.7173vw;
left: 5.816vw;
margin-left: -0.5333vw;
transform: rotate(45deg);
transform-origin: top center;
animation: line-spin-fade-loader 1.2s 0.96s infinite ease-in-out; }
.mDialog-loading-section.loading-notext {
padding: 8vw; }
/******************************************************************
* mDialog confirm 确认框
*/
.mDialog-confirm-section {
background: #fff;
padding: 5.333vw 4vw;
border-radius: 2.6667vw 2.6667vw 0 0; }
+20
View File
@@ -0,0 +1,20 @@
/*text render*/
.text-nowrap{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.text-left{text-align:left;}
.text-center{text-align:center;}
.text-right{text-align:right;}
.text-underline{text-decoration:underline;}
.text-through{text-decoration:line-through;}
.text-middle{vertical-align:middle}
.text-lighter{font-weight:400;}
.text-bold{font-weight:600;}
.text-normal{font-weight: normal;}
.text-break{word-break:break-all;word-wrap:break-word;}
.space-nowrap{white-space:nowrap;}
.space-normal{white-space:normal;}
.text-italic{font-style: italic;}
/*line-clamp*/
.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;}
.line-clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;}
.line-clamp-3{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;}
+132
View File
@@ -0,0 +1,132 @@
.toast-item-wrapper {
max-width: 450px;
padding: 10px;
box-sizing: border-box;
color: #fff;
overflow: hidden;
user-select: none;
font-size: 22px;
}
.toast-item-wrapper i.toast-icon {
position: absolute;
top: 12px;
left: 0;
width: 50px;
text-align: center;
vertical-align: middle;
font-size: 2rem;
}
.toast-item-wrapper .toast-close {
font-size: 1.2rem;
position: absolute;
top: 0;
right: 0;
width: 20px;
text-align: center;
cursor: pointer;
}
.toast-item-wrapper.success {
background-color: rgba(0,0,0,.4);
// border: 1px solid #1a9581;
}
.toast-item-wrapper.error {
background-color: #ff7946;
border: 1px solid #f35818;
}
.toast-item-wrapper.warning {
background-color: #fff1c0;
border: 1px solid #f0c948;
color: #333;
}
.toast-item-wrapper.notice {
background-color: #48a9f8;
border: 1px solid #208ce4;
}
.toast-item-wrapper.info {
background-color: #7f97a3;
border: 1px solid #6b8699;
}
.toast-item-wrapper.toast-top-left {
left: 20px;
top: 20px;
}
.toast-item-wrapper.toast-top-right {
right: 20px;
top: 20px;
}
.toast-item-wrapper.toast-top-center {
margin: 0 auto;
top: 20px;
}
.toast-item-wrapper.toast-bottom-left {
left: 20px;
bottom: 20px;
}
.toast-item-wrapper.toast-bottom-right {
right: 20px;
bottom: 20px;
}
.toast-item-wrapper.toast-bottom-center {
margin: 0 auto;
bottom: 20px;
}
.toast-item-wrapper.fullscreen {
left: 20px;
right: 20px;
width: calc(100% - 40px);
}
.toast-item-wrapper p {
margin: 0;
}
.toast-item-wrapper .toast-message {
font-size: 22px;
}
.toast-item-wrapper .toast-progress {
width: 0;
height: 3px;
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
bottom: 0;
right: 0;
}
.toast-item-wrapper.rtl {
direction: rtl;
text-align: right;
}
.toast-item-wrapper.rtl i.toast-icon {
left: auto;
right: 0;
}
.toast-item-wrapper.rtl .toast-close {
right: auto;
left: 0;
}
.toast-item-wrapper.rtl p {
text-align: right;
}
.toast-item-wrapper.rtl .toast-progress {
left: auto;
right: 0;
}
+39
View File
@@ -0,0 +1,39 @@
// aside {
// .service {
// position: fixed;
// right: 0;
// top: 50%;
// z-index: 100;
// margin-top: -50px;
// #returnTop {
// display: block;
// height: 23px;
// line-height: 23px;
// background-color: rgba(18, 37, 140, .8);
// margin-bottom: 1px;
// position: relative;
// &:after{
// content: "";
// position: absolute;
// left: 50%;
// top:50%;
// transform: translate(-50%,-50%);
// height: 12px;
// width: 74px;
// background-image: url(../img/icon.png);
// background-position: -110px -60px;
// background-repeat: no-repeat;
// }
// }
// ul {
// width: 87px;
// height: 80px;
// background-color: rgba(18, 37, 140, .8);
// padding-top: 10px;
// }
// a {
// color: #fff;
// }
// }
// }
+31
View File
@@ -0,0 +1,31 @@
// .border-darkGrey{border:1px solid #999}
// .border-grey1{border:1px solid #ccc}
// .border-grey{border:1px solid #ddd}
// .border-lightGrey{border:1px solid #e7e7e7}
// .border-line-lightblue {border:1px solid #b2e6ff;}
// .border-line-lightpurple {border:1px solid #a9c2ff;}
// .blc-lightblue{border-left:1px solid #b2e6ff;}
// .blc-lightpurple {border-left:1px solid #a9c2ff;}
// .br-line-purple {border-left:1px solid #a9c2ff!important;border-right:1px solid #a9c2ff!important;}
// .border-line-lightyellow{border:1px solid #ffa147;}
// .blc-lightyellow{border-left:1px solid #ffa147;}
// .br-line-yellow {border-left:1px solid #ffa147!important;border-right:1px solid #ffa147!important;}
.bds-2-eb5359{border: 2px solid #eb5359;}
.bds-1-eb5359{border: 1px solid #eb5359;}
.bbs-1-eb5359{border-bottom:#eb5359 1px solid;box-sizing:border-box;}
.bbs-2-eb5359{border-bottom:#eb5359 2px solid;box-sizing:border-box;}
.bbs-3-eb5359{border-bottom:#eb5359 3px solid;box-sizing:border-box;}
.bds-1-fab758{border: 1px solid #fab758;}
.bds-1-f0f0f0{border: 1px solid #f0f0f0;}
.bts-1-f0f0f0{border-top: 1px solid #f0f0f0;}
.bds-1-ccc{border: 1px solid #ccc;}
.bds-1-eee{border: 1px solid #eee;}
.bts-1-eee{border-top: 1px solid #eee;}
.bls-1-eee{border-left: 1px solid #eee;}
.bbs-1-eee{border-bottom: 1px solid #eee;}
.bbs-1-f8f8f8{border-bottom: 1px solid #f8f8f8;}
.bbs-1-e4e4e4{border-bottom: 1px solid #e4e4e4;}
.bds-1-445a6e{border: 1px solid #445A6E;}
+165
View File
@@ -0,0 +1,165 @@

/*layout con*/
.inner2{padding: 2px;}
.inner10{padding:10px;}
.inner20{padding:20px;}
.inner30{padding:30px;}
.inner40{padding:40px;}
.ulib-r0{-webkit-border-radius:0 !important;border-radius:0 !important;}
.ulib-r5{-webkit-border-radius:5px;border-radius:5px;}
.ulib-r10{-webkit-border-radius:10px;border-radius:10px;}
.ulib-r20{-webkit-border-radius:20px;border-radius:20px;}
.ulib-r22{-webkit-border-radius:22px;border-radius:22px;}
.ulib-r100{-webkit-border-radius:100px;border-radius:100px;}
.ulib-r750{-webkit-border-radius:750px;border-radius:750px;}
.ulib-r7500{-webkit-border-radius:750px;border-radius:750px 0 0 750px;}
.ulib-r7501{-webkit-border-radius:750px;border-radius:0 750px 750px 0;}
.mt0{margin-top:0 !important;}
.mt2{margin-top:2px;}
.mt5{margin-top:5px;}
.mt10{margin-top:10px;}
.mt12{margin-top:12px;}
.mt15{margin-top:15px;}
.mt20{margin-top:20px;}
.mt25{margin-top:25px;}
.mt30{margin-top:30px;}
.mt35{margin-top:35px;}
.mt40{margin-top:40px;}
.mt50{margin-top:50px;}
.mt60{margin-top:60px;}
.mt70{margin-top:70px;}
.mt105{margin-top:105px;}
.mt110{margin-top:110px;}
.ml5{margin-left:5px;}
.ml10{margin-left:10px;}
.ml15{margin-left:15px;}
.ml18{margin-left:18px;}
.ml20{margin-left:20px;}
.ml25{margin-left:25px;}
.ml30{margin-left:30px;}
.ml35{margin-left:35px;}
.ml40{margin-left:40px;}
.ml45{margin-left:45px;}
.ml50{margin-left:50px;}
.ml60{margin-left:60px;}
.ml70{margin-left:70px;}
.ml80{margin-left:80px;}
.ml96{margin-left:96px;}
.ml100{margin-left:100px;}
.ml110{margin-left:110px;}
.ml-115{margin-left:-115px;}
.ml120{margin-left:120px;}
.ml150{margin-left:150px;}
.ml160{margin-left:160px;}
.ml210{margin-left:210px;}
.ml200{margin-left:200px;}
.ml250{margin-left:250px;}
.ml290{margin-left:290px;}
.mr5{margin-right:5px;}
.mr10{margin-right:10px;}
.mr15{margin-right:15px;}
.mr20{margin-right:20px;}
.mr25{margin-right:25px;}
.mr30{margin-right:30px;}
.mr35{margin-right:35px;}
.mr40{margin-right:40px;}
.mr45{margin-right:45px;}
.mr50{margin-right:50px;}
.mr54{margin-right:54px;}
.mr55{margin-right:55px;}
.mr60{margin-right:60px;}
.mr70{margin-right:70px;}
.mr80{margin-right:80px;}
.mr100{margin-right:100px;}
.mr110{margin-right:110px;}
.mr120{margin-right:120px;}
.mr150{margin-right:150px;}
.mr200{margin-right:200px;}
.mr310{margin-right:310px;}
.mb1{margin-bottom:1px;}
.mb5{margin-bottom:5px;}
.mb10{margin-bottom:10px;}
.mb15{margin-bottom:15px;}
.mb20{margin-bottom:20px;}
.mb30{margin-bottom:30px;}
.mb40{margin-bottom:40px;}
.mb50{margin-bottom:50px;}
.pt0{padding-top:0 !important;}
.pt3{padding-top:3px;}
.pt5{padding-top:5px;}
.pt8{padding-top:8px;}
.pt10{padding-top:10px;}
.pt15{padding-top:15px;}
.pt17{padding-top:17px;}
.pt20{padding-top:20px;}
.pt21{padding-top:21px;}
.pt23{padding-top:23px;}
.pt25{padding-top:25px;}
.pt30{padding-top:30px;}
.pt40{padding-top:40px;}
.pt45{padding-top:45px;}
.pt60{padding-top:60px;}
.pt70{padding-top:70px;}
.pt150{padding-top:150px;}
.pl0{padding-left:0 !important;}
.pl5{padding-left:5px;}
.pl10{padding-left:10px;}
.pl15{padding-left:15px;}
.pl20{padding-left:20px;}
.pl25{padding-left:25px;}
.pl30{padding-left:30px;}
.pl35{padding-left:35px;}
.pl40{padding-left:40px;}
.pl80{padding-left:80px;}
.pl110{padding-left:110px;}
.pl220{padding-left:220px;}
.pr0{padding-right:0 !important;}
.pr5{padding-right:5px;}
.pr10{padding-right:10px;}
.pr15{padding-right:15px;}
.pr20{padding-right:20px;}
.pr30{padding-right:30px;}
.pr35{padding-right:35px;}
.pr40{padding-right:40px;}
.pr45{padding-right:45px;}
.pr80{padding-right:80px;}
.pr200{padding-right:200px;}
.pb0{padding-bottom:0 !important;}
.pb5{padding-bottom:5px;}
.pb8{padding-bottom:8px;}
.pb10{padding-bottom:10px;}
.pb15{padding-bottom:15px;}
.pb17{padding-bottom:17px;}
.pb20{padding-bottom:20px;}
.pb21{padding-bottom:21px;}
.pb23{padding-bottom:23px;}
.pb30{padding-bottom:30px;}
.pb40{padding-bottom:40px;}
.pb45{padding-bottom:45px;}
.pb60{padding-bottom:60px;}
.pb70{padding-bottom:70px;}
// .w970{width:970px;}
// .w900{width:900px;}
// .w870{width:870px;}
// .w800{width:800px;}
// .w780{width:780px;}
// .w770{width:770px;}
// .w760{width:760px;}
// .w600{width:600px;}
// .w460{width:460px;}
// .w410{width:410px;}
// .w400{width:400px;}
// .w350{width:350px;}
// .w340{width:340px;}
// .w280{width:280px;}
// .w240{width:240px;}
.w200{width:200px;}
// .w140{width:140px;}
// .w130{width:130px;}
// .w60 {width:60px;}
// .full{width:100%;}
+24
View File
@@ -0,0 +1,24 @@
.btn{display:inline-block;font-size:15px;text-align:center;border:none;vertical-align:middle;cursor:pointer;transition:all .15s ease 0s;}
// .btn.bc-blue:hover{background-color:#2b9bd1}
// .btn-yellow{background-color:#ffa127;color:#fff!important;border:1px solid #ffa127}
// .btn-yellow:hover{background-color:#e98e19;border-color:#e98e19}
// .btn-white-line{border:1px solid #fff;color:#fff!important}
// .btn-white-line:hover{border-color:#ccc}
// .btn-blue-line{border:1px solid #42b1e6;color:#42b1e6!important;background-color:#fff}
// .btn-blue-line:hover{background-color:#42b1e6;color:#fff!important}
// .btn-grey-line{border:1px solid #c9c9c9;color:#666!important;background-color:#fff}
// .btn-grey-line:hover{border-color:#ffb400;background-color:#ffb400;color:#fff!important}
// .btn-grey{color:#fff!important;background-color:#d2d2d2;border:1px solid #d2d2d2}
// .btn-grey:hover{color:#fff!important;background-color:#c0c0c0}
// .btn-red{color:#fff!important;background-color:#fc5e6c;border:1px solid #fc5e6c}
// .btn-red:hover{background-color:#ea4755;border-color:#ea4755}
// .btn-blueGreen{background-color:#26d9d6;color:#fff!important;}
// .btn-blueGreen:hover{background-color:#18d1ce;}
// .btn-purple{background-color:#725edb;color:#fff!important;}
// .btn-purple:hover{background-color:#5b46c5;}
// .btn-green{background-color:#7cd955;color:#fff!important;}
// .btn-green:hover{background-color:#65c43d;}
.btn:hover{opacity: .8;}
a.txtlink:hover{color: rgba($color: #eb5359, $alpha: .8);}
+60
View File
@@ -0,0 +1,60 @@
/*font color*/
.color-fff{color:#fff;}
.color-ccc{color:#ccc;}
.color-333{color:#333;}
.color-666{color:#666;}
.color-888{color:#888;}
.color-999{color:#999;}
.color-000{color:#000;}
.color-656565{color:#656565;}
.color-191919{color:#191919;}
.color-9a9a9a{color:#9a9a9a;}
.color-eb5359{color: #EB5359;}
.color-1282f4{color: #1282F4;}
.color-2b9b27{color: #2B9B27;}
.color-eb{color:#ebebeb;}
.color-88e4ff{color: #88E4FF;}
.color-1a1a1a{color: #1a1a1a;}
.color-3399ee{color: #3399EE;}
.color-ffa200{color: #ffa200;}
.color-78c1ff{color: #78c1ff;}
.color-77c1ff{color: #77c1ff;}
.color-ffbb59{color: #FFBB59;}
.color-445a6e{color: #445a6e;}
.color-51d3f4{color: #51D3F4;}
.color-fab758{color: #FAB758;}
/*bg*/
.bg-fff{background-color:#fff;}
.bg-f0{background-color:#f0f0f0;}
.bg-fa{background-color:#fafafa;}
.bg-f5{background-color:#f5f5f5;}
.bg-f7{background-color:#f7f7f7;}
.bg-f8{background-color:#f8f8f8;}
.bg-000{background-color: #000;}
.bg-aaa{background-color:#aaa;}
.bg-ccc{background-color:#ccc;}
.bg-ddd{background-color:#ddd;}
.bg-eee{background-color:#eee;}
.bg-666{background-color:#666;}
.bg-eb5359{background-color: #EB5359;}
.bg-1282f4{background-color: #1282F4;}
.bg-d25f6b-1{background-color: rgba($color: #D25F6B, $alpha: .1);;}
.bg-a271f9-1{background-color: rgba($color: #A271F9, $alpha: .1);}
.bg-4f983a{background-color: #4F983A;}
.bg-19273d-op50{background-color: rgba($color: #19273D, $alpha: .5);}
.bg-88e4ff{background-color: #88E4FF!important;}
.bg-3399EE{background-color: #3399EE!important;}
.bg-999{background-color: #999999!important;}
.bg-1a{background-color: #1a1a1a!important;}
.bg-78c1ff{background-color: #78c1ff!important;}
.bg-efefef{background-color: #efefef!important;}
.bg-f8f8f8{background-color: #f8f8f8!important;}
.bg-2b9b27-op20{background-color: rgba(43,155,39,.2);}
.bg-1281f3-op20{background-color: rgba(18,129,243,.2);}
.bg-eb5359-op20{background-color: rgba(235,83,89,.2);}
.bg-1a1a1a{background-color: #1a1a1a;}
.bg-1f1c32{background-color: #1F1C32;}
.bg-445a6e{background-color: #445a6e;}
.black-op60{background-color: rgba($color: #000000, $alpha: .6);}
+56
View File
@@ -0,0 +1,56 @@
@use '../base/_variable';
footer {
min-width: 1200px;
padding: 60px 0px;
background: #1E2023;
.icon{
// width: 40px;
// height: 40px;
// cursor: pointer;
// margin-right: 5px;
// &.icon-footer-wechat{
// background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAe1BMVEUAAACZmZmcnJyZmZmZmZmZmZmampqZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmampqZmZmZmZmampqZmZmampqZmZmZmZmZmZmZmZmZmZmZmZmZmZmampqZmZmZmZmZmZmZmZmZmZmYmJiZmZmZmZmZmZmYmJiampqZmZlq+OxBAAAAKHRSTlMACwbr+/EVu0r14dvJqIOfdm9QIRHmG9azZNGTXFeZeWtEM8Atjj0oRTFBqwAAA3xJREFUWMOtmdeCqjAQhhNI6F2RJmDdnfd/wnNUWEml6HdlBMZkyj8hohksp4+vhekC0Lywu+S8R9vBWVMADwnujrHFmuGELiig8c/qySUeaCkqY4253oRZ8tNik20Oi/CzReZ2NiymPMzbqyiswMzmYhvDShqtJ/cBrMbGGvcVsIHaUtn7zWET/k4xvxw24kvnaPmwmXoviW8AH2CLsY7hIxre3hE+pOUCQkHEDeIoSZJ7uMS7JluFtnjD/cd4B+xYurN1rV2wf+S9bEVzJidljT1urb0hy6uZuPnvhxLuyg3JcfS6m/5NkL0v2KuL3dfGZZSJlLWHkZqDttWc0Avmplwvwr9U58XBMzDFGf1QRee3TqbRZUkFvLprKMsmXE8S4ZADkIuQsiLd81Emv8bHsscgHgb9YxANgwuoocb46EiAxsemNtrHoEIDnCwJDutgQoJGUnOSP5E7EagU1Nz/X/f5FY9M09HAL2c6aR81OqVFyIIpuhzcRT4Q3w7j8KpsFsRik4ZqUjoktHP246iyVU7smeJR2jtSM8VsiocgIWGln6jsNRCLFX6WrDzm8lRRdx2ppI2yFLsVKjgXyEhJhqQYgsUCmXzzErmRE1KA+Sw3EWXHMqm+Mu1C391cJEiawA/ZDS4LSPiKNLaJbUnVHhBhx7kYzPCtEaPMV+9Cx5QzyLeJUHA8HXWx+uvnzqSDdNySBU3vOYMX1xhNR2U1xr1Mxm8zLig18FRcjdRIy4FLG1tWPlPSUm/QgClX6a4rnFZtsspgjHoQIdNQV9c1S+6RAyI2u13QG8y42rUApGHZR111eUTSIjetQVbFLIR8mezuI/r85AVBTSKdPYvwrb4DnutgjtmzqOiExpyJnYYCi2aKZyLsEbELc5AfZYhztvDw4NU5zJ3CgbVMCByYx5NG+jDY4wXfg3nck0TJc/5nhwsnWEJ5EwKi2hNjE5ZAygz/FfANP5RS3BIzMj6Pe23SY3uKSvo8FAlVKoU92ECRtawHJ/nfwibYnn5kX80+xubb64fQ3Zdfb49ffgGPv3xEEBjfPcTwre8es+QKMfr1YBPer1Iui03pffjuYVqwRxqMZsNxn56WrqqP9rtHpvYOLaH1Fka3XX6KbcIsZoLRcnDqzcwuxWglmqN7N3Q2/rlwr0GgvmcYbcc6nxr7+feHaxZ2czpbSM8/LQE1GI9iOi8AAAAASUVORK5CYII=');
// }
// &.icon-footer-weibo{
// background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAMAAAC5zwKfAAAAhFBMVEUAAACZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmTk5OZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmXl5eZmZmZmZmampqZmZmZmZmZmZmampqampqampqZmZmZmZmampqZmZmZmZmampqZmZmZmZmZmZkPlHCcAAAAK3RSTlMACt317OJ3+UdO6Lkg1hfRBPHKnqeNbL9ZB7NwDpRkXSQdE8U1K5mCPqp+dYZ4fAAAA59JREFUWMOs1umSqjAQBeCTsO+iII4LKozbnPd/v1sy4nUgIKLfT6pCpXO6OsEThT3feIGr0dJl5G3mdoHxhJNGbIlSR2AMO9HYQUtsvEisJHvJlcBwwtT5lG4KDLQwOIixwBC+x8E8H09tY74g3qLf14wvmn2hR1jyZWWITr7kCNJHh4PLUdwDlHYGRzJ2UAglR5OhIt8p3zBtZz3jW2Zo2PJNjQ73Y74p9vHI49s8PFjwAxa4EwY/wBComfwIEzdC52BWUHqZQSW93uKcg60muNqrr5w5fkkOFeEuV5QlUbE5mC5w5wdssXGVcLggzXQjO1XTZR2xKaki0djPLSOrGc1xDWDXWqkJAA77SPMAoPCUY/qHTQ6AI7vp+QSVdR1BuYf4TjUyEEBhseHYn/ElRK0+6BRX3zF5ArBU5ByyizXHf2n9MVkuc8AkpbLmsLtpNBsPEpLWdDnLLJI59iT3QK5oHJNq8RmPptbl91m4C0gPcMlv1Vg2u0a/dsYfxQQ3B3IKGNUPV4qrIKOK5aBTwAzQyAJI2ZQhoMoK3SQt81htEyWbArhUSNBtX/cUICw2uYjZZqxxE243y8jVjejyc56gcqqX+sjZooEKDiqTRcYHehpWMW/qomIq/GvO7JYThIEovFN+QhAkYkVBsOJIQff9369jEkptN9Ey6Uy/WzTJZJM9ZzfACIMGkij9Mb0SX1F4aAR8g3wJFcHsGnUdb8YRehivngGPuMp++WlNvN0Yifx+Nw5oIAYyS+p/sPN0sLUw5SARMdKksCXVsPQnXbxf0wkkFdJsYU3aHq7zryQsbktEhfaWF6MLC0kxDNVsUBb9IJj0ajp6NUhyo9hHSGXdUM0mN2Q4yiO9mo6UJYtGxKdglNYGhuleJ3eO6IoGlpQERADiFtQKEoYYt19SdqUXuDJpGilSuVBR8VoYNr0ajzP5Re2gMNrJd1pGr6ByZ5aAZs/k+mTYbULJldCTgeY+IltHNUByyJSmarNGW43poFHfmxKg7mP5I6YVv9b3OEMjr2az9LITAGLoq9T34+wSnkFxvKCFyGbngjCBbwheMbQQPDKc6eatK0FRn4vKRzv7pyxxnC8W2zx4yj26Nu3uywr3hY/70sx98ei+vHVfgLtvEbhvYrhvs2i6YOZ4HRhoU5xB2oKR05xm2gkslA3aoHO7Hf67hiR33TJ139T9+7YzTf24MV67bd3/h8cFxXJ8/kAvTm/PH0uw8wG0r8+pgxwVRgAAAABJRU5ErkJggg==');
// }
width: 16px;
height: 16px;
margin-right: 3px;
&.icon-footerqq{
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABMUlEQVQ4T53TrWvXURTH8dfHB3CyGS0mm0yMsjKD2QcGIou6JjZxccKKK66LSQ1iEEw6cdWysCiu7R8wiCbxgSMXft/x5Sub33nK5Tx83px7z7kxsKo6hru4hdlJ+iOe4kmS331J+k5VncAGLg/BE/89rif50eWHgEdY3kfchR8mWfkLUFUn8RntPMi+4nTXxV4HVTWPD/8Qd+mLSbab0wfcweORgKUkz4aAN7gyEvA6yY09QFVdxUtMjwR8w80km6mqM/iEUyPFXdkXnGuAddw/pLgrX2uAXZz9T8BOA3zHJq4dAlJ4i0sNcAFt19sjLo6EPMcSzvf3YAGv0D7TQdb+wUKSd/0xTqGt6PGBssWOYGYQb9eeSfKr38Ft3GujwU9s4cEEuoo5HMUO1pO8aNA/evBej0fxIBEAAAAASUVORK5CYII=');
}
}
// .footer-focus{
// span{
// em{
// display: none;
// }
// &:hover{
// em{
// display: block;
// }
// }
// }
// }
}
#dota_footer{
margin-top: 21px;
padding-top: 50px;
padding-bottom: 0;
.underline {
width:1200px;
height:1px;
background:rgba(51,51,51,1);
margin-top: 20px;
}
p {
font-size:14px;
color:rgba(153,153,153,1);
margin-top: 21px;
text-align: center;
margin-bottom: 18px;
}
}
+187
View File
@@ -0,0 +1,187 @@
@use '../base/_variable';
/*非常重要的样式让背景图片100%适应整个屏幕*/
header{
.icon-arrow{
transition: .2s all ease-in;
width: 16px;
height: 16px;
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEUAAADMzMzNzc3MzMzMzMzMzMzMzMzMzMzNzc3Nzc3Nzc3MzMzZ2dnMzMzNzc3IyMjMzMzMzMzNzc3Ly8vMzMzNzc3MzMzNzc3Nzc3MzMzKysrOzs7MzMzMzMzMzMzMzMzMzMzMzMzLy8vMzMzMzMzDCjeDAAAAJHRSTlMA+kP18Nt35aRoUwwGiScc0sKxlIJvWk48NzUV5t/Ps5yNYl8rrKDyAAAAwklEQVQ4y92R2RKCMAxFU7qDguwI7ub/v1GamU5By/is54XkHtrOJPAb7L5Ixc7jlh40syAQxRD3CUfUcEVEnsR8z2ZlIJMbf6TOHzKAXMwF69995/ypoKdcybq1tzjDj0A8XMOeS9+iI/XtnlobvKJAhaCioPVtQ62BQHbxR8KF5WrEhaawcXVNpZxgxcgp3gPcqBD5x1yQqA19WGRyChdYiGCCv8d3X3pfQZxJkqYNxaG9oS5gk4SFDcVJpUzgD3kB1aoYrYug5P4AAAAASUVORK5CYII=');
}
.header{
&-height{
height: 50px;
}
&-main{
width: 100%;
height: 30px;
background:#1E2023;
box-sizing: content-box;
z-index: 101;
}
&-logo{
width: 146px;
height: 30px;
background-repeat: no-repeat;
background-position: center;
background-size: 100% auto;
a{
display: block;
height: 100%;
text-indent: -999em;
}
}
&-game{
&:hover{
.icon-arrow{
transform: rotate(180deg);
}
.header-game-more{
display: block;
&:hover{
display: block;
}
}
}
span{
cursor: pointer;
display: block;
height: 30px;
line-height: 30px;
em{
margin: 0 5px;
}
}
img{
width: 20px;
height: 20px;
}
&-more{
display: none;
margin-bottom: 14px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
background-color: #26282B;
top: 40px;
ul{
li{
padding-left: 28px;
padding-right: 20px;
width: 70px;
box-sizing: content-box;
text-align: center;
line-height: 1.5;
img{
width: 48px;
height: 48px;
}
em{
// margin-top: 5px;
// display: block;
// color: #ccc;
}
}
}
}
}
&-language{
vertical-align: middle;
&:hover{
.icon-arrow{
transform: rotate(180deg);
}
.header-language-more{
display: block;
&:hover{
display: block;
}
}
}
span{
cursor: pointer;
display: block;
height: 30px;
line-height: 30px;
em{
margin: 0 5px;
font-size: 16px;
}
}
img{
width: 18px;
height: 18px;
}
.header-language-more{
display: none;
width: 110px;
margin-bottom: 14px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
background-color: #26282B;
top: 35px;
em{
margin-left: 5px;
}
ul{
li{
padding-top: 5px;
padding-bottom: 5px;
}
}
}
}
&-login{
&-no{
display: flex;
a {
width: 59px;
height: 28px;
border-radius: 14px 0px 0px 14px;
background: #fff;
color: $defaultColor;
line-height: 28px;
&:nth-of-type(2) {
border-radius: 0px 14px 14px 0px;
background: $defaultColor;
color: #fff;;
}
}
}
&-user{
&:hover{
ul{
display: block;
}
}
span{
cursor: pointer;
display: block;
max-width: 160px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
height: 30px;
line-height: 30px;
em{
margin: 0 5px;
color: $defaultColor;
}
}
ul{
display: none;
width: 80px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
background-color: #26282B;
// text-align: center;
// li{
// text-indent: 1em;
// }
}
}
}
}
}
+379
View File
@@ -0,0 +1,379 @@
.icon {
// background-image: url(../img/icon.png);
// vertical-align: middle;
// display: inline-block;
// background-repeat: no-repeat;
display: inline-block;
vertical-align: middle;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
text-indent: -999em;
&-win {
width: 138px;
height: 188px;
background-image: url(/images/web/icon-win.png);
}
&-loss {
width: 138px;
height: 188px;
background-image: url(/images/web/icon-loss.png);
}
&-arrow {
width: 16px;
height: 16px;
background-image: url(/images/web/icon-more.png);
}
&-fish {
width: 16px;
height: 16px;
background-image: url(/images/web/icon-fish.png);
}
&-warn {
width: 16px;
height: 16px;
background-image: url(/images/web/icon-warn.png);
}
&-del {
width: 16px;
height: 16px;
background-image: url(/images/web/del.png);
}
&-right {
width: 20px;
height: 20px;
background-image: url(/images/web/icon_right.png);
}
&-adc {
width: 22px;
height: 24px;
background-image: url(/images/web/icon-zb1.png);
}
&-skill {
width: 22px;
height: 24px;
background-image: url(/images/web/icon-jineg.png);
}
&-runes {
width: 22px;
height: 24px;
background-image: url(/images/web/icon-fuw.png);
}
&-history {
width: 24px;
height: 24px;
background-image: url(/images/web/icon-home25.png);
}
&-used {
width: 24px;
height: 24px;
background-image: url(/images/web/icon-home26.png);
}
&-sort {
width: 12px;
height: 16px;
background-image: url(/images/web/inco-home14.png);
}
&-coming {
width: 100px;
height: 96px;
background-image: url(/images/web/icon-coming.png);
}
&-search {
width: 22px;
height: 22px;
background-image: url(/images/web/inco-home5.png);
}
&-cupbg {
width: 166px;
height: 166px;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKYAAACmAgMAAAAt5hzkAAAACVBMVEXrTmIAAADnQ1LpopHeAAAAA3RSTlMMAAYaD5iPAAACt0lEQVRYw+3WPW7cMBAF4CcBKtSlUZ9GRXIKHYGFSDCu1OQerFOlYW6QRqeMSK6Wken5sWPELvxg7MLYDxRnKJCEveUBT+fLCcydBhCJj6kHlfExXUDmMQWd6UpXhg5X6hk6XqlhaHelG0P7K13A5Bk0vpQGjk7vi/JlvSe672xZ+x5v1AWI+V3oBjl9pg6azIkaFe0SXaBKotBlMliVdDDwSjoaGCXtDFJX98CzHwHoDZa8xl7YBw6baGdlahINGBR0BX4edFbsWS5RZLoK1BY66ein16XDi6l7z3Q+aXgutTIt74BMnY5OJ11UdM2vdmlGeF26YVRQj15D40kNOgU91J0uCnoMraDHNDU0/5zoCqjoYOCAKNOAOdNJpkg0faZ5szSNd9Ag0L6sazRIMxapz8dGapmC9pmWDZSlJtP0xdIu96dL1AMiDRgTXYFJosBwO45nnmaSqM2ngadpaetB85w5OuZHnleHnqdFmMwReRrQFboCM0sdMBTq0r8rs72aW4/KJhQ9Q8Ot8+W17kHnM8p6lg8p3UlXkQ4ntSKd7nSTqL1TL8ixUis+v1Ij1V+p3XcSft1jpTnc09+WxoaG/0ttQ5d/p31LNz01BO1a6gk66unQ0pWgc0sdQaeGkmsQ9dQ2lGps9xQ1VANaulINaKmjqqqUr8s2lKprfJp6aqotteRUW7oRXa2UadfUUKoHvW0oVdjQULKwyNCtaSpJHVlUoVRhvW0oVdjcUHJYK1BTi5JoLSxK1C61KIn6WhRPa2FWQU0tSqIuDxs11D7kQQVam2CVdEOvpvpRl49RP0bVjbofCUD6ivqNaOSpQU1H0vZe9GqU2N9FOnPU6el6oQNHvf6EMcQJK55bPUnbmylHw5VGPZ1o6nDNTFJP33LkC0mvp6DooqH6UWu+ff/11991Cf4AEjZBnX82iJUAAAAASUVORK5CYII=');
}
&-forecast-status-1{
width: 14px;
height: 14px;
background-image: url(/images/web/icon-forecast-status-1.png);
}
&-forecast-status-2{
width: 14px;
height: 14px;
background-image: url(/images/web/icon-forecast-status-2.png);
}
&-forecast-status-3{
width: 14px;
height: 14px;
background-image: url(/images/web/icon-forecast-status-3.png);
}
&-match-all{
background-image: url(/images/web/icon_allgame.png);
}
&-match-lol{
background-image: url(/images/web/icon_lol.png);
}
&-match-dota2{
background-image: url(/images/web/icon_dota2.png);
}
&-match-csgo{
background-image: url(/images/web/icon_csgo.png);
}
&-match-wzry{
background-image: url(/images/web/icon_wzry.png);
}
&-match-swxf{
background-image: url(/images/web/icon_swxf.png);
}
&-match-other{
background-image: url(/images/web/icon_other.png);
}
&-close{
width: 24px;
height: 24px;
background-image: url(/images/web/icon-close.png);
}
&-weixin{
width: 24px;
height: 20px;
background-image: url(/images/web/icon-weixin.png);
}
&-rank-default{
width: 10px;
height: 12px;
background-image: url(/images/web/icon-rank-default.png);
}
&-rank-up{
width: 10px;
height: 12px;
background-image: url(/images/web/icon-rank-up.png);
}
&-rank-down{
width: 10px;
height: 12px;
background-image: url(/images/web/icon-rank-down.png);
}
&-uparrow {
width: 20px;
height: 20px;
position: relative;
vertical-align: baseline;
&::after {
content: '';
width: 0;
height: 0;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-left: 8px solid transparent;
border-right: 8px solid transparent;
// border-bottom: 12px solid inherit;
border-bottom-width: 12px;
border-bottom-style: solid;
}
}
&-downarrow {
width: 20px;
height: 20px;
position: relative;
vertical-align: baseline;
&::after {
content: '';
width: 0;
height: 0;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-left: 8px solid transparent;
border-right: 8px solid transparent;
// border-top: 12px solid inherit;
border-top-width: 12px;
border-top-style: solid;
}
}
&-avgarrow {
width: 20px;
height: 20px;
position: relative;
vertical-align: baseline;
&::before {
content: '';
position: absolute;
left: 0;
top: 5px;
width: 100%;
height: 2px;
}
&::after {
content: '';
position: absolute;
left: 0;
bottom: 5px;
width: 100%;
height: 2px;
}
}
&-loading{
width: 32px;
height: 32px;
background-image: url(/images/web/loading.gif);
}
}
.color-eb5359 {
&.icon-uparrow,
&.icon-downarrow {
&::after {
border-top-color: #eb5359;
border-bottom-color: #eb5359;
}
}
&.icon-avgarrow {
&::after,
&::before {
background-color: #eb5359;
}
}
}
.color-2b9b27 {
&.icon-uparrow,
&.icon-downarrow {
&::after {
border-top-color: #2b9b27;
border-bottom-color: #2b9b27;
}
}
&.icon-avgarrow {
&::after,
&::before {
background-color: #2b9b27;
}
}
}
.descending{
i.icon-sort{
background-image: url(/images/web/inco-home15.png);
}
}
.ascending{
i.icon-sort{
background-image: url(/images/web/inco-home_xia.png);
}
}
.forecast-status{
padding-left: 10px;
width: 50px;
height: 18px;
line-height: 18px;
&.bg-eb5359{
&::before{
border-right-color: #eb5359;
}
}
&.bg-3399EE{
&::before{
border-right-color: #3399ed;
}
}
&.bg-1a1a1a{
&::before{
border-right-color: #1a1a1a;
}
}
&.bg-ccc{
&::before{
border-right-color: #ccc;
}
}
&::before{
content:'';
position: absolute;
top: 0;
left: -8px;
width: 0;
height: 0;
border-top: 9px solid transparent;
border-right-width: 8px;
border-right-style: solid;
border-bottom: 9px solid transparent;
}
}
.match_now-con-left-select{
.icon{
&-match-all{
background-image: url(/images/web/icon_allgame_hover.png);
}
&-match-lol{
background-image: url(/images/web/icon_lol_hover.png);
}
&-match-dota2{
background-image: url(/images/web/icon_dota2_hover.png);
}
&-match-csgo{
background-image: url(/images/web/icon_csgo_hover.png);
}
&-match-wzry{
background-image: url(/images/web/icon_wzry_hover.png);
}
&-match-swxf{
background-image: url(/images/web/icon_swxf_hover.png);
}
&-match-other{
background-image: url(/images/web/icon_other_hover.png);
}
}
}
File diff suppressed because one or more lines are too long
+202
View File
@@ -0,0 +1,202 @@
.imgsize-14X14 {
width: 14px;
height: 14px;
}
.imgsize-16X16 {
width: 16px;
height: 16px;
}
.imgsize-18X18 {
width: 18px;
height: 18px;
}
.imgsize-20X20 {
width: 20px;
height: 20px;
}
.imgsize-22X22 {
width: 22px;
height: 22px;
}
.imgsize-24X24 {
width: 24px;
height: 24px;
}
.imgsize-26X26 {
width: 26px;
height: 26px;
}
.imgsize-28X28 {
width: 28px;
height: 28px;
}
.imgsize-30X30 {
width: 30px;
height: 30px;
}
.imgsize-30X48 {
width: 30px;
height: 48px;
}
.imgsize-32X32 {
width: 32px;
height: 32px;
}
.imgsize-34X34 {
width: 34px;
height: 34px;
}
.imgsize-36X36 {
width: 36px;
height: 36px;
}
.imgsize-40X40 {
width: 40px;
height: 40px;
}
.imgsize-45X45 {
width: 45px;
height: 45px;
}
.imgsize-44X44 {
width: 44px;
height: 44px;
}
.imgsize-48X48 {
width: 48px;
height: 48px;
}
.imgsize-50X50 {
width: 50px;
height: 50px;
}
.imgsize-53X53 {
width: 53px;
height: 53px;
}
.imgsize-60X44 {
width: 60px !important;
height: 44px !important;
}
.imgsize-60X45 {
width: 60px !important;
height: 45px !important;
}
.imgsize-60X60 {
width: 60px;
height: 60px;
}
.imgsize-63X48 {
width: 63px;
height: 48px;
}
.imgsize-68X54 {
width: 68px;
height: 54px;
}
.imgsize-78X44 {
width: 78px !important;
height: 44px !important;
border: 0;
border-radius: 0;
}
.imgsize-80X45 {
width: 80px !important;
height: 45px !important;
}
.imgsize-80X80 {
width: 80px;
height: 80px;
}
.imgsize-90X90 {
width: 90px;
height: 90px;
}
.imgsize-92X92 {
width: 92px;
height: 92px;
}
.imgsize-92X52 {
width: 92px;
height: 52px;
}
.imgsize-100X100 {
width: 100px;
height: 100px;
}
.imgsize-106X80 {
width: 106px;
height: 80px;
}
.imgsize-122X122 {
width: 122px;
height: 122px;
}
.imgsize-130X80 {
width: 130px;
height: 80px;
}
.imgsize-140X140 {
width: 140px;
height: 140px;
}
.imgsize-160X60 {
width: 160px;
height: 60px;
}
.imgsize-216X122{
width: 216px;
height: 122px;
}
.imgsize-250X140 {
width: 250px;
height: 140px;
}
.imgsize-216X122 {
width: 216px;
height: 122px;
}
.imgsize-370X230 {
width: 370px;
height: 230px;
}
.imgsize-768X480 {
width: 100%;
height: 480px;
}
+77
View File
@@ -0,0 +1,77 @@
.clear:before,.clear:after{content:"";display:table;}
.clear:after{clear:both;}
.clear{zoom:1;}
.fl{float:left;}
.fr{float:right;}
.fn-clear:before,.fn-clear:after{content:"";display:table;}
.fn-clear:after{clear:both;}
.fn-clear{zoom:1;}
.fn-fl{float:left;}
.fn-fr{float:right;}
.fn-flex{display:-webkit-flex;display:-ms-flexbox;display:-webkit-box;display:flex;flex-flow:row;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;}
.fn-flex-center{-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;}
.fn-flex-item{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;}
.fn-flex-item[flexsize="2"]{-webkit-box-flex:2;-webkit-flex:2;-ms-flex:2;flex:2;}
.fn-flex-item[flexsize="3"]{-webkit-box-flex:3;-webkit-flex:3;-ms-flex:3;flex:3;}
.fn-flex-item[flexsize="4"]{-webkit-box-flex:4;-webkit-flex:4;-ms-flex:4;flex:4;}
.fn-flex-item[flexsize="5"]{-webkit-box-flex:5;-webkit-flex:5;-ms-flex:5;flex:5;}
.fn-flex-item[flexsize="6"]{-webkit-box-flex:6;-webkit-flex:6;-ms-flex:6;flex:6;}
.fn-flex-item[flexsize="7"]{-webkit-box-flex:7;-webkit-flex:7;-ms-flex:7;flex:7;}
.fn-flex-item[flexsize="8"]{-webkit-box-flex:8;-webkit-flex:8;-ms-flex:8;flex:8;}
.fn-flex-item[flexsize="9"]{-webkit-box-flex:9;-webkit-flex:9;-ms-flex:9;flex:9;}
.fn-flex-wrap{flex-wrap:wrap}/*多行*/
.justify-between{justify-content: space-between;}
.justify-center{justify-content:center;}
/*layout display*/
.block{display:block;}
.inline-block{display:inline-block;}
.fn-hide{display:none !important;}
.overflowhidden{overflow:hidden;}
.scroll-x{overflow-x:auto;}
.scroll-y{overflow-y:auto;}
/*layout position*/
.relative{position:relative;}
.absolute{position:absolute;}
.fixed{position:fixed;}
.top-0{top:0;}
.left-0{left:0;}
.bottom-0{bottom:0;}
.right-0{right:0;}
.z-index-0{z-index:0;}
.z-index-1{z-index:1;}
.z-index-2{z-index:2;}
.z-index-3{z-index:3;}
.z-index-4{z-index:4;}
.box-center-middle{top:50%;left:50%;transform:translate(-50%,-50%);}
.box-middle{top:50%;transform:translate(0,-50%);}
.box-center{left:50%;transform:translate(-50%,0);}
.box-border{box-sizing: border-box;}
// html,body{height:100%;background: #f0f0f0;}
// #stage{min-height:100%;_display:table;_height:100%;min-width:1200px;}
// #main{overflow:auto;padding-bottom:145px;padding-top:60px;}
// #footer{position:relative;margin-top:-145px;height:145px;clear:both;}
// body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
.wp20{width:20%;box-sizing:border-box;}
.wp25{width:25%;box-sizing:border-box;}
.wp33{width:33%;box-sizing:border-box;}
.wp40{width:40%;box-sizing:border-box;}
.wp50{width:50%;box-sizing:border-box;}
.wp60{width:60%!important;box-sizing:border-box;}
.wp65{width:65%!important;box-sizing:border-box;}
.wp70{width:70%!important;box-sizing:border-box;}
.wp80{width:80%!important;box-sizing:border-box;}
.wp90{width:90%;box-sizing:border-box;}
.wp100{width:100%;box-sizing:border-box;}
.transition-all{transition: all ease .2s;}
.op20{opacity: .2;}
+181
View File
@@ -0,0 +1,181 @@
/*
@Name: layer's style
@Author: 贤心
@Blog sentsin.com
*/
.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}
*html{background-image:url(about:blank);background-attachment:fixed}
html #layui_layer_skinlayercss{display:none;position:absolute;width:1989px}
.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}
.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+"px")}
.layui-layer{-webkit-overflow-scrolling:touch;top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px rgba(0,0,0,.3);border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}
.layui-layer-close{position:absolute}
.layui-layer-content{position:relative}
.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.3);box-shadow:1px 1px 5px rgba(0,0,0,.2)}
.layui-layer-moves{position:absolute;border:3px solid #666;border:3px solid rgba(0,0,0,.5);cursor:move;background-color:#fff;background-color:rgba(255,255,255,.3);filter:alpha(opacity=50)}
.layui-layer-load{background:url(../../images/global/loading-0.gif) center center no-repeat #fff}
.layui-layer-ico{background:url(../../images/global/layer-icon.png) no-repeat}
.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}
@-webkit-keyframes bounceIn{
0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}
100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}
}
@keyframes bounceIn{
0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}
100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}
}
.layer-anim{-webkit-animation-name:bounceIn;animation-name:bounceIn}
@-webkit-keyframes bounceOut{
100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}
30%{-webkit-transform:scale(1.03);transform:scale(1.03)}
0%{-webkit-transform:scale(1);transform:scale(1)}
}
@keyframes bounceOut{
100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}
30%{-webkit-transform:scale(1.03);-ms-transform:scale(1.03);transform:scale(1.03)}
0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}
}
.layer-anim-close{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}
@-webkit-keyframes zoomInDown{
0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}
60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}
}
@keyframes zoomInDown{
0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}
60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}
}
.layer-anim-01{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}
@-webkit-keyframes fadeInUpBig{
0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}
100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}
}
@keyframes fadeInUpBig{
0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}
100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}
}
.layer-anim-02{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}
@-webkit-keyframes zoomInLeft{
0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}
60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}
}
@keyframes zoomInLeft{
0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}
60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}
}
.layer-anim-03{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}
@-webkit-keyframes rollIn{
0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}
100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}
}
@keyframes rollIn{
0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}
100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}
}
.layer-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}
@keyframes fadeIn{
0%{opacity:0}
100%{opacity:1}
}
.layer-anim-05{-webkit-animation-name:fadeIn;animation-name:fadeIn}
@-webkit-keyframes shake{
0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}
10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}
20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}
}
@keyframes shake{
0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}
10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}
20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}
}
.layer-anim-06{-webkit-animation-name:shake;animation-name:shake}
@-webkit-keyframes fadeIn{
0%{opacity:0}
100%{opacity:1}
}
.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;background-color:#F8F8F8;border-radius:2px 2px 0 0}
.layui-layer-setwin{position:absolute;right:15px;*right:0;top:15px;font-size:0;line-height:initial}
.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}
.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}
.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}
.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}
.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}
.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}
.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}
.layui-layer-setwin .layui-layer-close1{background-position:0 -40px;cursor:pointer}
.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}
.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}
.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}
.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto}
.layui-layer-btn a{height:28px;line-height:28px;margin:0 6px;padding:0 15px;border:1px solid #dedede;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}
.layui-layer-btn a:hover{opacity:.9;text-decoration:none}
.layui-layer-btn a:active{opacity:.7}
.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}
.layui-layer-dialog{min-width:260px}
.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}
.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}
.layui-layer-ico1{background-position:-30px 0}
.layui-layer-ico2{background-position:-60px 0}
.layui-layer-ico3{background-position:-90px 0}
.layui-layer-ico4{background-position:-120px 0}
.layui-layer-ico5{background-position:-150px 0}
.layui-layer-ico6{background-position:-180px 0}
.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}
.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}
.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}
.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}
.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}
.layui-layer-page .layui-layer-content{position:relative;overflow:auto}
.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}
.layui-layer-nobg{background:0 0}
.layui-layer-iframe .layui-layer-content{overflow:hidden}
.layui-layer-iframe iframe{display:block;width:100%}
.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}
.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(../../images/global/loading-0.gif) no-repeat}
.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(../../images/global/loading-1.gif) no-repeat}
.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(../../images/global/loading-2.gif) no-repeat}
.layui-layer-tips{background:0 0;box-shadow:none;border:none}
.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:3px;box-shadow:1px 1px 3px rgba(0,0,0,.3);background-color:#F90;color:#fff}
.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}
.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}
.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#F90}
.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}
.layui-layer-tips i.layui-layer-TipsB{top:-8px}
.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:1px;border-bottom-style:solid;border-bottom-color:#F90}
.layui-layer-tips i.layui-layer-TipsR{left:-8px}
.layui-layer-tips i.layui-layer-TipsL{right:-8px}
.layui-layer-lan[type=dialog]{min-width:280px}
.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}
.layui-layer-lan .layui-layer-btn{padding:10px;text-align:right;border-top:1px solid #E9E7E7}
.layui-layer-lan .layui-layer-btn a{background:#BBB5B5;border:none}
.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}
.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}
.layui-layer-molv .layui-layer-btn a{background:#009f95}
.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}
.layui-layer-iconext{background:url(../../images/global/layer-icon-ext.png) no-repeat}
.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}
.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}
.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}
.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}
.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}
.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}
.layui-layer-tab .layui-layer-title span:first-child{border-left:none}
.layui-layer-tabmain{line-height:24px;clear:both}
.layui-layer-tabmain .layui-layer-tabli{display:none}
.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}
.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}
.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s}
.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}
.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}
.layui-layer-imgbar,.layui-layer-imguide{display:none}
.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}
.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}
.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}
.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}
.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}
.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}
.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}
.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}
.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}
.layui-layer-imgtit em{padding-left:10px;font-style:normal}
+89
View File
@@ -0,0 +1,89 @@
#nav{
background:rgba(16,22,30,.5);
height: 48px;
// position: fixed;
top: 50px;
width: 100%;
z-index: 10;
.icon-arrow{
transition: .2s all ease-in;
width: 12px;
height: 12px;
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAb1BMVEUAAADMzMzNzc3MzMzMzMzMzMzMzMzMzMzNzc3Nzc3Nzc3MzMzZ2dnMzMzNzc3IyMjMzMzMzMzNzc3Ly8vMzMzNzc3MzMzNzc3Nzc3MzMzKysrOzs7MzMzMzMzMzMzMzMzMzMzMzMzLy8vMzMzMzMzDCjeDAAAAJHRSTlMA+kP18Nt35aRoUwwGiScc0sKxlIJvWk48NzUV5t/Ps5yNYl8rrKDyAAAAwklEQVQ4y92R2RKCMAxFU7qDguwI7ub/v1GamU5By/is54XkHtrOJPAb7L5Ixc7jlh40syAQxRD3CUfUcEVEnsR8z2ZlIJMbf6TOHzKAXMwF69995/ypoKdcybq1tzjDj0A8XMOeS9+iI/XtnlobvKJAhaCioPVtQ62BQHbxR8KF5WrEhaawcXVNpZxgxcgp3gPcqBD5x1yQqA19WGRyChdYiGCCv8d3X3pfQZxJkqYNxaG9oS5gk4SFDcVJpUzgD3kB1aoYrYug5P4AAAAASUVORK5CYII=');
}
ul {
height: 48px;
li {
height: 100%;
margin-right: 34px;
a {
height: 48px;
line-height: 48px;
}
dl{
display: none;
}
a:hover {
background-color: #EB5359;
}
&:hover{
dl{
display: block;
}
a.nav_f_link{
background-color: #EB5359;
}
.icon-arrow{
transform: rotate(180deg);
}
}
}
.active {
background-color: #EB5359;
}
}
&.jewelry-nav{
height: 68px;
h1{
text-indent: -999em;
margin-top: 20px;
}
ul{
height: 68px;
line-height: 68px;
li{
a{
height: 68px;
line-height: 68px;
position: relative;
&:hover {
background-color: transparent;
color: #51D3F4;
&::after{
// background-color: #51D3F4;
}
}
&::after{
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4px;
}
}
&.active{
background-color: transparent;
a{
background-color: transparent;
color: #51D3F4;
&::after{
background-color: #51D3F4;
}
}
}
}
}
}
}
+57
View File
@@ -0,0 +1,57 @@
// .pages{font-size:12px;padding-bottom:20px;color:#888}
// .pages a,.pages span{display:inline-block;padding:4px 9px;margin:0 2px}
// .pages a{border:1px solid #ddd;color:#42b1e6}
// .pages a.current,.pages a:hover{border-color:#42b1e6;background-color:#42b1e6;color:#fff}
// .pages span{background-color:#efefef;border:1px solid #efefef}
@use '../../base/variable';
.pagination{
font-size: 16px;
color: #999;
text-align: center;
&.jewelry-pagination{
span{
&.active{
color: #1F1D32;
background-color: rgba($color: #fff, $alpha: .2);
}
}
a{
color: #445A6E;
background-color: rgba($color: #fff, $alpha: .03);
&:hover{
color: #1F1D32;
background-color: rgba($color: #fff, $alpha: .2);
}
}
}
span{
margin: 0 3px;
&.active{
display: inline-block;
width: 36px;
height: 36px;
line-height: 36px;
text-align: center;
color: #fff;
background-color: $defaultColor;
}
}
a{
margin: 0 3px;
display: inline-block;
width: 36px;
height: 36px;
line-height: 36px;
text-align: center;
color: #999;
background-color: #f0f0f0;
&.jump-btn{
background-color: inherit;
color: #999;
}
}
input[type=text]{
width: 30px;
border: 1px solid #eee;
}
}
+17
View File
@@ -0,0 +1,17 @@
// .pos .fl {
// line-height: 50px;
// height: 50px;
// }
// .pos .fr {
// margin-top: 8px;
// }
// .pos .btn {
// padding: 5px 30px;
// margin-left: 5px;
// }
// .pos-bottom-line {
// border-bottom: 1px solid #f3f3f3;
// }
+168
View File
@@ -0,0 +1,168 @@
html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,code,del,dfn,em,img,q,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border-style:none}
html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,code,del,dfn,em,img,q,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,textarea,input[type="text"]{font-size:100%;vertical-align:baseline}
body{color:#333}
body,button,input,select,textarea{font:16px/1.6 tahoma,arial,'Hiragino Sans GB',\5FAE\8F6F\96C5\9ED1,\5b8b\4f53,"WenQuanYi Micro Hei",sans-serif;}
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}
audio,canvas,video{display:inline-block;*display:inline;*zoom:1}
audio:not([controls]){display:none}
button,select,input{vertical-align:middle!important;}
[hidden]{display:none}
*{-webkit-text-size-adjust:none}
*:focus{outline:none}
a{color:#333;text-decoration:none}
a:focus,input:focus{-moz-outline-style:none;outline-style:none}
a:hover{text-decoration:none; }
del{text-decoration:line-through}
table{border-collapse:collapse;border-spacing:0}
ul,ol{list-style:none}
textarea{resize:none}
em,i{font-style:normal}
img{vertical-align:middle}
a,a img,a p,a i{transition: all 0.5s ease;}
hr {
border-color: #c0c0c0;
}
* {
// box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
}
ul,
ol {
list-style: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
input:focus,
select:focus,
textarea:focus {
outline: none;
}
em {
font-style: normal;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
input[type="search"] {
-webkit-appearance: textfield;
box-sizing: content-box;
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
a {
text-decoration: none;
color: #333;
}
body,
button,
select,
textarea {
font-family: '\5FAE\8F6F\96C5\9ED1', Tahoma, Arial, Helvetica, sans-serif;
}
html {
width: 100%;
}
+107
View File
@@ -0,0 +1,107 @@
@use '../../base/variable';
aside{
margin-right: 20px;
margin-bottom: 100px;
.icon{
&.icon-sidemenu{
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAilBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2N2iNAAAALnRSTlMAzMfDrQS5cSKyvqOHOjcqC2RTMyeWTZOOd1pCLhgOCIJ/HKedi15WSEYSmWk92D2yHgAAAWxJREFUOMuNUleSgzAUe7IdegkdQgqQnt3c/3prEwgl7Ez0YWSkQXrG9D1WZX20GBdOul+UNxp4UuhFLp/6p8U4InuuXtyvmebO9MgyvbHdZuFEj7n9mAY6uI+2B1PMQ1c5b4bdLzNojrWWDZzr9Ikb/J6m2NECtKJnzkmtO1Vz32Z5pRq4MHuDqRICyMkiDkdR5G3GujPwq2zNAI0yAAaZAORUW/TVoQ7FAgQ5gOyTSK/M8BF3BiuQS6mZETW2dZFtzsmWiNx395NDS7jwqO7OyVotGX4yF17LYtwXdAMpiarzioVPnLUD6d1R+Kz40FOkRFfW7QJsZrrHzjQyUAV9khKy04HoHaEogkH2E+RKp2M1vBS6LF7GjeEGNqzwlQN3Ygg5Wtib119aC5tGhtpBHt3C1Hv09yjh8chgg6lJoizudcGek7mqVvE1JBvPd10ycKclrAMTCs4WW/oHjVtGF2YNhkX4wj7QV/gDHrcSzCNIwDQAAAAASUVORK5CYII=');
}
&.icon-sidetop{
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAQlBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////8IX9KGAAAAFnRSTlMAzF8wNsPHM75IPidCK0OphXtyDLYWIEJABAAAAIlJREFUOMvtytsOgjAURNE5tvRCuQn6/7/qsUaqKY4h4ZHJvO2F/5uEbFIQGAgK0oUs4fClWzC0B5GGiF67Cs86Eblf9e6HMI1INCJ22BbaXcQToNsSPvcXyMLWfcAb1MLmXgDab5G0dyigElFciwJWYYro8QFWMaOsBvDznQPdCQjwFCzjuGDfHn+FBHlvISY6AAAAAElFTkSuQmCC');
}
&.icon-sideqq{
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABMUlEQVQ4T53TrWvXURTH8dfHB3CyGS0mm0yMsjKD2QcGIou6JjZxccKKK66LSQ1iEEw6cdWysCiu7R8wiCbxgSMXft/x5Sub33nK5Tx83px7z7kxsKo6hru4hdlJ+iOe4kmS331J+k5VncAGLg/BE/89rif50eWHgEdY3kfchR8mWfkLUFUn8RntPMi+4nTXxV4HVTWPD/8Qd+mLSbab0wfcweORgKUkz4aAN7gyEvA6yY09QFVdxUtMjwR8w80km6mqM/iEUyPFXdkXnGuAddw/pLgrX2uAXZz9T8BOA3zHJq4dAlJ4i0sNcAFt19sjLo6EPMcSzvf3YAGv0D7TQdb+wUKSd/0xTqGt6PGBssWOYGYQb9eeSfKr38Ft3GujwU9s4cEEuoo5HMUO1pO8aNA/evBej0fxIBEAAAAASUVORK5CYII=');
}
}
ul{
height: 120px;
li{
margin-bottom: 5px;
&:first-of-type{
span{
background-color: $defaultColor;
}
&.on,&:hover{
span{
background-color: darken($color: $defaultColor, $amount: 7);
}
}
}
&.on,&:hover{
span{
background-color: #666;
}
}
&:hover{
.aside-tooltip{
display: block;
}
}
span{
display: inline-block;
width: 50px;
height: 50px;
border-radius: 100%;
background-color: #aaa;
transition: .1s all ease-in;
cursor: pointer;
&#retTop{
display: none;
}
i{
width: 25px;
height: 25px;
}
}
.aside-tooltip{
display: none;
width: 180px;
height: 340px;
top: 50%;
left: -200px;
border-radius: 10px;
transform: translateY(-50%);
box-shadow: 0px 5px 10px 0px rgba(200, 200, 200, 0.2);
&-arrow{
width: 50px;
height: 25px;
top: 50%;
left: 167px;
transform: translateY(-50%) rotate(-90deg);
overflow: hidden;
&::after {
content: "";
position: absolute;
width: 20px;
height: 20px;
background: white;
transform: translateX(-50%) translateY(-50%) rotate(45deg);
top: 0;
left: 50%;
box-shadow: 1px 1px 10px 0px rgba(200, 200, 200, 0.2);
}
}
&-main{
.btn{
width: 120px;
height: 36px;
line-height: 36px;
background-color: $defaultColor;
border-radius: 100px;
text-align: center;
color: #fff;
&:hover{
background-color: lighten($color: $defaultColor, $amount: 10);
}
}
i{
width: 16px;
height: 16px;
margin-right: 3px;
}
}
}
}
}
}
+54
View File
@@ -0,0 +1,54 @@
.yahei{font-family:"Microsoft Yahei","微软雅黑",Tahoma,Arial,Helvetica,STHeiti}
.tc{text-align:center}
.tr{text-align:right}
.ti {text-indent:2em;}
.font-12{font-size:12px;}
.font-14{font-size:14px;}
.font-16{font-size:16px;}
.font-18{font-size:18px;}
.font-20{font-size:20px;}
.font-22{font-size:22px;}
.font-24{font-size:24px;}
.font-26{font-size:26px;}
.font-28{font-size:28px;}
.font-30{font-size:30px;}
.font-32{font-size:32px;}
.font-34{font-size:34px;}
.font-36{font-size:36px;}
.font-38{font-size:38px;}
.font-40{font-size:40px;}
.font-42{font-size:42px;}
.font-44{font-size:44px;}
.font-46{font-size:46px;}
.font-48{font-size:48px;}
.font-50{font-size:50px;}
.font-56{font-size:56px;}
.font-58{font-size:58px;}
.font-60{font-size:60px;}
.font-62{font-size:62px;}
.font-80{font-size: 80px;}
/*text render*/
.text-nowrap{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.text-left{text-align:left;}
.text-center{text-align:center;}
.text-right{text-align:right;}
.text-underline{text-decoration:underline;}
.text-through{text-decoration:line-through;}
.text-middle{vertical-align:middle}
.text-lighter{font-weight:400;}
.text-italic{font-style: italic;}
.text-bold{font-weight:600;}
.text-break{word-break:break-all;word-wrap:break-word;}
.space-nowrap{white-space:nowrap;}
.space-normal{white-space:normal;}
.text-arial{font-family: Arial, Helvetica, sans-serif;}
.cursor-pointer{cursor: pointer;}
/*line-clamp*/
.line-clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;}
.line-clamp-3{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;}
.line-height-1{line-height:1}
.line-height-15{line-height:1.5}
.line-height-17{line-height:1.7}
+74
View File
@@ -0,0 +1,74 @@
@use '../base/_variable';
@use 'pc/_reset';
@use 'pc/_border';
@use 'pc/_box';
@use 'pc/_btn';
@use 'pc/_color';
@use 'pc/_footer';
@use 'pc/_header';
@use 'pc/_nav';
@use 'pc/_iconfont';
@use 'pc/_layout';
// @use '_layui';
@use 'pc/_page';
// @use '_pos';
@use 'pc/_word';
@use 'pc/_side';
@use 'pc/_imgsize';
@use 'pc/_icon';
html {
height: 100%;
}
body {
min-height: 100%;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
html,body{
background-color: #f2f5f6;
}
.wrap {
width: 1200px;
margin: 0 auto;
}
.min-wrap {
width: 1000px;
margin: 0 auto;
}
.icon{
// display: inline-block;
// vertical-align: middle;
// background-repeat: no-repeat;
// background-position: center;
// background-size: cover;
// text-indent: -999em;
}
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-slide {
text-align: center;
font-size: 18px;
background: #fff;
/* Center slide text vertically */
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+199
View File
@@ -0,0 +1,199 @@
/**
* LArea移动端城市选择控件
*
* version:1.7.2
*
* author:黄磊
*
* git:https://github.com/xfhxbb/LArea
*
* Copyright 2016
*
* Licensed under MIT
*
* 最近修改于 2016-6-12 16:47:41
*/
@use '_mixin';
.gearArea {
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
@include font-dpr($defaultFont*.6);
background-color: rgba(0, 0, 0, 0.2);
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9900;
overflow: hidden;
-webkit-animation-fill-mode: both;
animation-fill-mode: both
}
.area_ctrl {
vertical-align: middle;
background-color: #d5d8df;
color: #000;
margin: 0;
height: auto;
width: 100%;
position: absolute;
left: 0;
bottom: 0;
z-index: 9901;
overflow: hidden;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0)
}
.slideInUp {
-webkit-animation: slideInUp .3s;
animation: slideInUp .3s;
}
@-webkit-keyframes slideInUp {
from {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0)
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0)
}
}
@keyframes slideInUp {
from {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0)
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0)
}
}
.area_roll {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
width: 100%;
height: auto;
overflow: hidden;
background-color: transparent;
-webkit-mask: -webkit-gradient(linear, 0% 50%, 0% 100%, from(#debb47), to(rgba(36, 142, 36, 0)));
-webkit-mask: -webkit-linear-gradient(top, #debb47 50%, rgba(36, 142, 36, 0))
}
.area_roll>div {
font-size: 1.6em;
height: 10em;
float: left;
background-color: transparent;
position: relative;
overflow: hidden;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1
}
.area_roll>div .gear {
width: 100%;
float: left;
position: absolute;
z-index: 9902;
margin-top: 4em
}
.area_roll_mask {
-webkit-mask: -webkit-gradient(linear, 0% 40%, 0% 0%, from(#debb47), to(rgba(36, 142, 36, 0)));
-webkit-mask: -webkit-linear-gradient(bottom, #debb47 50%, rgba(36, 142, 36, 0));
padding: 0
}
.area_grid {
position: relative;
top: 4em;
width: 100%;
height: 2em;
margin: 0;
box-sizing: border-box;
z-index: 0;
border-top: 1px solid #abaeb5;
border-bottom: 1px solid #abaeb5
}
.area_roll>div:nth-child(3) .area_grid>div {
left: 42%
}
.area_btn {
color: #0575f2;
font-size: 1.6em;
line-height: 1em;
text-align: center;
padding: .8em 1em
}
.area_btn_box:before,
.area_btn_box:after {
content: '';
position: absolute;
height: 1px;
width: 100%;
display: block;
background-color: #96979b;
z-index: 15;
-webkit-transform: scaleY(0.33);
transform: scaleY(0.33)
}
.area_btn_box {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
-webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch;
background-color: #f1f2f4;
position: relative
}
.area_btn_box:before {
left: 0;
top: 0;
-webkit-transform-origin: 50% 20%;
transform-origin: 50% 20%
}
.area_btn_box:after {
left: 0;
bottom: 0;
-webkit-transform-origin: 50% 70%;
transform-origin: 50% 70%
}
.tooth {
height: 2em;
line-height: 2em;
text-align: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
line-clamp: 1;
-webkit-box-orient:vertical;
-webkit-box-direction:normal;
-webkit-flex-direction:column;
-ms-flex-direction:column;
flex-direction:column;
overflow: hidden
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+221
View File
@@ -0,0 +1,221 @@
/*!
* fullPage 2.9.7
* https://github.com/alvarotrigo/fullPage.js
* MIT licensed
*
* Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
*/
html.fp-enabled,
.fp-enabled body {
margin: 0;
padding: 0;
overflow:hidden;
font-family: "PingFangSC-Regular","Microsoft YaHei",Helvetica,Arial;
/*Avoid flicker on slides transitions for mobile phones #336 */
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
.fp-section {
position: relative;
-webkit-box-sizing: border-box; /* Safari<=5 Android<=3 */
-moz-box-sizing: border-box; /* <=28 */
box-sizing: border-box;
}
.fp-slide {
float: left;
}
.fp-slide, .fp-slidesContainer {
height: 100%;
display: block;
}
.fp-slides {
z-index:1;
height: 100%;
overflow: hidden;
position: relative;
-webkit-transition: all 0.3s ease-out; /* Safari<=6 Android<=4.3 */
transition: all 0.3s ease-out;
}
.fp-section.fp-table, .fp-slide.fp-table {
display: table;
table-layout:fixed;
width: 100%;
}
.fp-tableCell {
display: table-cell;
vertical-align: middle;
width: 100%;
height: 100%;
}
.fp-slidesContainer {
float: left;
position: relative;
}
.fp-controlArrow {
-webkit-user-select: none; /* webkit (safari, chrome) browsers */
-moz-user-select: none; /* mozilla browsers */
-khtml-user-select: none; /* webkit (konqueror) browsers */
-ms-user-select: none; /* IE10+ */
position: absolute;
z-index: 4;
top: 50%;
cursor: pointer;
width: 0;
height: 0;
border-style: solid;
margin-top: -38px;
-webkit-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}
.fp-controlArrow.fp-prev {
left: 15px;
width: 0;
border-width: 38.5px 34px 38.5px 0;
border-color: transparent #fff transparent transparent;
}
.fp-controlArrow.fp-next {
right: 15px;
border-width: 38.5px 0 38.5px 34px;
border-color: transparent transparent transparent #fff;
}
.fp-scrollable {
overflow: hidden;
position: relative;
}
.fp-scroller{
overflow: hidden;
}
.iScrollIndicator{
border: 0 !important;
}
.fp-notransition {
-webkit-transition: none !important;
transition: none !important;
}
#fp-nav {
position: fixed;
z-index: 100;
margin-top: -32px;
top: 50%;
opacity: 1;
-webkit-transform: translate3d(0,0,0);
}
#fp-nav.right {
right: 17px;
}
#fp-nav.left {
left: 17px;
}
.fp-slidesNav{
position: absolute;
z-index: 4;
opacity: 1;
-webkit-transform: translate3d(0,0,0);
-ms-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
left: 0 !important;
right: 0;
margin: 0 auto !important;
}
.fp-slidesNav.bottom {
bottom: 17px;
}
.fp-slidesNav.top {
top: 17px;
}
#fp-nav ul,
.fp-slidesNav ul {
margin: 0;
padding: 0;
}
#fp-nav ul li,
.fp-slidesNav ul li {
display: block;
width: 14px;
height: 13px;
margin: 7px;
position:relative;
}
.fp-slidesNav ul li {
display: inline-block;
}
#fp-nav ul li a,
.fp-slidesNav ul li a {
display: block;
position: relative;
z-index: 1;
width: 100%;
height: 100%;
cursor: pointer;
text-decoration: none;
}
#fp-nav ul li a.active span,
.fp-slidesNav ul li a.active span,
#fp-nav ul li:hover a.active span,
.fp-slidesNav ul li:hover a.active span{
height: 12px;
width: 12px;
margin: -6px 0 0 -6px;
border-radius: 100%;
}
#fp-nav ul li a span,
.fp-slidesNav ul li a span {
border-radius: 50%;
position: absolute;
z-index: 1;
height: 4px;
width: 4px;
border: 0;
background: #333;
left: 50%;
top: 50%;
margin: -2px 0 0 -2px;
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-o-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
}
#fp-nav ul li:hover a span,
.fp-slidesNav ul li:hover a span{
width: 10px;
height: 10px;
margin: -5px 0px 0px -5px;
}
#fp-nav ul li .fp-tooltip {
position: absolute;
top: -2px;
color: #fff;
font-size: 14px;
font-family: arial, helvetica, sans-serif;
white-space: nowrap;
max-width: 220px;
overflow: hidden;
display: block;
opacity: 0;
width: 0;
cursor: pointer;
}
#fp-nav ul li:hover .fp-tooltip,
#fp-nav.fp-show-active a.active + .fp-tooltip {
-webkit-transition: opacity 0.2s ease-in;
transition: opacity 0.2s ease-in;
width: auto;
opacity: 1;
}
#fp-nav ul li .fp-tooltip.right {
right: 20px;
}
#fp-nav ul li .fp-tooltip.left {
left: 20px;
}
.fp-auto-height.fp-section,
.fp-auto-height .fp-slide,
.fp-auto-height .fp-tableCell{
height: auto !important;
}
.fp-responsive .fp-auto-height-responsive.fp-section,
.fp-responsive .fp-auto-height-responsive .fp-slide,
.fp-responsive .fp-auto-height-responsive .fp-tableCell {
height: auto !important;
}
+33
View File
@@ -0,0 +1,33 @@
@mixin icon($iconName){
&.icon{
background-size: 100% auto;
background-repeat: no-repeat;
vertical-align: middle;
display: inline-block;
&-#{$iconName}{
@include iconBg($iconName);
}
}
}
@mixin iconBg($iconName){
@if $iconName == couponCate{
@include px2rem(width, 30px);
@include px2rem(height, 30px);
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA1ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDJGRjI2RDA1RjZGMTFFNkFBMTdFODlFMUZFRUJGNTgiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDJGRjI2Q0Y1RjZGMTFFNkFBMTdFODlFMUZFRUJGNTgiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDNzA2QzhERDRDOUFFNTExQTVGREQzMzg2QTEyNEYwRSIgc3RSZWY6ZG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6ptfv1AAAAYFBMVEWqqqrp6enS0tKxsbGZmZny8vKkpKTu7u7i4uLm5ubw8PCtra2mpqacnJze3t6ioqLIyMigoKD19fW8vLz+/v74+Pi4uLjs7Oy1tbXb29u6urr7+/uenp6fn5+Wlpb////uMPHNAAABkklEQVR42nyT65KsIAyEUeTiKqCiqKM27/+WJ4iOZ7d2Jz+sSn8SYiey+DFYbPpj33fjwrplabPBGZKOviF8wEmKHggi0eEF9ElxOBJ2WiilirIFn2KcOGRZkyBqmfAuRS6qGLoYOzCV86Hd02l5pVFDDlMLfaVf8juOrNK1YfEb3h/ssVqEOxNncXcUt7DA6orf2ex6wgvKKx/MoURvrk5jSW+yaHFX91jGMcCP+eoWK+EtgKVmhYeha4odPp3XDMtGOAoONH4xMGs6te4wi28ALpLnZFTXVmRkqPMdRXBAJbshZkxN6dWqZ07Krnq4JpZiqq0WDxba1tMbb11rULnX9f2zlxUM66aMhwVggRscNlHrYHhgd2vbC62lT1Ueyb+5R6A2RssQtmzLfBYdPcIYQ3qc/cnTlvA2VSRT3WMqFsLyGQmv/h9J0buPA/25Ds0v6/DgmpZpkD+W6b2KX3+sohYUqmRoyOiBg5VzUvIiH5AthQSWs4wgE11WEmaHSXHwNU8hTiu/JBbZ51/wnwADAJF9UKGx+KqMAAAAAElFTkSuQmCC");
@at-root{ .sel .icon-#{$iconName}{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA1ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzRCMzc3OEU1RjZGMTFFNjkyRTZDRDVBMzM2MDA4OTUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzRCMzc3OEQ1RjZGMTFFNjkyRTZDRDVBMzM2MDA4OTUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDNzA2QzhERDRDOUFFNTExQTVGREQzMzg2QTEyNEYwRSIgc3RSZWY6ZG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4MAIzjAAAAYFBMVEVnsv87nP/c7f/K5P9EoP/8/v+TyP/l8v/1+v/q9P+83f/G4v+n0v9crP/T6f9Npf90uP97vP9Bn//h8P9UqP9Qpv+22v9Jo/80mP9utv/g7//A3//v9/9LpP8yl/////8uXjs3AAABn0lEQVR42oRT2ZLjIBDjsvEFBgcCNo74/78c8DGppGpn/eSWikao1ST/+ZGshFjKF8zQnVCXTKiIEKrQIgY/z14Apq9sbwExFyREUenA5bY99ORB9px3Aj/pbdsknyu9eHk2ZQptzi0cO+veL/X0fJWZY+53h/EqH190VpRr6vIHvczbDVgMKZq7kgcdhL6BNaaRkrtioUozcbrqfhFMCnopzVNcCz3Ab3fvtWkMbHNe7fAsdGegqlhpsZRrtICt57nC2hU6SwIouy5YnvXUUH5WqwAiq+fFqNZTRGEuidqECOrbPZ90EcWHxN5zYmkY+2tix5B0GuWblmPS+y/dtY6CBns1ZzbQSN3dvF8BZwiFGCqbAigxrkjrK91ZuFSe+rCo/jEBU3xokoOpD0t4naoai+K3gTltYR5DNRW3qXIRmwxfpr7eIyEx8fg7Eh3C/wf6EYeRU5X/kRYeS5g8+FdaLi2PK4pq+4hi4L2Ukk0O6gyym1gBpD6CLOLLee9ewHq0kcXEcCDHGqhjh6ggz3uJnkTQY4tUJn+v4I8AAwCKflB8vJZGnwAAAABJRU5ErkJggg==")!important;
}
}
}
@if $iconName == couponStatus{
@include px2rem(width, 30px);
@include px2rem(height, 30px);
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA1ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDNEODNBMkE1RjZGMTFFNkFBMTdFODlFMUZFRUJGNTgiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDNEODNBMjk1RjZGMTFFNkFBMTdFODlFMUZFRUJGNTgiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDNzA2QzhERDRDOUFFNTExQTVGREQzMzg2QTEyNEYwRSIgc3RSZWY6ZG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6fd1xcAAAAYFBMVEXh4eHFxcX9/f3R0dGzs7Pu7u719fXBwcGhoaG9vb3Nzc26urq1tbXc3Nz5+fnk5OStra3Jycm4uLjZ2dnm5uapqano6Ojr6+uenp7V1dXU1NTX19eampqWlpaZmZn///8Amk9LAAABAklEQVR42pTS25KDIAwGYESLCj2wasUDkfd/ywYKLLK0M5sLZ5xvIIm/xHwtYp76+FNazoG1GPe8NqkvgffCpbRrA2+lptfmnzxVfUUCNzlzAA3QfuALSMWUhEeZa1D4nOGnzBUw2x+qMs8bxXWlu6M0mq0eti97c6g/LmaHFzEpP0PKN5ij9pTkTBYWVBjhxjj1vie6CDtIynfhsn24sxUOygujodLhEDASDOB0+cy84pfnLp487/dZzGV04SGvqR5e9/fiyDzVgV6PKSrysCjqK+oagiOGPaHzBY3pT4ps6I37qim1rbaohpx/UAUTq3815xE6Hf6nAnPZrip5fwkwAGnQW6BSDmsdAAAAAElFTkSuQmCC");
@at-root{ .sel .icon-#{$iconName}{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA1ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzU5RDI3NUM1RjZGMTFFNjkyRTZDRDVBMzM2MDA4OTUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzU5RDI3NUI1RjZGMTFFNjkyRTZDRDVBMzM2MDA4OTUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDNzA2QzhERDRDOUFFNTExQTVGREQzMzg2QTEyNEYwRSIgc3RSZWY6ZG9jdW1lbnRJRD0iQjcwODdBM0U2M0FDMDAzMTdBN0JBQzE4RTg2QUM5MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7TDn4IAAAAYFBMVEWIw/9rtP/L5P/b7f97vP+czP9Gof/o8//6/f81mP9aq/91uf/9/v+z2f/E4f+k0f/U6f+x1//z+f+Vyf9wtv+Pxv9ir/+52/8zl//w9//P5/+r1P86m/84mv8yl/////+hMbWMAAABCUlEQVR42pTS7ZKDIAwFUORL0Cq4q3ZVDO//lg2tWFHamb2/dM4AySTEfw3xlVsvcaON7HjTndIslWORu8ylSpLIS+7RvvgnzwMf2sjFmQ2AAyAfmOmKTWwEmmcDoVULv3kmMIX3YcizXW7Y7qjZh9JCOCxf+hZg9sbGC5eax8/2b7jwHWxU4IqeuZXlrlsZyds/8WZUyUMhR57q52wpao39CxAJMwilUahv9cp10+IAksttGc6iaopnw3jO86b6pdgGua5D0D5o9xotsnnr/NR5V+RaMrWFrr3qV9QlDo74sgK5BQrPE0X26i62GKWcOKon6YIymCfz1jM3IF3cpwyLkXT28P8QYADlJVogiQc9hgAAAABJRU5ErkJggg==")!important;
}
}
}
}
+41
View File
@@ -0,0 +1,41 @@

//****使用方法****///
// @include keyframes(move-the-object) {
// 0% { left: 100px; }
// 100% { left: 200px; }
// }
// .object-to-animate {
// @include animation('move-the-object .5s 1', 'move-the-object-again .5s 1 .5s');
// }
@mixin animation($animate...) {
$max: length($animate);
$animations: '';
@for $i from 1 through $max {
$animations: #{$animations + nth($animate, $i)};
@if $i < $max {
$animations: #{$animations + ", "};
}
}
-webkit-animation: $animations;
-moz-animation: $animations;
-o-animation: $animations;
animation: $animations;
}
@mixin keyframes($animationName) {
@-webkit-keyframes #{$animationName} {
@content;
}
@-moz-keyframes #{$animationName} {
@content;
}
@-o-keyframes #{$animationName} {
@content;
}
@keyframes #{$animationName} {
@content;
}
}
+225
View File
@@ -0,0 +1,225 @@
//是否支持某个浏览器的前缀如果你不想支持可以设置为false
//----------------------------
$prefix-for-webkit: true !default;
$prefix-for-mozilla: false !default;
$prefix-for-microsoft: false !default;
$prefix-for-opera: false !default;
$prefix-for-spec: true !default; // 标准版
// prefixer
//----------------------------
@mixin prefixer ($property, $value, $prefixes) {
@each $prefix in $prefixes {
@if $prefix == webkit and $prefix-for-webkit == true {
-webkit-#{$property}: $value;
}
@else if $prefix == moz and $prefix-for-mozilla == true {
-moz-#{$property}: $value;
}
@else if $prefix == ms and $prefix-for-microsoft == true {
-ms-#{$property}: $value;
}
@else if $prefix == o and $prefix-for-opera == true {
-o-#{$property}: $value;
}
@else if $prefix == spec and $prefix-for-spec == true {
#{$property}: $value;
}
@else {
@warn "Unrecognized prefix: #{$prefix}";
}
}
}
@mixin skewX($degrees) {
@include prefixer(transform, skewX($degrees), webkit moz o ms spec);
-webkit-backface-visibility: hidden;
}
//webki和标准
@mixin box-shadow($shadow...) {
@include prefixer(box-shadow, $shadow, webkit spec);
}
//webkit moz 和标准
@mixin box-sizing($type:border-box) {
// border-box | padding-box | content-box
@include prefixer(box-sizing, $type, webkit moz spec);
}
//webkit moz o 和标准
@mixin transform($property...) {
@include prefixer(transform, $property, webkit moz o spec);
}
// triangle
@mixin triangle($direction, $size, $borderColor ) {
content:"";
height: 0;
width: 0;
@if $direction == top {
border-bottom:$size solid $borderColor;
border-left:$size dashed transparent;
border-right:$size dashed transparent;
}
@else if $direction == right {
border-left:$size solid $borderColor;
border-top:$size dashed transparent;
border-bottom:$size dashed transparent;
}
@else if $direction == bottom {
border-top:$size solid $borderColor;
border-left:$size dashed transparent;
border-right:$size dashed transparent;
}
@else if $direction == left {
border-right:$size solid $borderColor;
border-top:$size dashed transparent;
border-bottom:$size dashed transparent;
}
}
//定义media-queries的最小最大宽度
@mixin screen($res-min, $res-max){
@media screen and ( min-width: $res-min ) and ( max-width: $res-max ){
@content;
}
}
//定义animation的keyframes
@mixin keyframes($name){
@keyframes #{$name} {
@content;
}
}
//定义所有不支持圆角的浏览器使用背景图片
//得使用[modernizr](http://modernizr.com/)来检测在html上加class
@mixin no-border-radius{
.no-border-radius{
@content
}
}
@mixin borderbottom1px($color){
&{
position: relative;
}
&:after{
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: $color;
}
}
@mixin bordertop1px($color){
&{
position: relative;
}
&:before{
position: absolute;
right: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: $color;
top: -1px;
}
}
@mixin border1px($color){
& {
position: relative;
}
&:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border: 1px solid;
border-color:$color;
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-ms-transform-origin: 0 0;
-o-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scale(0.5, 0.5);
-ms-transform: scale(0.5, 0.5);
-o-transform: scale(0.5, 0.5);
transform: scale(0.5, 0.5);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
left:50%;
@include prefixer(transform,translateX(-50%),(webkit,spec));
}
}
@mixin fn-wrap(){
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
@mixin font-dpr($font-size){
font-size: $font-size;
[data-dpr="2"] & {
font-size: $font-size * 2;
}
[data-dpr="3"] & {
font-size: $font-size * 3;
}
}
// @mixin px2rem($property,$px-values,$baseline-px:124px,$support-for-ie:false){
// //Conver the baseline into rems
// $baseline-rem: $baseline-px / 1rem * 1;
// //Print the first line in pixel values
// @if $support-for-ie {
// #{$property}: $px-values;
// }
// //if there is only one (numeric) value, return the property/value line for it.
// @if type-of($px-values) == "number"{
// #{$property}: $px-values / $baseline-rem;
// }
// @else {
// //Create an empty list that we can dump values into
// $rem-values:();
// @each $value in $px-values{
// // If the value is zero or not a number, return it
// @if $value == 0 or type-of($value) != "number"{
// $rem-values: append($rem-values, $value / $baseline-rem);
// }
// }
// // Return the property and its list of converted values
// #{$property}: $rem-values;
// }
// }
@function px2rem($px, $base-font-size:75px) {
@if (unitless($px)) {
@warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
@return px2rem($px + 0px); // That may fail.
}
@else if (unit($px)==rem) {
@return $px;
}
@return ($px / $base-font-size) * 1rem;
}
@function px2em($px, $base-font-size: 16px) {
@if (unitless($px)) {
@warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
@return px2em($px + 0px); // That may fail.
} @else if (unit($px) == em) {
@return $px;
}
@return ($px / $base-font-size) * 1em;
}
File diff suppressed because one or more lines are too long
+370
View File
@@ -0,0 +1,370 @@
import axios from 'axios';
import config from './config';
// 微信配置
const WECHAT_CONFIG = {
appId: '', // 需要配置你的微信公众号AppID
scope: {
BASE: 'snsapi_base', // 静默授权,获取openid
USERINFO: 'snsapi_userinfo' // 用户授权,获取用户信息
}
};
/**
* 微信授权相关方法
*/
const WechatAuth = {
/**
* 检查是否在微信浏览器中
*/
isWechatBrowser() {
const ua = navigator.userAgent.toLowerCase();
return ua.includes('micromessenger');
},
/**
* 获取URL参数
*/
getUrlParam(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
const r = window.location.search.substr(1).match(reg);
return r ? decodeURIComponent(r[2]) : null;
},
/**
* 微信网页授权登录
* @param {string} redirectUri - 授权后重定向的回调地址
* @param {string} scope - 授权作用域 'snsapi_base' | 'snsapi_userinfo'
* @param {string} state - 重定向后会带上state参数
*/
authorize(redirectUri, scope = WECHAT_CONFIG.scope.BASE, state = 'STATE') {
if (!this.isWechatBrowser()) {
console.warn('当前不在微信浏览器环境中');
return false;
}
const encodedUri = encodeURIComponent(redirectUri);
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${WECHAT_CONFIG.appId}&redirect_uri=${encodedUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`;
window.location.href = authUrl;
return true;
},
/**
* 处理授权回调获取code
*/
handleAuthCallback() {
const code = this.getUrlParam('code');
const state = this.getUrlParam('state');
if (code) {
return { code, state };
}
return null;
},
/**
* 通过code获取access_token和用户信息
* @param {string} code - 授权码
*/
async getAccessToken(code) {
try {
const urlParams = new URLSearchParams(window.location.search);
const friend_account_id = urlParams.get('friend_account_id');
const accountId = urlParams.get('accountId');
const response = service.post('/auto/login', {
code: code,
friend_account_id,
accountId
});
const result = await response;
console.log('获取access_token成功:', result.data);
if(result.data&&result.data.Authorization){
localStorage.setItem('token', result.data.Authorization);
}
// 保存token到本地存储
// if (result.access_token) {
// localStorage.setItem('token', result.access_token);
// localStorage.setItem('wechat_openid', result.openid);
// if (result.refresh_token) {
// localStorage.setItem('refresh_token', result.refresh_token);
// }
// }
return result;
} catch (error) {
console.error('获取access_token失败:', error);
throw error;
}
},
/**
* 自动处理微信授权流程
*/
async autoAuth() {
// 检查是否有授权回调的code
const authCallback = this.handleAuthCallback();
if (authCallback && authCallback.code) {
try {
await this.getAccessToken(authCallback.code);
// 清除URL中的code参数
const url = new URL(window.location);
url.searchParams.delete('code');
url.searchParams.delete('state');
window.history.replaceState({}, document.title, url.toString());
return true;
} catch (error) {
console.error('自动授权失败:', error);
return false;
}
}
return false;
},
/**
* 重新授权
*/
reAuth() {
// 清除本地token
localStorage.removeItem('token');
localStorage.removeItem('wechat_openid');
localStorage.removeItem('refresh_token');
// 重新发起授权
const currentUrl = window.location.href.split('?')[0].split('#')[0];
this.authorize(currentUrl);
}
};
// 创建axios实例,使用config中的基础配置
const service = axios.create({
baseURL: config.baseURL,
timeout: config.timeout,
headers: config.commonHeaders
});
// 请求拦截器:添加认证信息等
service.interceptors.request.use(
(config) => {
// 示例:从localStorage获取token并添加到请求头
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器:处理状态码和错误
let isAuthing = false; // 授权标记位
service.interceptors.response.use(
(response) => {
// 直接返回响应数据(根据后端接口规范调整)
return response.data;
},
async (error) => {
const { response } = error;
// 处理401未认证和400错误,重新进行微信授权
if (response && (response.status === 401 || response.status === 400)) {
console.warn('认证失败,准备重新授权:', response.status);
// 如果在微信浏览器中,自动重新授权
if (WechatAuth.isWechatBrowser() && !isAuthing) {
isAuthing = true;
try {
await WechatAuth.reAuth();
// 授权成功后刷新页面
window.location.reload();
} finally {
isAuthing = false;
}
return Promise.reject(new Error('正在重新授权,请稍候...'));
} else {
console.error('不在微信浏览器环境中,无法自动重新授权');
}
}
// 处理其他HTTP错误状态码
console.error('API请求失败:', response?.status);
return Promise.reject(error);
}
);
// 微信相关API方法
const wechatAPI = {
/**
* 获取微信appid
* GET /auto/config/wechat
*/
getWechatAppId() {
return service.get('/auto/config/wechat?url='+encodeURIComponent(location.href));
},
/**
* 微信授权登录获取token
* GET /auto/login
* @param {string} code - 微信授权code
* @param {number} friend_account_id - 分享用户id可选
* @param {number} accountId - 渠道用户id可选
*/
wechatLogin(code, accountId,friend_account_id) {
const params = { code };
if (accountId) {
params.accountId = accountId;
}
if (friend_account_id) {
params.friend_account_id = friend_account_id;
}
return service.get('/auto/login', params);
},
/**
* 经纬度解析转换城市编码
* GET /auto/config/city
* @param {number} latitude - 纬度
* @param {number} longitude - 经度
*/
getLocationCity(latitude, longitude) {
return service.get('/auto/config/city', {
params: {
latitude,
longitude
}
});
},
/**
* 获取产品详情
* GET /auto/car/product/detail
* @param {number} id - 产品id
*/
getProductDetail(id) {
return service.get('/auto/car/product/detail', {
params: {
id
}
});
},
/**
* 检查并处理微信登录
* 如果没有token自动进行微信授权登录
* @param {string} redirectUri - 授权回调地址
* @param {number} accountId - 渠道用户id可选
* @param {number} friend_account_id - 分享用户id可选
*/
async checkAndLogin(redirectUri, accountId,friend_account_id) {
const token = localStorage.getItem('token');
// 如果已有token,直接返回
if (token) {
return { success: true, token };
}
// 检查URL中是否有微信授权返回的code
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
if (code) {
try {
// 使用code获取token
const result = await this.wechatLogin(code, accountId,friend_account_id);
if (result.code === 200 && result.data?.Authorization) {
localStorage.setItem('token', result.data.Authorization);
// 清除URL中的code参数
const newUrl = window.location.pathname + window.location.hash;
window.history.replaceState({}, document.title, newUrl);
return { success: true, token: result.data.Authorization, userInfo: result.data };
} else {
throw new Error(result.message || '登录失败');
}
} catch (error) {
console.error('微信登录失败:', error);
return { success: false, error: error.message };
}
} else {
// 没有code,需要跳转到微信授权页面
try {
const appIdResult = await this.getWechatAppId();
console.log('获取微信AppID成功111:', appIdResult);
if (appIdResult.code === 200 && appIdResult.data?.appId) {
const appId = appIdResult.data.appId;
const encodedUri = encodeURIComponent(redirectUri);
const state = accountId || 'STATE';
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${encodedUri}&response_type=code&scope=snsapi_userinfo&state=${state}#wechat_redirect`;
localStorage.setItem('w_c', JSON.stringify(appIdResult.data));
localStorage.setItem('app_id', appId);
window.location.href = authUrl;
return { success: false, redirecting: true };
} else {
throw new Error('获取微信AppID失败');
}
} catch (error) {
console.error('获取微信AppID失败:', error);
return { success: false, error: error.message };
}
}
}
};
// 导出常用请求方法
// 获取微信配置
async function getWechatConfig() {
try {
const response = await service.get('/auto/config/wechat?url='+encodeURIComponent(location.href));
const config = await response.data;
if (config.appid) {
WECHAT_CONFIG.appId = config.appid;
console.log('微信AppID配置成功:', config.appid);
}
return config;
} catch (error) {
console.error('获取微信配置失败:', error);
return null;
}
}
// 初始化微信授权
if (WechatAuth.isWechatBrowser()) {
// 先获取微信配置,再处理授权回调
getWechatConfig().then(() => {
WechatAuth.autoAuth();
});
} else {
// 非微信环境也获取配置,以备后用
getWechatConfig();
}
// 导出常用请求方法和微信授权工具
export default {
get: (url, params) => service.get(url, { params }),
post: (url, data) => service.post(url, data),
put: (url, data) => service.put(url, data),
delete: (url) => service.delete(url),
upload: (data) => service.post('/auto/upload', data, { headers: { 'Content-Type': 'multipart/form-data' } }),
// 微信相关方法
wechatAPI: wechatAPI,
// 微信授权相关方法
wechatAuth: WechatAuth,
// 设置微信AppID
setWechatAppId: (appId) => {
WECHAT_CONFIG.appId = appId;
},
// 手动触发微信授权
triggerWechatAuth: (redirectUri, scope) => {
return WechatAuth.authorize(redirectUri, scope);
}
};

Some files were not shown because too many files have changed in this diff Show More