├── .gitattributes ├── .gitignore ├── src ├── assets │ ├── css │ │ ├── constant.scss │ │ └── style.css │ ├── logo.png │ ├── img │ │ └── tou_tiao.png │ └── icon │ │ ├── iconfont.eot │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ ├── iconfont.woff2 │ │ ├── iconfont.json │ │ ├── iconfont.css │ │ ├── demo.css │ │ ├── demo_index.html │ │ └── iconfont.svg ├── plugins │ ├── mitt.config.js │ ├── vant.js │ └── map.config.js ├── api │ ├── news.js │ ├── city.js │ ├── options.js │ ├── house.js │ ├── map.js │ └── http.js ├── store │ └── index.js ├── compositions │ ├── MapRoomList.js │ ├── RecommendRoomList.js │ ├── HomeRoomList.js │ ├── HouseDetailMap.js │ └── Panorama.js ├── utils │ ├── unit.js │ └── map.js ├── main.js ├── views │ ├── city_list │ │ ├── components │ │ │ ├── CityListNavBar.vue │ │ │ └── IndexBar.vue │ │ └── Main.vue │ ├── home │ │ ├── components │ │ │ ├── HomeOptionsItem.vue │ │ │ ├── HomeCard.vue │ │ │ ├── HomeTabs.vue │ │ │ ├── HomeNews.vue │ │ │ ├── HomeOptions.vue │ │ │ └── HomeNavBar.vue │ │ └── Main.vue │ ├── house_detail │ │ ├── components │ │ │ ├── HouseDetailSwiper.vue │ │ │ ├── HouseDetailNavBar.vue │ │ │ ├── HouseDetailMap.vue │ │ │ ├── HouseDetailDesc.vue │ │ │ └── HouseDetailPanorama.vue │ │ └── Main.vue │ ├── AppMain.vue │ └── map │ │ └── Main.vue ├── router │ └── index.js ├── components │ ├── RoomList.vue │ ├── NewsSwiper.vue │ ├── RoomItem.vue │ └── FloorScroll.vue └── App.vue ├── public └── favicon.ico ├── postcss.config.js ├── index.html ├── vite.config.js ├── package.json ├── LICENSE ├── docs ├── 代码更新与视频发布计划.md └── 接口文档.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html linguist-language=vue -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *.local -------------------------------------------------------------------------------- /src/assets/css/constant.scss: -------------------------------------------------------------------------------- 1 | $margin: 12px; 2 | // 主色 3 | $mainColor: #26ce97; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/img/tou_tiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/src/assets/img/tou_tiao.png -------------------------------------------------------------------------------- /src/assets/icon/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/src/assets/icon/iconfont.eot -------------------------------------------------------------------------------- /src/assets/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/src/assets/icon/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/icon/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/src/assets/icon/iconfont.woff -------------------------------------------------------------------------------- /src/assets/icon/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lgd8981289/vue-next-renting/HEAD/src/assets/icon/iconfont.woff2 -------------------------------------------------------------------------------- /src/plugins/mitt.config.js: -------------------------------------------------------------------------------- 1 | import mitt from 'mitt'; 2 | 3 | export default function initMitt(app) { 4 | app.config.globalProperties.$emitter = mitt(); 5 | } 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-pxtorem': { 4 | rootValue: 37.5, 5 | propList: ['*'] 6 | } 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /src/api/news.js: -------------------------------------------------------------------------------- 1 | import http from './http'; 2 | 3 | export const getNews = (params) => { 4 | return http({ 5 | url: '/api/news', 6 | method: 'GET', 7 | params 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /src/api/city.js: -------------------------------------------------------------------------------- 1 | import http from './http'; 2 | 3 | export const getCityList = (params) => { 4 | return http({ 5 | url: '/api/cityList', 6 | method: 'GET', 7 | params 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /src/api/options.js: -------------------------------------------------------------------------------- 1 | import http from './http'; 2 | 3 | export const getOptions = (params) => { 4 | return http({ 5 | url: '/api/options', 6 | method: 'GET', 7 | params 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'vuex'; 2 | 3 | export default createStore({ 4 | state: { 5 | city: '中国' 6 | }, 7 | mutations: { 8 | setCity(state, city) { 9 | state.city = city; 10 | } 11 | }, 12 | actions: {}, 13 | modules: {} 14 | }); 15 | -------------------------------------------------------------------------------- /src/compositions/MapRoomList.js: -------------------------------------------------------------------------------- 1 | import { ref, onMounted } from 'vue'; 2 | import { getAreaHouse } from '/@api/map'; 3 | 4 | export default function initMapRoomList() { 5 | const list = ref([]); 6 | 7 | onMounted(async () => { 8 | list.value = await getAreaHouse(); 9 | }); 10 | 11 | return { 12 | list 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /src/utils/unit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 为数字加万 3 | * 12000 -> 1.20 万 4 | * 9800 -> 0.98 万 5 | * @param {} number 6 | */ 7 | export default function (number) { 8 | number = parseFloat(number); 9 | if (typeof number !== 'number') return '0.00'; 10 | if (number < 1000) return number; 11 | return (number / 10000).toFixed(2) + '万'; 12 | } 13 | -------------------------------------------------------------------------------- /src/compositions/RecommendRoomList.js: -------------------------------------------------------------------------------- 1 | import { ref, onMounted } from 'vue'; 2 | import { getAreaRecommend } from '/@api/map'; 3 | 4 | export default function initRecommendRoomList(props) { 5 | const list = ref([]); 6 | 7 | onMounted(async () => { 8 | list.value = await getAreaRecommend({ 9 | id: props.houseId 10 | }); 11 | }); 12 | 13 | return { 14 | list 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | import router from './router'; 4 | import store from './store'; 5 | import initVant from './plugins/vant'; 6 | import initMitt from './plugins/mitt.config'; 7 | 8 | import './assets/css/style.css'; 9 | import './assets/icon/iconfont.css'; 10 | 11 | const app = createApp(App); 12 | app.use(router); 13 | app.use(store); 14 | initVant(app); 15 | initMitt(app); 16 | app.mount('#app'); 17 | -------------------------------------------------------------------------------- /src/api/house.js: -------------------------------------------------------------------------------- 1 | import http from './http'; 2 | 3 | export const getTabs = (params) => { 4 | return http({ 5 | url: '/api/tabs', 6 | method: 'GET', 7 | params 8 | }); 9 | }; 10 | 11 | export const getList = (params) => { 12 | return http({ 13 | url: '/api/list', 14 | method: 'GET', 15 | params 16 | }); 17 | }; 18 | 19 | export const getHouse = (params) => { 20 | return http({ 21 | url: '/api/getHouse', 22 | method: 'GET', 23 | params 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | vue-next-renting 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/api/map.js: -------------------------------------------------------------------------------- 1 | import http from './http'; 2 | 3 | export const getArea = (params) => { 4 | return http({ 5 | url: '/api/area', 6 | method: 'GET', 7 | params 8 | }); 9 | }; 10 | 11 | export const getAreaHouse = (params) => { 12 | return http({ 13 | url: '/api/area/house', 14 | method: 'GET', 15 | params 16 | }); 17 | }; 18 | 19 | export const getAreaRecommend = (params) => { 20 | return http({ 21 | url: '/api/area/recommend', 22 | method: 'GET', 23 | params 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /src/views/city_list/components/CityListNavBar.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | let path = require('path'); 2 | 3 | module.exports = { 4 | // alias a path to a fs directory 5 | // the key must start and end with a slash 6 | alias: { 7 | '/@src/': path.join(__dirname, './src'), 8 | '/@api/': path.join(__dirname, './src/api'), 9 | '/@assets/': path.join(__dirname, './src/assets'), 10 | '/@plugins/': path.join(__dirname, './src/plugins'), 11 | '/@views/': path.join(__dirname, './src/views'), 12 | '/@components/': path.join(__dirname, './src/components'), 13 | '/@utils/': path.join(__dirname, './src/utils'), 14 | '/@compositions/': path.join(__dirname, './src/compositions') 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /src/views/home/components/HomeOptionsItem.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | 20 | 35 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router'; 2 | import AppMain from '../views/AppMain.vue'; 3 | import CityList from '../views/city_list/Main.vue'; 4 | import HouseDetail from '../views/house_detail/Main.vue'; 5 | 6 | const routes = [ 7 | { 8 | path: '/', 9 | name: 'AppMain', 10 | component: AppMain 11 | }, 12 | { 13 | path: '/cityList', 14 | name: 'CityList', 15 | component: CityList 16 | }, 17 | { 18 | path: '/houseDetail', 19 | name: 'HouseDetail', 20 | component: HouseDetail 21 | } 22 | ]; 23 | 24 | const router = createRouter({ 25 | history: createWebHistory(process.env.BASE_URL), 26 | routes 27 | }); 28 | 29 | export default router; 30 | -------------------------------------------------------------------------------- /src/views/house_detail/components/HouseDetailSwiper.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | 23 | 33 | -------------------------------------------------------------------------------- /src/api/http.js: -------------------------------------------------------------------------------- 1 | // issues: https://github.com/axios/axios/issues/1879 2 | // 因为 vite 不支持 commonJS 导入,而 axios 并没有提供 ECMAScript(ESM) 版本,所以直接在 vite 中无法使用 axios 。 这里我们借助了一个 镜像库,来解决这个问题 3 | import { axios } from '@bundled-es-modules/axios'; 4 | import { Dialog } from 'vant'; 5 | 6 | const $http = axios.create({ 7 | baseURL: 'https://api.renting.lgdsunday.club/' 8 | }); 9 | 10 | $http.interceptors.response.use( 11 | function (response) { 12 | const data = response.data; 13 | // 处理错误信息 14 | if (data.status !== 200) { 15 | Dialog.alert({ 16 | message: data.description 17 | }); 18 | } 19 | return data.data; 20 | }, 21 | function (error) { 22 | return Promise.reject(error); 23 | } 24 | ); 25 | 26 | export default $http; 27 | -------------------------------------------------------------------------------- /src/views/home/components/HomeCard.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-next-renting", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build" 7 | }, 8 | "dependencies": { 9 | "@amap/amap-jsapi-loader": "^0.0.4", 10 | "@bundled-es-modules/axios": "^0.18.1", 11 | "amfe-flexible": "^2.2.1", 12 | "animejs": "^3.2.1", 13 | "dayjs": "^1.9.1", 14 | "lodash-es": "^4.17.15", 15 | "mitt": "^2.1.0", 16 | "swiper": "^6.3.3", 17 | "three": "^0.122.0", 18 | "vant": "^3.0.0-beta.8", 19 | "vue": "^3.0.2", 20 | "vue-router": "^4.0.0-rc.1", 21 | "vuex": "^4.0.0-rc.1" 22 | }, 23 | "devDependencies": { 24 | "@vue/compiler-sfc": "^3.0.2", 25 | "postcss-pxtorem": "^5.1.1", 26 | "sass": "^1.27.0", 27 | "vite": "^1.0.0-rc.4" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/views/city_list/Main.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | 23 | 38 | -------------------------------------------------------------------------------- /src/plugins/vant.js: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | Tabbar, 4 | TabbarItem, 5 | Swipe, 6 | SwipeItem, 7 | Image, 8 | Tabs, 9 | List, 10 | Tag, 11 | Divider, 12 | Tab, 13 | Popup, 14 | NavBar, 15 | IndexBar, 16 | IndexAnchor, 17 | Skeleton, 18 | Cell, 19 | Row, 20 | Col, 21 | Loading 22 | } from 'vant'; 23 | import 'vant/lib/index.css'; 24 | 25 | export default function initVant(app) { 26 | app.use(Button); 27 | app.use(Image); 28 | app.use(Tabbar); 29 | app.use(TabbarItem); 30 | app.use(Swipe); 31 | app.use(SwipeItem); 32 | app.use(Tabs); 33 | app.use(List); 34 | app.use(Divider); 35 | app.use(Tag); 36 | app.use(Tab); 37 | app.use(Popup); 38 | app.use(NavBar); 39 | app.use(IndexBar); 40 | app.use(IndexAnchor); 41 | app.use(Skeleton); 42 | app.use(Cell); 43 | app.use(Row); 44 | app.use(Col); 45 | app.use(Loading); 46 | } 47 | -------------------------------------------------------------------------------- /src/compositions/HomeRoomList.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue'; 2 | import { getList } from '/@api/house'; 3 | 4 | export default function initHomeRoomList(props) { 5 | const pageSize = ref(5); 6 | const pageNum = ref(1); 7 | const list = ref([]); 8 | const loading = ref(false); 9 | const finished = ref(false); 10 | 11 | const onLoad = async () => { 12 | // 加载数据 13 | const data = await getList({ 14 | name: props.name, 15 | pageSize: pageSize.value, 16 | pageNum: pageNum.value 17 | }); 18 | list.value.push(...data); 19 | // 加载状态结束 20 | loading.value = false; 21 | // 进入下一页 22 | pageNum.value++; 23 | // 数据全部加载完成 24 | if (data.length === 0) { 25 | finished.value = true; 26 | } 27 | }; 28 | 29 | return { 30 | list, 31 | loading, 32 | finished, 33 | pageSize, 34 | pageNum, 35 | onLoad 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /src/plugins/map.config.js: -------------------------------------------------------------------------------- 1 | import AMapLoader from '@amap/amap-jsapi-loader'; 2 | function init() { 3 | if (window.AMap) { 4 | return new Promise((resolve, reject) => resolve(window.AMap)); 5 | } 6 | return AMapLoader.load({ 7 | // 申请好的Web端开发者Key,首次调用 load 时必填 8 | key: '1140bde0f083c320481282c74832afb0', 9 | // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 10 | version: '2.0', 11 | // 需要使用的的插件列表,如比例尺'AMap.Scale'等 12 | plugins: [ 13 | 'AMap.CitySearch', 14 | 'AMap.CircleMarker', 15 | 'AMap.Driving', 16 | 'AMap.Geolocation', 17 | 'AMap.ToolBar' 18 | ] 19 | // Loca: { 20 | // // 是否加载 Loca, 缺省不加载 21 | // version: '1.3.2' // Loca 版本,缺省 1.3.2 22 | // } 23 | }) 24 | .then((AMap) => { 25 | window.AMap = AMap; 26 | return AMap; 27 | }) 28 | .catch((err) => { 29 | return err; 30 | }); 31 | } 32 | 33 | export default init; 34 | -------------------------------------------------------------------------------- /src/views/house_detail/components/HouseDetailNavBar.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | 29 | 44 | -------------------------------------------------------------------------------- /src/compositions/HouseDetailMap.js: -------------------------------------------------------------------------------- 1 | import { getAMap, getLocation } from '/@utils/map.js'; 2 | 3 | export function initDriving(el, toLnglat, onMapClick) { 4 | return new Promise(async (resolve, reject) => { 5 | const location = await getLocation(); 6 | const AMap = await getAMap(); 7 | //基本地图加载 8 | const map = new AMap.Map(el, { 9 | resizeEnable: true, 10 | center: [location.position.lng, location.position.lat] //地图中心点 11 | }); 12 | // 构造路线导航类; 13 | var driving = new AMap.Driving({ 14 | policy: AMap.DrivingPolicy.LEAST_TIME, 15 | map: map 16 | }); 17 | // 根据起终点名称规划驾车导航路线 18 | driving.search([location.position.lng, location.position.lat], toLnglat, (status, result) => { 19 | resolve({ 20 | driving, 21 | fromLnglat: [location.position.lng, location.position.lat], 22 | searchResult: result 23 | }); 24 | }); 25 | map.addControl(new AMap.ToolBar()); 26 | map.on('click', onMapClick); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /src/views/home/components/HomeTabs.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 LGD_Sunday 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/views/house_detail/components/HouseDetailMap.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 31 | 32 | 48 | -------------------------------------------------------------------------------- /src/views/AppMain.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 44 | 45 | 55 | -------------------------------------------------------------------------------- /src/views/house_detail/components/HouseDetailDesc.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 26 | 27 | 55 | -------------------------------------------------------------------------------- /src/utils/map.js: -------------------------------------------------------------------------------- 1 | import init from '/@plugins/map.config.js'; 2 | import { ref } from 'vue'; 3 | 4 | async function getLocalCity() { 5 | let AMap = window.AMap; 6 | if (!AMap) { 7 | AMap = await init(); 8 | } 9 | const citySearch = new AMap.CitySearch(); 10 | return new Promise((resolve, reject) => { 11 | citySearch.getLocalCity((status, result) => { 12 | if (status === 'complete' && result.info === 'OK') { 13 | // 查询成功,result即为当前所在城市信息 14 | resolve(result.city); 15 | } 16 | }); 17 | }); 18 | } 19 | 20 | async function getGeoLocation() { 21 | let AMap = window.AMap; 22 | if (!AMap) { 23 | AMap = await init(); 24 | } 25 | const geolocation = new AMap.Geolocation({ 26 | timeout: 10 * 1000, 27 | maximumAge: 24 * 3600 * 1000 28 | }); 29 | 30 | return new Promise((resolve, reject) => { 31 | geolocation.getCurrentPosition((status, result) => { 32 | if (status == 'complete') { 33 | resolve(result); 34 | } else { 35 | reject(result); 36 | } 37 | }); 38 | }); 39 | } 40 | 41 | export function getAMap() { 42 | return init(); 43 | } 44 | 45 | export function getCity() { 46 | const city = ref('中国'); 47 | const getCity = async () => { 48 | city.value = (await getLocalCity()).replace('市', ''); 49 | }; 50 | getCity(); 51 | return city; 52 | } 53 | 54 | export async function getLocation() { 55 | return await getGeoLocation(); 56 | } 57 | -------------------------------------------------------------------------------- /src/components/RoomList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 58 | 59 | 64 | -------------------------------------------------------------------------------- /src/views/home/components/HomeNews.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 37 | 38 | 69 | -------------------------------------------------------------------------------- /src/views/home/components/HomeOptions.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 48 | 49 | 67 | -------------------------------------------------------------------------------- /src/components/NewsSwiper.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 63 | 64 | 77 | -------------------------------------------------------------------------------- /docs/代码更新与视频发布计划.md: -------------------------------------------------------------------------------- 1 | # 代码更新与视频发布计划 2 | 3 | ## 代码更新 4 | 5 | ### v1.0.0 6 | 7 | v 1.0 版本代码于 2020-11-30 日更新完成 8 | 9 | ## 视频发布 10 | 11 | ### 发布地址:B 站 12 | 13 | ### 课程大纲 14 | 15 | - 内容概述 16 | - vite + vue3 开发企业级移动端应用 17 | - 课程适合人群 18 | - 0 - 3 年开发经验的前端开发者 19 | - 想要了解 vue3 原理和 组合式 API 的同学 20 | - 希望扩展前端知识面,让技术更进一层的同学 21 | - 技术储备要求 22 | - 熟悉 JS 基础语法 23 | - 了解 Vue 2.x 基础语法 24 | - 了解 NPM 开发环境 25 | 26 | ### 章节规划(持续更新中...) 27 | 28 | - 番外(课程之外的一些说明视频,不在预计之内的视频内容) 29 | - 主章(课程主要章节) 30 | - 第一章:课程简介 31 | - 1-1:[简介](https://www.bilibili.com/video/BV1vi4y157p4?p=1) 32 | - 1-2:[项目演示](https://www.bilibili.com/video/BV1vi4y157p4?p=2) 33 | - 1-3:[课程设计与你的收获](https://www.bilibili.com/video/BV1vi4y157p4?p=3) 34 | - - 第二章:Vue 3 新特性 与 vite 讲解 35 | - 2-1:[为什么要使用 Composition(组合式) API](https://www.bilibili.com/video/BV1vi4y157p4?p=5) 36 | - 2-2:[入口函数 - setup](https://www.bilibili.com/video/BV1vi4y157p4?p=6) 37 | - 2-3:[新的响应式机制-proxy](https://www.bilibili.com/video/BV1vi4y157p4?p=7) 38 | - 2-4:[proxy 实现简单的响应式数据渲染](https://www.bilibili.com/video/BV1vi4y157p4?p=8) 39 | - 2-5:[使用 ref 创建响应式变量](https://www.bilibili.com/video/BV1vi4y157p4?p=9) 40 | - 2-6:[reactive 配合 toRefs 解析响应式](https://www.bilibili.com/video/BV1vi4y157p4?p=10) 41 | - 2-7:[setup 函数中的 生命周期钩子](https://www.bilibili.com/video/BV1vi4y157p4?p=11) 42 | - 2-8:[composition API 之 watch、watchEffect 、 computed - 01](https://www.bilibili.com/video/BV1vi4y157p4?p=12) 43 | - 2-9:[composition API 之 watch、watchEffect 、 computed - 02](https://www.bilibili.com/video/BV1vi4y157p4?p=13) 44 | - 2-10:setup 函数中的 Provide / Inject 45 | - 2-11:有意思的瞬间移动 - Teleport 46 | - 2-12:章节总结 47 | - 第三章:万事开头难 - 构建项目与首页开发 48 | - 第四章:高品质交互体验 - 构建进入二楼组件 49 | - 第五章:让路由跳转不再生硬 - 城市列表与虚拟任务栈 50 | - 第六章:地图来了 - 高德地图在 vue3 中的实现 51 | - 第七章:沉浸式体验 - threejs 实现 3D 全景看房 52 | - 第八章:不会部署不用怕 - 从买服务器到部署上线全流程 53 | - 第九章:项目总结 54 | -------------------------------------------------------------------------------- /src/components/RoomItem.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 60 | 61 | 98 | -------------------------------------------------------------------------------- /src/assets/css/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | width: 100%; 4 | height: 100%; 5 | overflow: hidden; 6 | /* 图片之间默认间距 */ 7 | font-size: 0; 8 | /* 不允许去选中文本 */ 9 | user-select: none; 10 | /* IOS 下的滑动卡顿问题 */ 11 | -webkit-overflow-scrolling: touch; 12 | /* IOS 下点击取消默认高亮效果 */ 13 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 14 | } 15 | html, 16 | body, 17 | div, 18 | span, 19 | applet, 20 | object, 21 | iframe, 22 | h1, 23 | h2, 24 | h3, 25 | h4, 26 | h5, 27 | h6, 28 | p, 29 | blockquote, 30 | pre, 31 | a, 32 | abbr, 33 | acronym, 34 | address, 35 | big, 36 | cite, 37 | code, 38 | del, 39 | dfn, 40 | em, 41 | img, 42 | ins, 43 | kbd, 44 | q, 45 | s, 46 | samp, 47 | small, 48 | strike, 49 | strong, 50 | sub, 51 | sup, 52 | tt, 53 | var, 54 | b, 55 | u, 56 | i, 57 | center, 58 | dl, 59 | dt, 60 | dd, 61 | ol, 62 | ul, 63 | li, 64 | fieldset, 65 | form, 66 | label, 67 | legend, 68 | table, 69 | caption, 70 | tbody, 71 | tfoot, 72 | thead, 73 | tr, 74 | th, 75 | td, 76 | article, 77 | aside, 78 | canvas, 79 | details, 80 | embed, 81 | figure, 82 | figcaption, 83 | footer, 84 | header, 85 | hgroup, 86 | menu, 87 | nav, 88 | output, 89 | ruby, 90 | section, 91 | summary, 92 | time, 93 | mark, 94 | audio, 95 | video { 96 | margin: 0; 97 | padding: 0; 98 | border: 0; 99 | font-size: 100%; 100 | font: inherit; 101 | vertical-align: baseline; 102 | } 103 | 104 | article, 105 | aside, 106 | details, 107 | figcaption, 108 | figure, 109 | footer, 110 | header, 111 | hgroup, 112 | menu, 113 | nav, 114 | section { 115 | display: block; 116 | } 117 | body { 118 | line-height: 1; 119 | } 120 | ol, 121 | ul { 122 | list-style: none; 123 | } 124 | blockquote, 125 | q { 126 | quotes: none; 127 | } 128 | blockquote:before, 129 | blockquote:after, 130 | q:before, 131 | q:after { 132 | content: ''; 133 | content: none; 134 | } 135 | table { 136 | border-collapse: collapse; 137 | border-spacing: 0; 138 | } 139 | 140 | .single-line { 141 | overflow: hidden; 142 | /*文本不会换行*/ 143 | white-space: nowrap; 144 | /*当文本溢出包含元素时,以省略号表示超出的文本*/ 145 | text-overflow: ellipsis; 146 | } 147 | 148 | /* 背景色 */ 149 | #app { 150 | background-color: #f4f4f4; 151 | } 152 | 153 | /* tabbar 选中色 */ 154 | .van-tabbar-item--active { 155 | color: #26ce97; 156 | } 157 | 158 | /* 分割线样式 */ 159 | .van-divider.van-divider--hairline { 160 | margin: 0 !important; 161 | } 162 | -------------------------------------------------------------------------------- /src/assets/icon/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2113337", 3 | "name": "imooc-renting", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon", 6 | "description": "慕课租房", 7 | "glyphs": [ 8 | { 9 | "icon_id": "2076391", 10 | "name": " 360度全景", 11 | "font_class": "duquanjing", 12 | "unicode": "e8c3", 13 | "unicode_decimal": 59587 14 | }, 15 | { 16 | "icon_id": "4192838", 17 | "name": "全景360", 18 | "font_class": "quanjing", 19 | "unicode": "e61f", 20 | "unicode_decimal": 58911 21 | }, 22 | { 23 | "icon_id": "4236624", 24 | "name": "全屏", 25 | "font_class": "quanping", 26 | "unicode": "e607", 27 | "unicode_decimal": 58887 28 | }, 29 | { 30 | "icon_id": "14166830", 31 | "name": "缩小", 32 | "font_class": "suoxiao", 33 | "unicode": "e639", 34 | "unicode_decimal": 58937 35 | }, 36 | { 37 | "icon_id": "1183130", 38 | "name": "定位", 39 | "font_class": "location", 40 | "unicode": "e675", 41 | "unicode_decimal": 58997 42 | }, 43 | { 44 | "icon_id": "690679", 45 | "name": "YDUI-二维码扫描", 46 | "font_class": "yduierweimasaomiao", 47 | "unicode": "e606", 48 | "unicode_decimal": 58886 49 | }, 50 | { 51 | "icon_id": "1788970", 52 | "name": "搜索", 53 | "font_class": "sousuo", 54 | "unicode": "e6a6", 55 | "unicode_decimal": 59046 56 | }, 57 | { 58 | "icon_id": "4867075", 59 | "name": "后退", 60 | "font_class": "back", 61 | "unicode": "e64f", 62 | "unicode_decimal": 58959 63 | }, 64 | { 65 | "icon_id": "17890084", 66 | "name": "后退", 67 | "font_class": "down", 68 | "unicode": "e779", 69 | "unicode_decimal": 59257 70 | }, 71 | { 72 | "icon_id": "1110412", 73 | "name": "箭头", 74 | "font_class": "jiantou", 75 | "unicode": "e60c", 76 | "unicode_decimal": 58892 77 | }, 78 | { 79 | "icon_id": "6999501", 80 | "name": "箭头", 81 | "font_class": "tuya_huabanfuben", 82 | "unicode": "e75d", 83 | "unicode_decimal": 59229 84 | }, 85 | { 86 | "icon_id": "1132478", 87 | "name": "推荐", 88 | "font_class": "tuijian", 89 | "unicode": "e63b", 90 | "unicode_decimal": 58939 91 | }, 92 | { 93 | "icon_id": "9809642", 94 | "name": "首页", 95 | "font_class": "shouye", 96 | "unicode": "e659", 97 | "unicode_decimal": 58969 98 | }, 99 | { 100 | "icon_id": "11521313", 101 | "name": "地图", 102 | "font_class": "ditu", 103 | "unicode": "e778", 104 | "unicode_decimal": 59256 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-next-renting 2 | 3 | ## 简介 4 | 5 | `vue-next-renting` 是一个基于 `vite + vue3` 构建的移动端[视频课程项目](#jump)。 6 | 7 | 我们可以通过下面的 `gif` 图片来对 `vue-next-renting` 有一个更深的了解([图片未打开?](http://res.lgdsunday.club/renting-overview.gif))。 8 | 9 | renting-overview 10 | 11 | ## 项目将遵循的 git 规范 12 | 13 | ### 分支 14 | 15 | - master:主分支。用于项目阶段部署发布。 16 | - dev:开发分支。始终保持最新完成以及 bug 修复后的代码。 17 | - feature:新功能分支。用于新功能开发,以 dev 为基础创建。 18 | - release:预上线分支。发布提测阶段。 19 | 20 | ### 提交 21 | 22 | - 提交规范:key: value。比如:新增 首页 -> feat: home / 首页 23 | - key 可选: 24 | 25 | ``` 26 | feat:新功能(feature) 27 | fix:修补bug 28 | docs:文档(documentation) 29 | style: 格式(不影响代码运行的变动) 30 | refactor:重构(即不是新增功能,也不是修改bug的代码变动) 31 | test:增加测试 32 | chore:构建过程或辅助工具的变动 33 | release: 发布 34 | ``` 35 | 36 | ### 进度 37 | 38 | v 1.0.0 版本代码已全部提交完成 39 | 40 | ## 章节规划(持续更新中...) 41 | 42 | - 番外(课程之外的一些说明视频,不在预计之内的视频内容) 43 | - [代码托管与提问方式](https://www.bilibili.com/video/BV1vi4y157p4?p=4) 44 | - 主章(课程主要章节) 45 | - 第一章:课程简介 46 | - 1-1:[简介](https://www.bilibili.com/video/BV1vi4y157p4?p=1) 47 | - 1-2:[项目演示](https://www.bilibili.com/video/BV1vi4y157p4?p=2) 48 | - 1-3:[课程设计与你的收获](https://www.bilibili.com/video/BV1vi4y157p4?p=3) 49 | - - 第二章:Vue 3 新特性 与 vite 讲解 50 | - 2-1:[为什么要使用 Composition(组合式) API](https://www.bilibili.com/video/BV1vi4y157p4?p=5) 51 | - 2-2:[入口函数 - setup](https://www.bilibili.com/video/BV1vi4y157p4?p=6) 52 | - 2-3:[新的响应式机制-proxy](https://www.bilibili.com/video/BV1vi4y157p4?p=7) 53 | - 2-4:[proxy 实现简单的响应式数据渲染](https://www.bilibili.com/video/BV1vi4y157p4?p=8) 54 | - 2-5:[使用 ref 创建响应式变量](https://www.bilibili.com/video/BV1vi4y157p4?p=9) 55 | - 2-6:[reactive 配合 toRefs 解析响应式](https://www.bilibili.com/video/BV1vi4y157p4?p=10) 56 | - 2-7:[setup 函数中的 生命周期钩子](https://www.bilibili.com/video/BV1vi4y157p4?p=11) 57 | - 2-8:[composition API 之 watch、watchEffect 、 computed - 01](https://www.bilibili.com/video/BV1vi4y157p4?p=12) 58 | - 2-9:[composition API 之 watch、watchEffect 、 computed - 02](https://www.bilibili.com/video/BV1vi4y157p4?p=13) 59 | - 2-10:setup 函数中的 Provide / Inject 60 | - 2-11:有意思的瞬间移动 - Teleport 61 | - 2-12:章节总结 62 | - 第三章:万事开头难 - 构建项目与首页开发 63 | - 第四章:高品质交互体验 - 构建进入二楼组件 64 | - 第五章:让路由跳转不再生硬 - 城市列表与虚拟任务栈 65 | - 第六章:地图来了 - 高德地图在 vue3 中的实现 66 | - 第七章:沉浸式体验 - threejs 实现 3D 全景看房 67 | - 第八章:不会部署不用怕 - 从买服务器到部署上线全流程 68 | - 第九章:项目总结 69 | 70 | 所有的课程视频将 **免费** 发布到 **b 站**。 71 | 72 | 欢迎大家 `star` ,后续该项目的所有代码将会被 `push`到该仓库中,关于课程内容与问题讨论亦会在本仓库中进行。 73 | 74 | [点击跳转查看后续计划](https://github.com/lgd8981289/vue-next-renting/blob/master/docs/%E4%BB%A3%E7%A0%81%E6%9B%B4%E6%96%B0%E4%B8%8E%E8%A7%86%E9%A2%91%E5%8F%91%E5%B8%83%E8%AE%A1%E5%88%92.md) 75 | 76 | ## 涉及到的技术点 77 | 78 | 包括但不仅限于以下技术: 79 | 80 | - vite(构建工具) 81 | - vue-next(vue3) 82 | - vant-ui(UI 库) 83 | - 高德地图 API(地图相关) 84 | - 虚拟任务栈(介绍:https://juejin.cn/post/6844904199528923143) 85 | - threejs(3D 全景) 86 | - animejs(动画实现) 87 | - 复杂的自定义组件 88 | - ... 89 | 90 |

什么叫视频课程项目?

91 | 以录制视频的形式,来讲解 **整个项目中所涉及到的所有技术点**,以及 **项目的实现思路、代码、方案等** 。 92 | 93 | 也可以理解为:**手把手教你完成这个项目的开发** 94 | 95 | ## 接口文档 96 | 97 | [点击跳转接口文档地址](https://github.com/lgd8981289/vue-next-renting/blob/master/docs/%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3.md) 98 | 99 | ## 声明 100 | 101 | 为避免纠纷,项目中所涉及到的所有资源均为网络公开资源,如有侵权请联系作者 102 | 103 | lgd_sunday@163.com 104 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 58 | 59 | 129 | -------------------------------------------------------------------------------- /src/views/home/Main.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 115 | 116 | 136 | -------------------------------------------------------------------------------- /src/views/house_detail/Main.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 88 | 89 | 121 | -------------------------------------------------------------------------------- /src/views/city_list/components/IndexBar.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 99 | 100 | 140 | -------------------------------------------------------------------------------- /src/views/house_detail/components/HouseDetailPanorama.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 108 | 109 | 162 | -------------------------------------------------------------------------------- /src/compositions/Panorama.js: -------------------------------------------------------------------------------- 1 | import { 2 | Scene, 3 | PerspectiveCamera, 4 | WebGLRenderer, 5 | TextureLoader, 6 | SphereGeometry, 7 | MeshBasicMaterial, 8 | Mesh, 9 | Vector3, 10 | BackSide, 11 | MathUtils 12 | } from 'three'; 13 | 14 | // 配置对象 15 | let opt = { 16 | // 展示元素 17 | el: null, 18 | // 展示宽度 19 | width: 0, 20 | // 展示高度 21 | height: 0, 22 | // 展示资源 23 | src: '', 24 | // 球体半径 25 | radius: 1000, 26 | // 球体水平分段数(沿着经线分段) 27 | widthSegments: 88, 28 | // 球体垂直分段数(沿着纬线分段) 29 | heightSegments: 88, 30 | // 是否自动动画 31 | isAutoAnim: true, 32 | // 加载完成的回调 33 | complete: null, 34 | // 是否横向展示 35 | isHorizontal: false 36 | }; 37 | // 自动动画对象 38 | let autoInterval = null; 39 | // 动画执行序列 40 | let requestAnimationHandler; 41 | // 获取 DOM 元素 42 | let element; 43 | // 定义 场景,相机,渲染器变量,三维点 44 | let scene, camera, renderer, vector3; 45 | // 标记用户拖动 46 | let isUserInteracting = false; 47 | // 标记用户按下的点 48 | let onPointerDownPointerX = 0, 49 | onPointerDownPointerY = 0; 50 | // 标记当用户按下时,当前全景的经纬度 51 | let onPointerDownLon = 0, 52 | onPointerDownLat = 0; 53 | // 标记用户拖动时,当前全景的经纬度 54 | let onPointerMoveLon = 0, 55 | onPointerMoveLat = 0; 56 | 57 | /** 58 | * 初始化函数 59 | */ 60 | function init() { 61 | initElement(); 62 | initScene(); 63 | initCamera(); 64 | loadPanorama(); 65 | initRenderer(); 66 | } 67 | 68 | /** 69 | * 初始化 dom 元素,并获取宽高 70 | */ 71 | function initElement() { 72 | element = opt.el; 73 | element.innerHTML = ''; 74 | opt.height = element.clientHeight; 75 | opt.width = element.clientWidth; 76 | element.addEventListener('touchstart', onTouchStart, false); 77 | element.addEventListener('touchmove', onTouchMove, false); 78 | element.addEventListener('touchend', onTouchEnd, false); 79 | } 80 | 81 | /** 82 | * 初始化场景 83 | */ 84 | function initScene() { 85 | // 定义一个场景 86 | scene = new Scene(); 87 | } 88 | /** 89 | * 初始化相机 90 | */ 91 | function initCamera() { 92 | // 定义透视相机 93 | camera = new PerspectiveCamera(50, opt.width / opt.height); 94 | // 设置观测点 95 | camera.position.set(0, 0, 0); 96 | vector3 = new Vector3(0, 0, 0); 97 | } 98 | 99 | /** 100 | * 设置全景图片 101 | */ 102 | function loadPanorama() { 103 | // 资源(图片)加载类 104 | let loader = new TextureLoader(); 105 | // 加载图片 106 | loader.load( 107 | opt.src, 108 | // onLoad 109 | (texture) => { 110 | // 构建物体 111 | var mesh = new Mesh( 112 | // 将全景图构建为球体 113 | new SphereGeometry(opt.radius, opt.widthSegments, opt.heightSegments), 114 | // 构建材质 115 | new MeshBasicMaterial({ map: texture, side: BackSide }) 116 | ); 117 | // 将构建出的物体添加到场景中 118 | scene.add(mesh); 119 | opt.complete(); 120 | } 121 | ); 122 | } 123 | 124 | /** 125 | * 初始化渲染器 126 | */ 127 | function initRenderer() { 128 | // 定义场景渲染器 129 | renderer = new WebGLRenderer(); 130 | // 设置大小 131 | renderer.setSize(opt.width, opt.height); 132 | // 渲染到指定容器中 133 | element.appendChild(renderer.domElement); 134 | } 135 | 136 | /** 137 | * 循环场景渲染 138 | */ 139 | function animate() { 140 | requestAnimationHandler = requestAnimationFrame(animate); 141 | computePosition(); 142 | renderer.render(scene, camera); 143 | } 144 | 145 | function autoAnim() { 146 | if (autoInterval) { 147 | clearInterval(autoInterval); 148 | } 149 | autoInterval = setInterval(() => { 150 | onPointerMoveLon += 0.07; 151 | }); 152 | } 153 | 154 | /** 155 | * 计算摄像的视角 156 | */ 157 | function computePosition() { 158 | onPointerMoveLat = Math.max(-85, Math.min(85, onPointerMoveLat)); 159 | var phi = MathUtils.degToRad(90 - onPointerMoveLat); 160 | var theta = MathUtils.degToRad(onPointerMoveLon); 161 | vector3.x = opt.radius * Math.sin(phi) * Math.cos(theta); 162 | vector3.y = opt.radius * Math.cos(phi); 163 | vector3.z = opt.radius * Math.sin(phi) * Math.sin(theta); 164 | camera.lookAt(vector3); 165 | } 166 | 167 | /** 168 | * 工具函数,合并对象 169 | */ 170 | function extend(o, n, override) { 171 | for (var key in n) { 172 | if (n.hasOwnProperty(key) && (!o.hasOwnProperty(key) || override)) { 173 | o[key] = n[key]; 174 | } 175 | } 176 | return o; 177 | } 178 | 179 | /** 180 | * 事件函数 181 | */ 182 | function onTouchStart(event) { 183 | const touch = event.changedTouches[0]; 184 | event.preventDefault(); 185 | isUserInteracting = true; 186 | onPointerDownPointerX = touch.clientX; 187 | onPointerDownPointerY = touch.clientY; 188 | onPointerDownLon = onPointerMoveLon; 189 | onPointerDownLat = onPointerMoveLat; 190 | } 191 | 192 | function onTouchMove(event) { 193 | // 用户拖动则停止动画 194 | if (autoInterval) { 195 | clearInterval(autoInterval); 196 | } 197 | const touch = event.changedTouches[0]; 198 | if (isUserInteracting) { 199 | // 横向操作判断 200 | if (opt.isHorizontal) { 201 | onPointerMoveLon = (onPointerDownPointerY - touch.clientY) * 0.2 + onPointerDownLon; 202 | onPointerMoveLat = (onPointerDownPointerX - touch.clientX) * 0.2 + onPointerDownLat; 203 | } else { 204 | onPointerMoveLon = (onPointerDownPointerX - touch.clientX) * 0.2 + onPointerDownLon; 205 | onPointerMoveLat = (touch.clientY - onPointerDownPointerY) * 0.2 + onPointerDownLat; 206 | } 207 | } 208 | } 209 | 210 | function onTouchEnd() { 211 | isUserInteracting = false; 212 | } 213 | 214 | export function renderPanorama(options) { 215 | opt = extend(opt, options, true); 216 | if (!opt.el) return; 217 | init(); 218 | animate(); 219 | if (opt.isAutoAnim) { 220 | autoAnim(); 221 | } 222 | } 223 | 224 | export function onDestory() { 225 | cancelAnimationFrame(requestAnimationHandler); 226 | element.innerHTML = ''; 227 | renderer.dispose(); 228 | // scene = camera = renderer = vector3 = null; 229 | } 230 | -------------------------------------------------------------------------------- /src/views/map/Main.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 203 | 204 | 220 | -------------------------------------------------------------------------------- /src/views/home/components/HomeNavBar.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 179 | 180 | 239 | -------------------------------------------------------------------------------- /src/components/FloorScroll.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 244 | 245 | 281 | -------------------------------------------------------------------------------- /src/assets/icon/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src: url('iconfont.eot?t=1606131097699'); /* IE9 */ 3 | src: url('iconfont.eot?t=1606131097699#iefix') format('embedded-opentype'), /* IE6-IE8 */ 4 | url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), 5 | url('iconfont.woff?t=1606131097699') format('woff'), 6 | url('iconfont.ttf?t=1606131097699') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url('iconfont.svg?t=1606131097699#iconfont') format('svg'); /* iOS 4.1- */ 8 | } 9 | 10 | .iconfont { 11 | font-family: "iconfont" !important; 12 | font-size: 16px; 13 | font-style: normal; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | } 17 | 18 | .iconduquanjing:before { 19 | content: "\e8c3"; 20 | } 21 | 22 | .iconquanjing:before { 23 | content: "\e61f"; 24 | } 25 | 26 | .iconquanping:before { 27 | content: "\e607"; 28 | } 29 | 30 | .iconsuoxiao:before { 31 | content: "\e639"; 32 | } 33 | 34 | .iconlocation:before { 35 | content: "\e675"; 36 | } 37 | 38 | .iconyduierweimasaomiao:before { 39 | content: "\e606"; 40 | } 41 | 42 | .iconsousuo:before { 43 | content: "\e6a6"; 44 | } 45 | 46 | .iconback:before { 47 | content: "\e64f"; 48 | } 49 | 50 | .icondown:before { 51 | content: "\e779"; 52 | } 53 | 54 | .iconjiantou:before { 55 | content: "\e60c"; 56 | } 57 | 58 | .icontuya_huabanfuben:before { 59 | content: "\e75d"; 60 | } 61 | 62 | .icontuijian:before { 63 | content: "\e63b"; 64 | } 65 | 66 | .iconshouye:before { 67 | content: "\e659"; 68 | } 69 | 70 | .iconditu:before { 71 | content: "\e778"; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /docs/接口文档.md: -------------------------------------------------------------------------------- 1 | # vue-next-renting 接口文档 2 | 3 | ## 1. API V1 接口说明 4 | 5 | - 基准 URL 地址:`https://api.renting.lgdsunday.club/api/` 6 | - 服务端已开启 CORS 跨域支持 7 | - 数据返回格式统一使用 JSON 8 | - 数据为网络公开资源 9 | 10 | ## 2.接口列表 11 | 12 | ### 2.1 获取功能选项列表 13 | 14 | - 请求路径:`options` 15 | - 请求方法:`get` 16 | - 请求参数:无 17 | - 响应参数 18 | 19 | | 参数名 | 参数说明 | 数据类型 | 20 | | :---------- | ------------ | -------- | 21 | | status | 响应状态 | Number | 22 | | description | 响应描述信息 | String | 23 | | data | 响应数据体 | Array | 24 | 25 | - 响应数据 26 | 27 | ```json 28 | { 29 | "status": 200, 30 | "description": "请求成功", 31 | "data": [{ 32 | "name": "新房", 33 | "icon": "https://res.lgdsunday.club/renting_xin_fang.png" 34 | }, 35 | ... 36 | ] 37 | } 38 | ``` 39 | 40 | ## 41 | 42 | ### 2.2 获取新闻列表 43 | 44 | - 请求路径:`news` 45 | - 请求方法:`get` 46 | - 请求参数:无 47 | - 响应参数 48 | 49 | | 参数名 | 参数说明 | 数据类型 | 50 | | :---------- | ------------ | -------- | 51 | | status | 响应状态 | Number | 52 | | description | 响应描述信息 | String | 53 | | data | 响应数据体 | Array | 54 | 55 | - 响应数据 56 | 57 | ```json 58 | { 59 | "status": 200, 60 | "description": "请求成功", 61 | "data": [{ 62 | "title": "无论经济如何发展,世界怎样改变, 资产配置始终是高净值人群重点关注的问题。" 63 | }, ... 64 | ] 65 | } 66 | ``` 67 | 68 | ## 69 | 70 | ### 2.3 获取房产分类列表 71 | 72 | - 请求路径:`tabs` 73 | - 请求方法:`get` 74 | - 请求参数:无 75 | - 响应参数 76 | 77 | | 参数名 | 参数说明 | 数据类型 | 78 | | :---------- | ------------ | -------- | 79 | | status | 响应状态 | Number | 80 | | description | 响应描述信息 | String | 81 | | data | 响应数据体 | Array | 82 | 83 | - 响应数据 84 | 85 | ```json 86 | { 87 | "status": 200, 88 | "description": "请求成功", 89 | "data": ["全部", "项目在建", "活动优惠", "VR看房", "专车看房", "大户型", "配套纯属", "医院", "VR看盘", "人气楼盘", "低单价", "新开盘", "特价房源", "一房一价", "独栋别墅", "项目封顶", "大型社区", "热评楼盘", "装修交付", "银行", "车位充足", "全朝南", "低容积", "高绿化率", "南北通透", "轨交房", "花园洋房", "高性价比", "热搜盘"] 90 | } 91 | ``` 92 | 93 | ### 2.4 获取城市列表 94 | 95 | - 请求路径:`cityList` 96 | - 请求方法:`get` 97 | - 请求参数:无 98 | - 响应参数 99 | 100 | | 参数名 | 参数说明 | 数据类型 | 101 | | :---------- | ------------ | -------- | 102 | | status | 响应状态 | Number | 103 | | description | 响应描述信息 | String | 104 | | data | 响应数据体 | Array | 105 | 106 | - 响应数据 107 | 108 | ```json 109 | { 110 | "status": 200, 111 | "description": "请求成功", 112 | "data": { 113 | "recommendList": [{ 114 | "code": "010", 115 | "name": "北京", 116 | "pinyin": "Beijing", 117 | "label": "Beijing010" 118 | }, { 119 | "code": "021", 120 | "name": "上海", 121 | "pinyin": "Shanghai", 122 | "label": "Shanghai021" 123 | }], 124 | "cityList": [{ 125 | "initial": "A", 126 | "list": [{ 127 | "code": "0997", 128 | "name": "阿克苏", 129 | "pinyin": "Akesu", 130 | "label": "Akesu0997" 131 | }] 132 | }] 133 | }] 134 | } 135 | ``` 136 | 137 | ### 2.5 根据房产ID获取房产详情 138 | 139 | - 请求路径:`getHouse` 140 | 141 | - 请求方法:`get` 142 | 143 | - 请求参数: 144 | 145 | | 参数名 | 参数说明 | 数据类型 | 146 | | :------ | -------- | -------- | 147 | | houseId | 房产 ID | String | 148 | 149 | - 响应参数 150 | 151 | | 参数名 | 参数说明 | 数据类型 | 152 | | :---------- | ------------ | -------- | 153 | | status | 响应状态 | Number | 154 | | description | 响应描述信息 | String | 155 | | data | 响应数据体 | Array | 156 | 157 | - 响应数据 158 | 159 | ```json 160 | { 161 | "status": 200, 162 | "description": "请求成功", 163 | "data": { 164 | "id": "0", 165 | "name": "福满街系华瀚品牌馆", 166 | "maps": ["朝阳", "东坝"], 167 | "address": "东坝南二街和管庄路交汇处", 168 | "price": "67730", 169 | "minArea": "82", 170 | "maxArea": "186", 171 | "tags": ["项目在建", "活动优惠", "VR看房", "专车看房"], 172 | "icon": "https://res.lgdsunday.club/renting_sale_3.jpg", 173 | "panoramaImg": "https://res.lgdsunday.club/renting_panorama_2.jpg", 174 | "imags": ["https://res.lgdsunday.club/renting_sale_3.jpg", "https://res.lgdsunday.club/renting_sale_5.jpg", "https://res.lgdsunday.club/renting_sale_7.jpg", "https://res.lgdsunday.club/renting_sale_1.jpg", "https://res.lgdsunday.club/renting_sale_2.jpg"], 175 | "lng": "116.58161989806", 176 | "lat": "39.964750858521" 177 | } 178 | } 179 | ``` 180 | 181 | 182 | 183 | ### 2.6 根据房产ID获取推荐房产列表 184 | 185 | - 请求路径:`area/recommend` 186 | 187 | - 请求方法:`get` 188 | 189 | - 请求参数: 190 | 191 | | 参数名 | 参数说明 | 数据类型 | 192 | | :----- | -------- | -------- | 193 | | id | 房产 ID | String | 194 | 195 | - 响应参数 196 | 197 | | 参数名 | 参数说明 | 数据类型 | 198 | | :---------- | ------------ | -------- | 199 | | status | 响应状态 | Number | 200 | | description | 响应描述信息 | String | 201 | | data | 响应数据体 | Array | 202 | 203 | - 响应数据 204 | 205 | ```json 206 | { 207 | "status": 200, 208 | "description": "请求成功", 209 | "data": { 210 | "id": "0", 211 | "name": "福满街系华瀚品牌馆", 212 | "maps": ["朝阳", "东坝"], 213 | "address": "东坝南二街和管庄路交汇处", 214 | "price": "67730", 215 | "minArea": "82", 216 | "maxArea": "186", 217 | "tags": ["项目在建", "活动优惠", "VR看房", "专车看房"], 218 | "icon": "https://res.lgdsunday.club/renting_sale_3.jpg", 219 | "panoramaImg": "https://res.lgdsunday.club/renting_panorama_2.jpg", 220 | "imags": ["https://res.lgdsunday.club/renting_sale_3.jpg", "https://res.lgdsunday.club/renting_sale_5.jpg", "https://res.lgdsunday.club/renting_sale_7.jpg", "https://res.lgdsunday.club/renting_sale_1.jpg", "https://res.lgdsunday.club/renting_sale_2.jpg"], 221 | "lng": "116.58161989806", 222 | "lat": "39.964750858521" 223 | } 224 | } 225 | ``` 226 | 227 | ### 2.7 获取地图区域房产信息 228 | 229 | - 请求路径:`area` 230 | 231 | - 请求方法:`get` 232 | 233 | - 请求参数: 234 | 235 | | 参数名 | 参数说明 | 数据类型 | 236 | | :--------------- | --------------------- | -------- | 237 | | parentId(可选) | 父区域 ID | String | 238 | | level(可选) | 地图级别.可选 0、1、2 | String | 239 | 240 | - 响应参数 241 | 242 | | 参数名 | 参数说明 | 数据类型 | 243 | | :---------- | ------------ | -------- | 244 | | status | 响应状态 | Number | 245 | | description | 响应描述信息 | String | 246 | | data | 响应数据体 | Array | 247 | 248 | - 响应数据 249 | 250 | ```json 251 | { 252 | "status": 200, 253 | "description": "请求成功", 254 | "data": [{ 255 | "id": "642", 256 | "prop_num": 146273, 257 | "name": "朝阳", 258 | "parent_id": "600", 259 | "mid_price": "71976", 260 | "mid_change": "-0.00378301", 261 | "lat": "39.92656", 262 | "lng": "116.44976" 263 | }, { 264 | "id": "818", 265 | "prop_num": 25118, 266 | "name": "通州", 267 | "parent_id": "600", 268 | "mid_price": "44799", 269 | "mid_change": "-0.00154788", 270 | "lat": "39.91624", 271 | "lng": "116.663214" 272 | }, { 273 | "id": "2678", 274 | "prop_num": 21593, 275 | "name": "北京周边", 276 | "parent_id": "600", 277 | "mid_price": "14316", 278 | "mid_change": "0.0195556", 279 | "lat": "39.544097", 280 | "lng": "116.690164" 281 | }] 282 | } 283 | ``` 284 | 285 | ### 2.8 获取地图中任一小区的房产列表 286 | 287 | - 请求路径:`area/house` 288 | 289 | - 请求方法:`get` 290 | 291 | - 请求参数:无 292 | 293 | - 响应参数 294 | 295 | | 参数名 | 参数说明 | 数据类型 | 296 | | :---------- | ------------ | -------- | 297 | | status | 响应状态 | Number | 298 | | description | 响应描述信息 | String | 299 | | data | 响应数据体 | Array | 300 | 301 | - 响应数据 302 | 303 | ```json 304 | { 305 | "status": 200, 306 | "description": "请求成功", 307 | "data": [{ 308 | "id": "5", 309 | "name": "和棠瑞著", 310 | "maps": ["平谷", "平谷"], 311 | "address": "金海湖景区坝前广场西侧500米", 312 | "price": "18000", 313 | "minArea": "305", 314 | "maxArea": "350", 315 | "tags": ["一房一价", "低单价", "项目在建", "独栋别墅"], 316 | "icon": "https://res.lgdsunday.club/renting_sale_4.jpg", 317 | "panoramaImg": "https://res.lgdsunday.club/renting_panorama_1.jpg", 318 | "imags": ["https://res.lgdsunday.club/renting_sale_4.jpg", "https://res.lgdsunday.club/renting_sale_8.jpg", "https://res.lgdsunday.club/renting_sale_7.jpg", "https://res.lgdsunday.club/renting_sale_9.jpg", "https://res.lgdsunday.club/renting_sale_2.jpg", "https://res.lgdsunday.club/renting_sale_6.jpg", "https://res.lgdsunday.club/renting_sale_8.jpg", "https://res.lgdsunday.club/renting_sale_4.jpg"], 319 | "lng": "117.29248588749", 320 | "lat": "40.183640647611" 321 | }, { 322 | "id": "7", 323 | "name": "首开龙湖熙悦宸著", 324 | "maps": ["大兴", "西红门"], 325 | "address": "京开高速与福欣路交叉口向东100米", 326 | "price": "64400", 327 | "minArea": "81", 328 | "maxArea": "136", 329 | "tags": ["项目在建", "装修交付", "活动优惠", "大户型"], 330 | "icon": "https://res.lgdsunday.club/renting_sale_3.jpg", 331 | "panoramaImg": "https://res.lgdsunday.club/renting_panorama_3.jpg", 332 | "imags": ["https://res.lgdsunday.club/renting_sale_3.jpg", "https://res.lgdsunday.club/renting_sale_6.jpg", "https://res.lgdsunday.club/renting_sale_1.jpg", "https://res.lgdsunday.club/renting_sale_8.jpg", "https://res.lgdsunday.club/renting_sale_5.jpg"], 333 | "lng": "116.35037226417", 334 | "lat": "39.797250039556" 335 | }] 336 | } 337 | ``` 338 | 339 | -------------------------------------------------------------------------------- /src/assets/icon/demo.css: -------------------------------------------------------------------------------- 1 | /* Logo 字体 */ 2 | @font-face { 3 | font-family: "iconfont logo"; 4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); 5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), 6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), 7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), 8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); 9 | } 10 | 11 | .logo { 12 | font-family: "iconfont logo"; 13 | font-size: 160px; 14 | font-style: normal; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | 19 | /* tabs */ 20 | .nav-tabs { 21 | position: relative; 22 | } 23 | 24 | .nav-tabs .nav-more { 25 | position: absolute; 26 | right: 0; 27 | bottom: 0; 28 | height: 42px; 29 | line-height: 42px; 30 | color: #666; 31 | } 32 | 33 | #tabs { 34 | border-bottom: 1px solid #eee; 35 | } 36 | 37 | #tabs li { 38 | cursor: pointer; 39 | width: 100px; 40 | height: 40px; 41 | line-height: 40px; 42 | text-align: center; 43 | font-size: 16px; 44 | border-bottom: 2px solid transparent; 45 | position: relative; 46 | z-index: 1; 47 | margin-bottom: -1px; 48 | color: #666; 49 | } 50 | 51 | 52 | #tabs .active { 53 | border-bottom-color: #f00; 54 | color: #222; 55 | } 56 | 57 | .tab-container .content { 58 | display: none; 59 | } 60 | 61 | /* 页面布局 */ 62 | .main { 63 | padding: 30px 100px; 64 | width: 960px; 65 | margin: 0 auto; 66 | } 67 | 68 | .main .logo { 69 | color: #333; 70 | text-align: left; 71 | margin-bottom: 30px; 72 | line-height: 1; 73 | height: 110px; 74 | margin-top: -50px; 75 | overflow: hidden; 76 | *zoom: 1; 77 | } 78 | 79 | .main .logo a { 80 | font-size: 160px; 81 | color: #333; 82 | } 83 | 84 | .helps { 85 | margin-top: 40px; 86 | } 87 | 88 | .helps pre { 89 | padding: 20px; 90 | margin: 10px 0; 91 | border: solid 1px #e7e1cd; 92 | background-color: #fffdef; 93 | overflow: auto; 94 | } 95 | 96 | .icon_lists { 97 | width: 100% !important; 98 | overflow: hidden; 99 | *zoom: 1; 100 | } 101 | 102 | .icon_lists li { 103 | width: 100px; 104 | margin-bottom: 10px; 105 | margin-right: 20px; 106 | text-align: center; 107 | list-style: none !important; 108 | cursor: default; 109 | } 110 | 111 | .icon_lists li .code-name { 112 | line-height: 1.2; 113 | } 114 | 115 | .icon_lists .icon { 116 | display: block; 117 | height: 100px; 118 | line-height: 100px; 119 | font-size: 42px; 120 | margin: 10px auto; 121 | color: #333; 122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear; 123 | -moz-transition: font-size 0.25s linear, width 0.25s linear; 124 | transition: font-size 0.25s linear, width 0.25s linear; 125 | } 126 | 127 | .icon_lists .icon:hover { 128 | font-size: 100px; 129 | } 130 | 131 | .icon_lists .svg-icon { 132 | /* 通过设置 font-size 来改变图标大小 */ 133 | width: 1em; 134 | /* 图标和文字相邻时,垂直对齐 */ 135 | vertical-align: -0.15em; 136 | /* 通过设置 color 来改变 SVG 的颜色/fill */ 137 | fill: currentColor; 138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 139 | normalize.css 中也包含这行 */ 140 | overflow: hidden; 141 | } 142 | 143 | .icon_lists li .name, 144 | .icon_lists li .code-name { 145 | color: #666; 146 | } 147 | 148 | /* markdown 样式 */ 149 | .markdown { 150 | color: #666; 151 | font-size: 14px; 152 | line-height: 1.8; 153 | } 154 | 155 | .highlight { 156 | line-height: 1.5; 157 | } 158 | 159 | .markdown img { 160 | vertical-align: middle; 161 | max-width: 100%; 162 | } 163 | 164 | .markdown h1 { 165 | color: #404040; 166 | font-weight: 500; 167 | line-height: 40px; 168 | margin-bottom: 24px; 169 | } 170 | 171 | .markdown h2, 172 | .markdown h3, 173 | .markdown h4, 174 | .markdown h5, 175 | .markdown h6 { 176 | color: #404040; 177 | margin: 1.6em 0 0.6em 0; 178 | font-weight: 500; 179 | clear: both; 180 | } 181 | 182 | .markdown h1 { 183 | font-size: 28px; 184 | } 185 | 186 | .markdown h2 { 187 | font-size: 22px; 188 | } 189 | 190 | .markdown h3 { 191 | font-size: 16px; 192 | } 193 | 194 | .markdown h4 { 195 | font-size: 14px; 196 | } 197 | 198 | .markdown h5 { 199 | font-size: 12px; 200 | } 201 | 202 | .markdown h6 { 203 | font-size: 12px; 204 | } 205 | 206 | .markdown hr { 207 | height: 1px; 208 | border: 0; 209 | background: #e9e9e9; 210 | margin: 16px 0; 211 | clear: both; 212 | } 213 | 214 | .markdown p { 215 | margin: 1em 0; 216 | } 217 | 218 | .markdown>p, 219 | .markdown>blockquote, 220 | .markdown>.highlight, 221 | .markdown>ol, 222 | .markdown>ul { 223 | width: 80%; 224 | } 225 | 226 | .markdown ul>li { 227 | list-style: circle; 228 | } 229 | 230 | .markdown>ul li, 231 | .markdown blockquote ul>li { 232 | margin-left: 20px; 233 | padding-left: 4px; 234 | } 235 | 236 | .markdown>ul li p, 237 | .markdown>ol li p { 238 | margin: 0.6em 0; 239 | } 240 | 241 | .markdown ol>li { 242 | list-style: decimal; 243 | } 244 | 245 | .markdown>ol li, 246 | .markdown blockquote ol>li { 247 | margin-left: 20px; 248 | padding-left: 4px; 249 | } 250 | 251 | .markdown code { 252 | margin: 0 3px; 253 | padding: 0 5px; 254 | background: #eee; 255 | border-radius: 3px; 256 | } 257 | 258 | .markdown strong, 259 | .markdown b { 260 | font-weight: 600; 261 | } 262 | 263 | .markdown>table { 264 | border-collapse: collapse; 265 | border-spacing: 0px; 266 | empty-cells: show; 267 | border: 1px solid #e9e9e9; 268 | width: 95%; 269 | margin-bottom: 24px; 270 | } 271 | 272 | .markdown>table th { 273 | white-space: nowrap; 274 | color: #333; 275 | font-weight: 600; 276 | } 277 | 278 | .markdown>table th, 279 | .markdown>table td { 280 | border: 1px solid #e9e9e9; 281 | padding: 8px 16px; 282 | text-align: left; 283 | } 284 | 285 | .markdown>table th { 286 | background: #F7F7F7; 287 | } 288 | 289 | .markdown blockquote { 290 | font-size: 90%; 291 | color: #999; 292 | border-left: 4px solid #e9e9e9; 293 | padding-left: 0.8em; 294 | margin: 1em 0; 295 | } 296 | 297 | .markdown blockquote p { 298 | margin: 0; 299 | } 300 | 301 | .markdown .anchor { 302 | opacity: 0; 303 | transition: opacity 0.3s ease; 304 | margin-left: 8px; 305 | } 306 | 307 | .markdown .waiting { 308 | color: #ccc; 309 | } 310 | 311 | .markdown h1:hover .anchor, 312 | .markdown h2:hover .anchor, 313 | .markdown h3:hover .anchor, 314 | .markdown h4:hover .anchor, 315 | .markdown h5:hover .anchor, 316 | .markdown h6:hover .anchor { 317 | opacity: 1; 318 | display: inline-block; 319 | } 320 | 321 | .markdown>br, 322 | .markdown>p>br { 323 | clear: both; 324 | } 325 | 326 | 327 | .hljs { 328 | display: block; 329 | background: white; 330 | padding: 0.5em; 331 | color: #333333; 332 | overflow-x: auto; 333 | } 334 | 335 | .hljs-comment, 336 | .hljs-meta { 337 | color: #969896; 338 | } 339 | 340 | .hljs-string, 341 | .hljs-variable, 342 | .hljs-template-variable, 343 | .hljs-strong, 344 | .hljs-emphasis, 345 | .hljs-quote { 346 | color: #df5000; 347 | } 348 | 349 | .hljs-keyword, 350 | .hljs-selector-tag, 351 | .hljs-type { 352 | color: #a71d5d; 353 | } 354 | 355 | .hljs-literal, 356 | .hljs-symbol, 357 | .hljs-bullet, 358 | .hljs-attribute { 359 | color: #0086b3; 360 | } 361 | 362 | .hljs-section, 363 | .hljs-name { 364 | color: #63a35c; 365 | } 366 | 367 | .hljs-tag { 368 | color: #333333; 369 | } 370 | 371 | .hljs-title, 372 | .hljs-attr, 373 | .hljs-selector-id, 374 | .hljs-selector-class, 375 | .hljs-selector-attr, 376 | .hljs-selector-pseudo { 377 | color: #795da3; 378 | } 379 | 380 | .hljs-addition { 381 | color: #55a532; 382 | background-color: #eaffea; 383 | } 384 | 385 | .hljs-deletion { 386 | color: #bd2c00; 387 | background-color: #ffecec; 388 | } 389 | 390 | .hljs-link { 391 | text-decoration: underline; 392 | } 393 | 394 | /* 代码高亮 */ 395 | /* PrismJS 1.15.0 396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ 397 | /** 398 | * prism.js default theme for JavaScript, CSS and HTML 399 | * Based on dabblet (http://dabblet.com) 400 | * @author Lea Verou 401 | */ 402 | code[class*="language-"], 403 | pre[class*="language-"] { 404 | color: black; 405 | background: none; 406 | text-shadow: 0 1px white; 407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 408 | text-align: left; 409 | white-space: pre; 410 | word-spacing: normal; 411 | word-break: normal; 412 | word-wrap: normal; 413 | line-height: 1.5; 414 | 415 | -moz-tab-size: 4; 416 | -o-tab-size: 4; 417 | tab-size: 4; 418 | 419 | -webkit-hyphens: none; 420 | -moz-hyphens: none; 421 | -ms-hyphens: none; 422 | hyphens: none; 423 | } 424 | 425 | pre[class*="language-"]::-moz-selection, 426 | pre[class*="language-"] ::-moz-selection, 427 | code[class*="language-"]::-moz-selection, 428 | code[class*="language-"] ::-moz-selection { 429 | text-shadow: none; 430 | background: #b3d4fc; 431 | } 432 | 433 | pre[class*="language-"]::selection, 434 | pre[class*="language-"] ::selection, 435 | code[class*="language-"]::selection, 436 | code[class*="language-"] ::selection { 437 | text-shadow: none; 438 | background: #b3d4fc; 439 | } 440 | 441 | @media print { 442 | 443 | code[class*="language-"], 444 | pre[class*="language-"] { 445 | text-shadow: none; 446 | } 447 | } 448 | 449 | /* Code blocks */ 450 | pre[class*="language-"] { 451 | padding: 1em; 452 | margin: .5em 0; 453 | overflow: auto; 454 | } 455 | 456 | :not(pre)>code[class*="language-"], 457 | pre[class*="language-"] { 458 | background: #f5f2f0; 459 | } 460 | 461 | /* Inline code */ 462 | :not(pre)>code[class*="language-"] { 463 | padding: .1em; 464 | border-radius: .3em; 465 | white-space: normal; 466 | } 467 | 468 | .token.comment, 469 | .token.prolog, 470 | .token.doctype, 471 | .token.cdata { 472 | color: slategray; 473 | } 474 | 475 | .token.punctuation { 476 | color: #999; 477 | } 478 | 479 | .namespace { 480 | opacity: .7; 481 | } 482 | 483 | .token.property, 484 | .token.tag, 485 | .token.boolean, 486 | .token.number, 487 | .token.constant, 488 | .token.symbol, 489 | .token.deleted { 490 | color: #905; 491 | } 492 | 493 | .token.selector, 494 | .token.attr-name, 495 | .token.string, 496 | .token.char, 497 | .token.builtin, 498 | .token.inserted { 499 | color: #690; 500 | } 501 | 502 | .token.operator, 503 | .token.entity, 504 | .token.url, 505 | .language-css .token.string, 506 | .style .token.string { 507 | color: #9a6e3a; 508 | background: hsla(0, 0%, 100%, .5); 509 | } 510 | 511 | .token.atrule, 512 | .token.attr-value, 513 | .token.keyword { 514 | color: #07a; 515 | } 516 | 517 | .token.function, 518 | .token.class-name { 519 | color: #DD4A68; 520 | } 521 | 522 | .token.regex, 523 | .token.important, 524 | .token.variable { 525 | color: #e90; 526 | } 527 | 528 | .token.important, 529 | .token.bold { 530 | font-weight: bold; 531 | } 532 | 533 | .token.italic { 534 | font-style: italic; 535 | } 536 | 537 | .token.entity { 538 | cursor: help; 539 | } 540 | -------------------------------------------------------------------------------- /src/assets/icon/demo_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IconFont Demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |

19 | 29 |
30 |
31 |
    32 | 33 |
  • 34 | 35 |
    360度全景
    36 |
    &#xe8c3;
    37 |
  • 38 | 39 |
  • 40 | 41 |
    全景360
    42 |
    &#xe61f;
    43 |
  • 44 | 45 |
  • 46 | 47 |
    全屏
    48 |
    &#xe607;
    49 |
  • 50 | 51 |
  • 52 | 53 |
    缩小
    54 |
    &#xe639;
    55 |
  • 56 | 57 |
  • 58 | 59 |
    定位
    60 |
    &#xe675;
    61 |
  • 62 | 63 |
  • 64 | 65 |
    YDUI-二维码扫描
    66 |
    &#xe606;
    67 |
  • 68 | 69 |
  • 70 | 71 |
    搜索
    72 |
    &#xe6a6;
    73 |
  • 74 | 75 |
  • 76 | 77 |
    后退
    78 |
    &#xe64f;
    79 |
  • 80 | 81 |
  • 82 | 83 |
    后退
    84 |
    &#xe779;
    85 |
  • 86 | 87 |
  • 88 | 89 |
    箭头
    90 |
    &#xe60c;
    91 |
  • 92 | 93 |
  • 94 | 95 |
    箭头
    96 |
    &#xe75d;
    97 |
  • 98 | 99 |
  • 100 | 101 |
    推荐
    102 |
    &#xe63b;
    103 |
  • 104 | 105 |
  • 106 | 107 |
    首页
    108 |
    &#xe659;
    109 |
  • 110 | 111 |
  • 112 | 113 |
    地图
    114 |
    &#xe778;
    115 |
  • 116 | 117 |
118 |
119 |

Unicode 引用

120 |
121 | 122 |

Unicode 是字体在网页端最原始的应用方式,特点是:

123 |
    124 |
  • 兼容性最好,支持 IE6+,及所有现代浏览器。
  • 125 |
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • 126 |
  • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
  • 127 |
128 |
129 |

注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式

130 |
131 |

Unicode 使用步骤如下:

132 |

第一步:拷贝项目下面生成的 @font-face

133 |
@font-face {
135 |   font-family: 'iconfont';
136 |   src: url('iconfont.eot');
137 |   src: url('iconfont.eot?#iefix') format('embedded-opentype'),
138 |       url('iconfont.woff2') format('woff2'),
139 |       url('iconfont.woff') format('woff'),
140 |       url('iconfont.ttf') format('truetype'),
141 |       url('iconfont.svg#iconfont') format('svg');
142 | }
143 | 
144 |

第二步:定义使用 iconfont 的样式

145 |
.iconfont {
147 |   font-family: "iconfont" !important;
148 |   font-size: 16px;
149 |   font-style: normal;
150 |   -webkit-font-smoothing: antialiased;
151 |   -moz-osx-font-smoothing: grayscale;
152 | }
153 | 
154 |

第三步:挑选相应图标并获取字体编码,应用于页面

155 |
156 | <span class="iconfont">&#x33;</span>
158 | 
159 |
160 |

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

161 |
162 |
163 |
164 |
165 |
    166 | 167 |
  • 168 | 169 |
    170 | 360度全景 171 |
    172 |
    .iconduquanjing 173 |
    174 |
  • 175 | 176 |
  • 177 | 178 |
    179 | 全景360 180 |
    181 |
    .iconquanjing 182 |
    183 |
  • 184 | 185 |
  • 186 | 187 |
    188 | 全屏 189 |
    190 |
    .iconquanping 191 |
    192 |
  • 193 | 194 |
  • 195 | 196 |
    197 | 缩小 198 |
    199 |
    .iconsuoxiao 200 |
    201 |
  • 202 | 203 |
  • 204 | 205 |
    206 | 定位 207 |
    208 |
    .iconlocation 209 |
    210 |
  • 211 | 212 |
  • 213 | 214 |
    215 | YDUI-二维码扫描 216 |
    217 |
    .iconyduierweimasaomiao 218 |
    219 |
  • 220 | 221 |
  • 222 | 223 |
    224 | 搜索 225 |
    226 |
    .iconsousuo 227 |
    228 |
  • 229 | 230 |
  • 231 | 232 |
    233 | 后退 234 |
    235 |
    .iconback 236 |
    237 |
  • 238 | 239 |
  • 240 | 241 |
    242 | 后退 243 |
    244 |
    .icondown 245 |
    246 |
  • 247 | 248 |
  • 249 | 250 |
    251 | 箭头 252 |
    253 |
    .iconjiantou 254 |
    255 |
  • 256 | 257 |
  • 258 | 259 |
    260 | 箭头 261 |
    262 |
    .icontuya_huabanfuben 263 |
    264 |
  • 265 | 266 |
  • 267 | 268 |
    269 | 推荐 270 |
    271 |
    .icontuijian 272 |
    273 |
  • 274 | 275 |
  • 276 | 277 |
    278 | 首页 279 |
    280 |
    .iconshouye 281 |
    282 |
  • 283 | 284 |
  • 285 | 286 |
    287 | 地图 288 |
    289 |
    .iconditu 290 |
    291 |
  • 292 | 293 |
294 |
295 |

font-class 引用

296 |
297 | 298 |

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

299 |

与 Unicode 使用方式相比,具有如下特点:

300 |
    301 |
  • 兼容性良好,支持 IE8+,及所有现代浏览器。
  • 302 |
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • 303 |
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • 304 |
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • 305 |
306 |

使用步骤如下:

307 |

第一步:引入项目下面生成的 fontclass 代码:

308 |
<link rel="stylesheet" href="./iconfont.css">
309 | 
310 |

第二步:挑选相应图标并获取类名,应用于页面:

311 |
<span class="iconfont iconxxx"></span>
312 | 
313 |
314 |

" 315 | iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

316 |
317 |
318 |
319 |
320 |
    321 | 322 |
  • 323 | 326 |
    360度全景
    327 |
    #iconduquanjing
    328 |
  • 329 | 330 |
  • 331 | 334 |
    全景360
    335 |
    #iconquanjing
    336 |
  • 337 | 338 |
  • 339 | 342 |
    全屏
    343 |
    #iconquanping
    344 |
  • 345 | 346 |
  • 347 | 350 |
    缩小
    351 |
    #iconsuoxiao
    352 |
  • 353 | 354 |
  • 355 | 358 |
    定位
    359 |
    #iconlocation
    360 |
  • 361 | 362 |
  • 363 | 366 |
    YDUI-二维码扫描
    367 |
    #iconyduierweimasaomiao
    368 |
  • 369 | 370 |
  • 371 | 374 |
    搜索
    375 |
    #iconsousuo
    376 |
  • 377 | 378 |
  • 379 | 382 |
    后退
    383 |
    #iconback
    384 |
  • 385 | 386 |
  • 387 | 390 |
    后退
    391 |
    #icondown
    392 |
  • 393 | 394 |
  • 395 | 398 |
    箭头
    399 |
    #iconjiantou
    400 |
  • 401 | 402 |
  • 403 | 406 |
    箭头
    407 |
    #icontuya_huabanfuben
    408 |
  • 409 | 410 |
  • 411 | 414 |
    推荐
    415 |
    #icontuijian
    416 |
  • 417 | 418 |
  • 419 | 422 |
    首页
    423 |
    #iconshouye
    424 |
  • 425 | 426 |
  • 427 | 430 |
    地图
    431 |
    #iconditu
    432 |
  • 433 | 434 |
435 |
436 |

Symbol 引用

437 |
438 | 439 |

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 440 | 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

441 |
    442 |
  • 支持多色图标了,不再受单色限制。
  • 443 |
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • 444 |
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • 445 |
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • 446 |
447 |

使用步骤如下:

448 |

第一步:引入项目下面生成的 symbol 代码:

449 |
<script src="./iconfont.js"></script>
450 | 
451 |

第二步:加入通用 CSS 代码(引入一次就行):

452 |
<style>
453 | .icon {
454 |   width: 1em;
455 |   height: 1em;
456 |   vertical-align: -0.15em;
457 |   fill: currentColor;
458 |   overflow: hidden;
459 | }
460 | </style>
461 | 
462 |

第三步:挑选相应图标并获取类名,应用于页面:

463 |
<svg class="icon" aria-hidden="true">
464 |   <use xlink:href="#icon-xxx"></use>
465 | </svg>
466 | 
467 |
468 |
469 | 470 |
471 |
472 | 491 | 492 | 493 | -------------------------------------------------------------------------------- /src/assets/icon/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | --------------------------------------------------------------------------------