非常感谢那些无私开源的程序员,希望我也能够有能力像你们那样,开源很多很有意思的东西~~

  1. //index.html
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="utf-8">
  6. <title>cloud-music</title>
  7. <meta http-equiv=X-UA-Compatible content="IE=edge">
  8. <meta name=format-detection content="telephone=no">
  9. <meta name=format-detection content="email=no">
  10. <meta name=apple-mobile-web-app-capable content=yes>
  11. <meta name=apple-mobile-web-app-status-bar-style content=black>
  12. <meta name=full-screen content=yes>
  13. <meta name=browsermode content=application>
  14. <meta name=x5-orientation content=portrait>
  15. <meta name=x5-fullscreen content=true>
  16. <meta name=x5-page-mode content=app>
  17. <!--清除缓存-->
  18. <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  19. <meta http-equiv="Pragma" content="no-cache" />
  20. <meta http-equiv="Expires" content="0" />
  21. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,minimal-ui">
  22. <link rel="icon" href="static/logo.ico" type="image/x-icon" />
  23. <link rel="shortcut icon" href="static/logo.ico" type="image/x-icon" />
  24. <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
  25. <link href="http://cdn.bootcss.com/material-design-icons/3.0.1/iconfont/material-icons.min.css" rel="stylesheet">
  26. <script>
  27. ;(function (doc, win, undefined) {
  28. let docEl = doc.documentElement,
  29. resizeEvt = 'orientationchange' in win? 'orientationchange' : 'resize',
  30. recalc = function () {
  31. let clientWidth = docEl.clientWidth;
  32. if (clientWidth === undefined) return;
  33. docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';
  34. };
  35. if (doc.addEventListener === undefined) return;
  36. win.addEventListener(resizeEvt, recalc, false);
  37. doc.addEventListener('DOMContentLoaded', recalc, false)
  38. })(document, window);
  39. </script>
  40. <style>
  41. * {
  42. margin: 0;
  43. padding: 0;
  44. }
  45. a {
  46. text-decoration: none;
  47. }
  48. p, span {
  49. font-size: 12px;
  50. }
  51. </style>
  52. </head>
  53. <body>
  54. <div id="app">
  55. <keep-alive>
  56. <router-view v-if="$route.meta.keepAlive"></router-view>
  57. </keep-alive>
  58. <router-view v-if="!$route.meta.keepAlive"></router-view>
  59. </div>
  60. <script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
  61. <script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
  62. <script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
  63. <script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
  64. </body>
  65. </html>
  1. //app.vue
  2. <template>
  3. <div>
  4. <!-- 主界面部分 -->
  5. <loading :show="loadingShow"></loading>
  6. <keep-alive>
  7. <router-view v-if="$route.meta.keepAlive"></router-view>
  8. </keep-alive>
  9. <router-view v-if="!$route.meta.keepAlive"></router-view>
  10. <player v-show="songList.length > 0 && !showDetail"></player>
  11. </div>
  12. </template>
  13. <script>
  14. import player from './components/playerBar/playerBar';
  15. import loading from './components/loading/overall-loading';
  16. import { mapGetters } from 'vuex';
  17. export default {
  18. name: 'app',
  19. mounted () {
  20. console.log('%c 浅滩戏虾', 'background-image:-webkit-gradient( linear, left top,right top, color-stop(0, #00a419),color-stop(0.15, #f44336), color-stop(0.29, #ff4300),color-stop(0.3, #AA00FF),color-stop(0.4, #8BC34A), color-stop(0.45, #607D8B),color-stop(0.6, #4096EE), color-stop(0.75, #D50000),color-stop(0.9, #4096EE), color-stop(1, #FF1A00));color:transparent;-webkit-background-clip:text;font-size:13px;');
  21. },
  22. computed: {
  23. ...mapGetters([
  24. 'songList',
  25. 'showDetail',
  26. 'loadingShow'
  27. ])
  28. },
  29. components: {
  30. player,
  31. loading
  32. }
  33. };
  34. </script>
  1. //main.js
  2. import Vue from 'vue';
  3. import store from './vuex';
  4. import VueRouter from 'vue-router';
  5. import VueLazyload from 'vue-lazyload'; // 引入图片懒加载模块
  6. import App from './App';
  7. import routes from './routers';
  8. // import {loadFromlLocal} from './common/js/store'; // 公共方法:本地缓存
  9. // 注册为全局组件
  10. Vue.use(VueRouter);
  11. // error,loading是图片路径, 用require引入
  12. Vue.use(VueLazyload, {
  13. error: require('./assets/404.png'),
  14. loading: require('./assets/loading.jpg'),
  15. attempt: 1
  16. }
  17. );
  18. const scrollBehavior = (to, from, savedPosition) => {
  19. if (savedPosition) {
  20. // savedPosition is only available for popstate navigations.
  21. return savedPosition;
  22. } else {
  23. let position = {};
  24. // new navigation.
  25. // scroll to anchor by returning the selector
  26. if (to.hash) {
  27. position.selector = to.hash;
  28. }
  29. // check if any matched route config has meta that requires scrolling to top
  30. if (to.matched.some(m => m.meta.scrollToTop)) {
  31. // cords will be used if no selector is provided,
  32. // or if the selector didn't match any element.
  33. position.x = 0;
  34. position.y = 0;
  35. }
  36. // if the returned position is falsy or an empty object,
  37. // will retain current scroll position.
  38. return position;
  39. }
  40. };
  41. const router = new VueRouter({
  42. // mode: 'history',
  43. 'linkActiveClass': 'active',
  44. routes, // (缩写)相当于 routes: routes
  45. scrollBehavior
  46. });
  47. /**
  48. * 创建和挂载根实例。
  49. * 记得要通过 router 配置参数注入路由,
  50. * 从而让整个应用都有路由功能
  51. */
  52. const routerApp = new Vue({
  53. router,
  54. store,
  55. render: h => h(App)
  56. }).$mount('#app');
  57. /**
  58. * loadFromlLocal()是读取本地缓存数据,具体common/js/store.js 查看
  59. */
  60. // if (!loadFromlLocal('music', 'find', false)) {
  61. // router.push('/find');
  62. // }
  63. export default routerApp;
  1. //router.js
  2. /**
  3. * 整个app的路由设置
  4. */
  5. const router = [{
  6. path: '/find', // 引导页
  7. name: 'index',
  8. component (resolve) {
  9. require.ensure(['./views/index'], () => {
  10. resolve(require('./views/index'));
  11. });
  12. },
  13. children: [{
  14. path: '/find', // 发现
  15. name: 'find',
  16. component (resolve) {
  17. require.ensure(['./views/find/find'], () => {
  18. resolve(require('./views/find/find'));
  19. });
  20. },
  21. meta: { keepAlive: true }
  22. }],
  23. meta: { keepAlive: true }
  24. }, {
  25. path: '/search', // 搜索页
  26. name: 'search',
  27. component (resolve) {
  28. require.ensure(['./views/search/search'], () => {
  29. resolve(require('./views/search/search'));
  30. });
  31. },
  32. meta: { keepAlive: true }
  33. }, {
  34. path: '/player/:id', // 单曲播放页
  35. name: 'player',
  36. component (resolve) {
  37. require.ensure(['./views/detail/player/player'], () => {
  38. resolve(require('./views/detail/player/player'));
  39. });
  40. },
  41. meta: { keepAlive: false }
  42. }, {
  43. path: '/playLists/:id', // 歌单详情页
  44. name: 'playLists',
  45. component (resolve) {
  46. require.ensure(['./views/detail/playList/playlists'], () => {
  47. resolve(require('./views/detail/playList/playlists'));
  48. });
  49. },
  50. meta: { keepAlive: false }
  51. }, {
  52. path: '/singer/:id', // 歌手详情页
  53. name: 'singer',
  54. component (resolve) {
  55. require.ensure(['./views/detail/singer/singer'], () => {
  56. resolve(require('./views/detail/singer/singer'));
  57. });
  58. },
  59. meta: { keepAlive: false }
  60. }, {
  61. path: '/album/:id', // 专辑详情页
  62. name: 'album',
  63. component (resolve) {
  64. require.ensure(['./views/detail/album/album'], () => {
  65. resolve(require('./views/detail/album/album'));
  66. });
  67. },
  68. meta: { keepAlive: false }
  69. }, {
  70. path: '/user/:id', // 用户详情页
  71. name: 'user',
  72. component (resolve) {
  73. require.ensure(['./views/detail/user/user'], () => {
  74. resolve(require('./views/detail/user/user'));
  75. });
  76. },
  77. meta: { keepAlive: false }
  78. }, {
  79. path: '/ranking/:idx', // 榜单详情页
  80. name: 'ranking',
  81. component (resolve) {
  82. require.ensure(['./views/detail/ranking/ranking'], () => {
  83. resolve(require('./views/detail/ranking/ranking'));
  84. });
  85. },
  86. meta: { keepAlive: false }
  87. }, {
  88. path: '/mv/:id', // 视频播放
  89. name: 'mv',
  90. component (resolve) {
  91. require.ensure(['./views/detail/mvPlay/mvPlay'], () => {
  92. resolve(require('./views/detail/mvPlay/mvPlay'));
  93. });
  94. },
  95. meta: { keepAlive: false }
  96. }, {
  97. path: '/playListComment/:id', // 歌单评论
  98. name: 'playListComment',
  99. component (resolve) {
  100. require.ensure(['./views/detail/playList/playListComment'], () => {
  101. resolve(require('./views/detail/playList/playListComment'));
  102. });
  103. },
  104. meta: { keepAlive: false }
  105. }, {
  106. path: '/albumComment/:id', // 专辑评论
  107. name: 'albumComment',
  108. component (resolve) {
  109. require.ensure(['./views/detail/album/albumComment'], () => {
  110. resolve(require('./views/detail/album/albumComment'));
  111. });
  112. },
  113. meta: { keepAlive: false }
  114. }, {
  115. path: '/rankingComment/:id', // 排行榜歌单评论
  116. name: 'rankingComment',
  117. component (resolve) {
  118. require.ensure(['./views/detail/ranking/rankingComment'], () => {
  119. resolve(require('./views/detail/ranking/rankingComment'));
  120. });
  121. },
  122. meta: { keepAlive: false }
  123. }, {
  124. path: '*', redirect: '/find' // url错误重回定向
  125. }];
  126. export default router;
  1. //find.vue
  2. <template>
  3. <transition name="fade">
  4. <div class="find-page">
  5. <tab :line-width=2 active-color='#b72712' defaultColor='#666' bar-active-color='#b72712'
  6. v-model="index">
  7. <!-- 切换 -->
  8. <tab-item class="vux-center" :selected="type === item" v-for="(item, index) in tabList"
  9. @click="type = item" :key="index" style="background-color: #fdfffe;">{{item}}
  10. </tab-item>
  11. </tab>
  12. <!-- 轮播切换的 -->
  13. <!-- 这个是左右的那种切换 -->
  14. <swiper v-model="index" height="100%" :show-dots="false" class="swiper-container" style="width:100%;height: 100%;padding-bottom: 90px;background-color: #eef2f1;">
  15. <swiper-item :key="1">
  16. <div class="tab-swiper vux-center">
  17. <v-recommend></v-recommend>
  18. </div>
  19. </swiper-item>
  20. <swiper-item :key="2">
  21. <div class="tab-swiper vux-center">
  22. <v-play-lists></v-play-lists>
  23. </div>
  24. </swiper-item>
  25. <swiper-item :key="3">
  26. <div class="tab-swiper vux-center">
  27. <v-ranking></v-ranking>
  28. </div>
  29. </swiper-item>
  30. </swiper>
  31. </div>
  32. </transition>
  33. </template>
  34. <script>
  35. import { Tab, TabItem, Swiper, SwiperItem } from 'vux';
  36. import vRecommend from './recommend/recommend';
  37. import vPlayLists from './playLists/playLists';
  38. import vRanking from './ranking/ranking';
  39. //tabList:list()
  40. const list = () => ['个性推荐', '歌单', '排行榜'];
  41. export default {
  42. name: 'find',
  43. data () {
  44. return {
  45. index: 0,
  46. tabList: list(),
  47. type: '个性推荐'
  48. };
  49. },
  50. components: {
  51. vPlayLists,
  52. vRecommend,
  53. vRanking,
  54. Tab,
  55. TabItem,
  56. Swiper,
  57. SwiperItem
  58. }
  59. };
  60. </script>
  61. <style lang="stylus" rel="stylesheet/stylus" scoped>
  62. @import 'find.styl';
  63. </style>
  1. //activitysList.vue
  2. <template>
  3. <ul class="activitys-area">
  4. <li class="activity-card-find" v-for="(data, index) in activitys" :key="index">
  5. <img v-lazy="data.picUrl + '?param=400y200'" lazy="loading">
  6. <h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2>
  7. </li>
  8. </ul>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'v-activity-list',
  13. props: {
  14. activitys: {
  15. type: Array,
  16. default: []
  17. }
  18. }
  19. };
  20. </script>
  21. <style lang="stylus" rel="stylesheet/stylus">
  22. @import 'activitysList.styl';
  23. </style>
  1. //mvList.vue
  2. <template>
  3. <ul class="MV-area">
  4. <li class="mv-card-find" v-for="(data, index) in MVs" style="flex: 0 0 49.5%" @click="jumpMvDetail(data.id)" :key="index">
  5. <img v-lazy="data.picUrl + '?param=400y200'" lazy="loading">
  6. <h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2>
  7. </li>
  8. </ul>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'v-mv-list',
  13. props: {
  14. MVs: {
  15. type: Array,
  16. default: []
  17. }
  18. },
  19. methods: {
  20. jumpMvDetail(id) {
  21. this.$router.push({
  22. path: '/mv/' + id
  23. });
  24. }
  25. }
  26. };
  27. </script>
  1. //newSongList.vue
  2. <template>
  3. <ul class="newSongList-area">
  4. <li class="newSongList-card-find" v-for="(data, index) in newSong" @click="jumpAlbumDetail(data.song.album.id)" :key="index">
  5. <img v-lazy="data.song.album.picUrl+ '?param=200y200'" lazy="loading">
  6. <h2 style="-webkit-box-orient: vertical;-webkit-line-clamp: 1">{{data.name}}</h2>
  7. <p style="-webkit-box-orient: vertical;">{{data.song.artists[0].name}}</p>
  8. </li>
  9. </ul>
  10. </template>
  11. <script>
  12. export default {
  13. name: 'v-new-song-lists',
  14. props: {
  15. newSong: {
  16. type: Array,
  17. default: []
  18. }
  19. },
  20. methods: {
  21. jumpAlbumDetail(id) {
  22. this.$router.push({
  23. path: '/album/' + id
  24. });
  25. }
  26. }
  27. };
  28. </script>
  1. //djProgram.vue
  2. <template>
  3. <ul class="djProgram-area">
  4. <li class="djProgram-card-find" v-for="(data, index) in djProgram" :key="index">
  5. <img v-lazy="data.picUrl+ '?param=200y200'" lazy="loading">
  6. <h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2>
  7. </li>
  8. </ul>
  9. </template>
  10. <script>
  11. export default {
  12. name: 'v-dj-program-lists',
  13. props: {
  14. djProgram: {
  15. type: Array,
  16. default: []
  17. }
  18. },
  19. methods: {
  20. jumpPlayListsDetail(id) {
  21. this.$router.push({
  22. path: '/playLists/' + id
  23. });
  24. }
  25. }
  26. };
  27. </script>
  1. //recommend.vue
  2. <template>
  3. <div class="recommend-area">
  4. <div id="slider">
  5. <swiper :options="swiperOption" style="height: 100%;">
  6. <swiper-slide v-for="(item, index) in slide_list" :key="index"><img :src="item" class="banner-item" alt="" style="width: 100%; height: 100%;"></swiper-slide>
  7. <div class="swiper-pagination swiper-pagination-white" slot="pagination"></div>
  8. </swiper>
  9. </div>
  10. <div class="recommend-playLists-area">
  11. <h1 class="title">推荐歌单</h1>
  12. <!-- 推荐歌单,有与后端交互 -->
  13. <v-play-lists :playlists="playlists"></v-play-lists>
  14. </div>
  15. <div class="recommend-activitys-area">
  16. <h1 class="title">独家放送</h1>
  17. <v-activitys-list :activitys="activitys"></v-activitys-list>
  18. </div>
  19. <div class="recommend-mv-area">
  20. <h1 class="title">最新音乐</h1>
  21. <v-new-song-list :newSong="newSong"></v-new-song-list>
  22. </div>
  23. <div class="recommend-mv-area">
  24. <h1 class="title">推荐MV</h1>
  25. <v-mv-list :MVs="MVs"></v-mv-list>
  26. </div>
  27. <div class="recommend-mv-area">
  28. <h1 class="title">主播电台</h1>
  29. <v-dj-program-list :djProgram="djProgram"></v-dj-program-list>
  30. </div>
  31. </div>
  32. </template>
  33. <script>
  34. import api from '../../../api/index';
  35. import { swiper, swiperSlide } from 'vue-awesome-swiper';
  36. // v-for
  37. import vPlayLists from '../../../components/list/find/recommend/playLists';
  38. // v-for
  39. import vActivitysList from '../../../components/list/find/recommend/activitysList';
  40. import vMvList from '../../../components/list/find/recommend/mvList';
  41. import vNewSongList from '../../../components/list/find/recommend/newSongList';
  42. import vDjProgramList from '../../../components/list/find/recommend/djProgram';
  43. const imgList = ['/static/banner1.jpg', '/static/banner2.jpg', '/static/banner3.jpg', '/static/banner4.jpg'];
  44. export default {
  45. name: 'v-recommend',
  46. data () {
  47. return {
  48. swiperOption: {
  49. pagination: '.swiper-pagination',
  50. paginationClickable: true,
  51. autoplay: 2500
  52. },
  53. slide_list: imgList,
  54. playlists: [],
  55. activitys: [],
  56. MVs: [],
  57. newSong: [],
  58. djProgram: []
  59. };
  60. },
  61. mounted () {
  62. this.getPersonalizedResource();
  63. this.getPrivatecontentResource();
  64. this.getPersonalizedMvResource();
  65. this.getNewSongResource();
  66. this.getDjProgramResource();
  67. },
  68. methods: {
  69. getPersonalizedResource() {
  70. api.getPersonalized().then((response) => {
  71. this.playlists = response.data.result;
  72. console.log('getPersonalizedResource',response);
  73. })
  74. .catch((response) => {
  75. console.log(response);
  76. });
  77. },
  78. getPrivatecontentResource() {
  79. api.getPrivatecontent().then((response) => {
  80. this.activitys = response.data.result;
  81. })
  82. .catch((response) => {
  83. console.log(response);
  84. });
  85. },
  86. getPersonalizedMvResource() {
  87. api.getPersonalizedMv().then((response) => {
  88. this.MVs = response.data.result;
  89. })
  90. .catch((response) => {
  91. console.log(response);
  92. });
  93. },
  94. getNewSongResource() {
  95. api.getNewSong().then((response) => {
  96. this.newSong = response.data.result.slice(0, 6);
  97. })
  98. .catch((response) => {
  99. console.log(response);
  100. });
  101. },
  102. getDjProgramResource() {
  103. api.getDjProgram().then((response) => {
  104. this.djProgram = response.data.result.slice(0, 6);
  105. })
  106. .catch((response) => {
  107. console.log(response);
  108. });
  109. }
  110. },
  111. components: {
  112. swiper,
  113. swiperSlide,
  114. vPlayLists,
  115. vActivitysList,
  116. vMvList,
  117. vNewSongList,
  118. vDjProgramList
  119. }
  120. };
  121. </script>
  122. <style lang="stylus" rel="stylesheet/stylus">
  123. @import 'recommend.styl';
  124. </style>

  1. //主界面部分代码
  2. <template>
  3. <!-- 主界面部分 -->
  4. <transition name="fade">
  5. <div class="index">
  6. <!-- 侧边栏 -->
  7. <asideMenu v-show="isShowAsideMenu"></asideMenu>
  8. <!-- 头部 -->
  9. <v-header></v-header>
  10. <router-view></router-view>
  11. </div>
  12. </transition>
  13. </template>
  14. <script>
  15. import vHeader from '../components/header/header';
  16. import asideMenu from '../components/aside/aside';
  17. export default {
  18. computed: {
  19. isShowAsideMenu() {
  20. return this.$store.state.isShowAsideMenu;
  21. }
  22. },
  23. components: {
  24. vHeader,
  25. asideMenu
  26. }
  27. };
  28. </script>
  29. <style lang="stylus" rel="stylesheet/stylus" scoped>
  30. @import 'index.styl';
  31. </style>
  1. //header.vue
  2. <template>
  3. <div class="header">
  4. <div class="name">
  5. <span @click="showAsideMenu(true)" class="func"><i class="func-icon"></i></span>
  6. <router-link to="/find" class="item">
  7. <span class="music"><i class="music-icon"></i></span>
  8. </router-link>
  9. <router-link to="/search" class="item">
  10. <span class="personal"><i class="personal-icon"></i></span>
  11. </router-link>
  12. <span class="search"><i @click="toSearch" class="search-icon"></i></span>
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. export default {
  18. name: 'header',
  19. methods: {
  20. toSearch () {
  21. this.$router.push('/search');
  22. },
  23. showAsideMenu (flag) {
  24. this.$store.commit('showAsideMenu', flag);
  25. }
  26. }
  27. };
  28. </script>
  29. <style lang="stylus" rel="stylesheet/stylus" scoped>
  30. @import "header.styl";
  31. </style>
  1. //src/components/aside/aside.vue
  2. <template>
  3. <transition name="fadeIn">
  4. <div class="aside-menu">
  5. <i @click="showAsideMenu" class="back"></i>
  6. <div class="aside">
  7. <div class="info">
  8. <img src="https://avatars2.githubusercontent.com/u/16521402?v=3&u=225ef33c491d879294c4cb06621ec15f5b01f02a&s=400">
  9. <p class="author">浅滩戏虾</p>
  10. </div>
  11. </div>
  12. <div @click.stop.prevent="showAsideMenu" class="mask"></div>
  13. </div>
  14. </transition>
  15. </template>
  16. <script>
  17. export default {
  18. name: 'aside',
  19. data () {
  20. return {
  21. isSignIn: false
  22. };
  23. },
  24. methods: {
  25. showAsideMenu () {
  26. this.$store.commit('showAsideMenu', false);
  27. }
  28. }
  29. };
  30. </script>
  31. <style lang="stylus" rel="stylesheet/stylus" scoped>
  32. @import "aside.styl";
  33. </style>



  1. //src/views/find/playLists/playLists.vue
  2. <template>
  3. <div class="playLists-area">
  4. <button-tab v-model="index">
  5. <button-tab-item @on-item-click="selectType()">最新</button-tab-item>
  6. <button-tab-item @on-item-click="selectType()">最热</button-tab-item>
  7. </button-tab>
  8. <div class="playLists">
  9. <ul>
  10. <li v-for="(data, index) in playlists" :key="index">
  11. <v-play-list :data="data"></v-play-list>
  12. </li>
  13. </ul>
  14. </div>
  15. </div>
  16. </template>
  17. <script>
  18. import api from '../../../api/index';
  19. import { ButtonTab, ButtonTabItem } from 'vux';
  20. import vPlayList from '../../../components/card/findCard/playList/playList';
  21. export default {
  22. name: 'v-play-lists',
  23. data () {
  24. return {
  25. index: 0,
  26. keys: 'new',
  27. playlists: []
  28. };
  29. },
  30. mounted: function() {
  31. this.getTopPlaylistResource();
  32. },
  33. methods: {
  34. selectType () {
  35. this.keys = this.index ? 'hot' : 'new';
  36. //点击切换,从后端获取数据
  37. this.getTopPlaylistResource();
  38. },
  39. getTopPlaylistResource() {
  40. this.$store.commit('update_loading', true);
  41. api.getTopPlaylistResource(this.keys, 20, 0).then((response) => {
  42. this.playlists = response.data.playlists;
  43. //数据会先渲染出来,所以要重新渲染完后执行
  44. // $nextTick() 在dom 重新渲染完后执行
  45. this.$nextTick(() => {
  46. this.$store.commit('update_loading', false);
  47. });
  48. })
  49. .catch((response) => {
  50. console.log(response);
  51. });
  52. }
  53. },
  54. components: {
  55. vPlayList,
  56. ButtonTab,
  57. ButtonTabItem
  58. }
  59. };
  60. </script>
  61. <style lang="stylus" rel="stylesheet/stylus" scoped>
  62. @import 'playLists.styl';
  63. </style>
  1. //src/components/list/find/ranking/songsList.vue
  2. <template>
  3. <ul class="ranking-songsList">
  4. <li style="-webkit-box-orient: vertical;" v-for="(item, index) in data" :key="index">{{index + 1}}.{{item.name}}-{{item.artists[0].name}}</li>
  5. </ul>
  6. </template>
  7. <script>
  8. export default {
  9. name: 'v-songs-list',
  10. props: {
  11. data: {
  12. type: Array,
  13. default: []
  14. //如果有和后端交互的数据,页面会展示
  15. }
  16. }
  17. };
  18. </script>
  19. <style lang="stylus" rel="stylesheet/stylus">
  20. @import 'songsList.styl';
  21. </style>

  1. //search.vue
  2. <template lang="html">
  3. <transition name="fade">
  4. <div class="search-page">
  5. <div class='header-other'>
  6. <span @click="goBack" class="back"><i class="back-icon"></i></span>
  7. <div class="input">
  8. <input v-model="keywords" @keyup.enter="toSearch(keywords)" type="text" placeholder='搜素音乐、歌手、歌词、用户'>
  9. <i @click="keywords=''" v-show="keywords!==''&&!isShowHot" class="icon-cancel"></i>
  10. </div>
  11. </div>
  12. <div class="hot" v-if="isShowHot">
  13. <p>热门搜索</p>
  14. <ul class="keywords">
  15. <li v-for="item of hotKeywords" v-text="item" @click="toSearch(item)" class="keyword"></li>
  16. </ul>
  17. </div>
  18. <div v-else class="search-list">
  19. <tab :line-width=2 active-color='#b72712' defaultColor='#666' bar-active-color='#b72712'
  20. v-model="index">
  21. <tab-item class="vux-center" :selected="type === item" v-for="(item, index) in tabList"
  22. @click="type = item" :key="index">{{item}}
  23. </tab-item>
  24. </tab>
  25. <swiper v-model="index" height="100%" :show-dots="false" class="swiper-container">
  26. <swiper-item :key="1">
  27. <div class="tab-swiper vux-center search-area">
  28. <v-single-list :songs="songs"></v-single-list>
  29. </div>
  30. </swiper-item>
  31. <swiper-item :key="2">
  32. <div class="tab-swiper vux-center search-area">
  33. <v-singer-list :singer="singer"></v-singer-list>
  34. </div>
  35. </swiper-item>
  36. <swiper-item :key="3">
  37. <div class="tab-swiper vux-center search-area">
  38. <v-album-list :albums="albums"></v-album-list>
  39. </div>
  40. </swiper-item>
  41. <swiper-item :key="4">
  42. <div class="tab-swiper vux-center search-area">
  43. <v-play-lists :playlist="playlist"></v-play-lists>
  44. </div>
  45. </swiper-item>
  46. <swiper-item :key="5">
  47. <div class="tab-swiper vux-center search-area">
  48. <v-user-list :user="user"></v-user-list>
  49. </div>
  50. </swiper-item>
  51. <swiper-item :key="6">
  52. <div class="tab-swiper vux-center search-area">
  53. <v-mv-list :MVs="mvs"></v-mv-list>
  54. </div>
  55. </swiper-item>
  56. </swiper>
  57. </div>
  58. </div>
  59. </transition>
  60. </template>
  61. <script>
  62. import api from '../../api/index';
  63. import { Tab, TabItem, Swiper, SwiperItem } from 'vux';
  64. import vSingleList from '../../components/list/search/singleList';
  65. import vSingerList from '../../components/list/search/singerList';
  66. import vAlbumList from '../../components/list/search/albumList';
  67. import vPlayLists from '../../components/list/search/playLists';
  68. import vUserList from '../../components/list/search/userList';
  69. import vMvList from '../../components/list/search/mvList';
  70. const list = () => ['单曲', '歌手', '专辑', '歌单', '用户', 'MV'];
  71. const hotKeywordsList = () => ['清白之年', '我喜欢上你时的内心活动', '我想和你唱',
  72. 'hyukoh', '童话镇', '陈奕迅', '漂洋过海来看你', '许嵩', '成都', '林俊杰'];
  73. export default {
  74. name: 'search',
  75. data () {
  76. return {
  77. index: 0,
  78. tabList: list(),
  79. hotKeywords: hotKeywordsList(),
  80. type: '单曲',
  81. keywords: '',
  82. isShowHot: true,
  83. songs: [],
  84. singer: [],
  85. albums: [],
  86. playlist: [],
  87. user: [],
  88. mvs: []
  89. };
  90. },
  91. // watch $route 决定是否清除关键词
  92. watch: {
  93. '$route' (to, from) {
  94. if (from.name === 'find') {
  95. this.keywords = '';
  96. this.isShowHot = true;
  97. }
  98. }
  99. },
  100. methods: {
  101. initSearchList () {
  102. this.getSingleResource(); // 获取搜索单曲
  103. this.getAlbumResource(); // 获取搜索专辑
  104. this.getSingerResource(); // 获取搜索歌手
  105. this.getPlayListResource(); // 获取搜索歌单
  106. this.getUserResource(); // 获取搜索用户
  107. this.getMvResource(); // 获取搜索MV
  108. },
  109. goBack () {
  110. //返回
  111. this.$router.push({
  112. path: '/find'
  113. });
  114. },
  115. // 关键词搜索
  116. toSearch (keywords) {
  117. //关键词搜索
  118. this.keywords = keywords;
  119. if (this.keywords.trim()) {
  120. this.isShowHot = false;
  121. this.$router.push({
  122. path: '/search',
  123. query: {
  124. keywords: keywords
  125. }
  126. });
  127. this.initSearchList();
  128. }
  129. },
  130. // 获取搜索单曲
  131. getSingleResource() {
  132. this.$store.commit('update_loading', true);
  133. //获取搜索单曲
  134. api.getSearchResource(this.$route.query.keywords, 1, 30, 0)
  135. .then((response) => {
  136. this.songs = response.data.result.songs;
  137. // $nextTick() 在dom 重新渲染完后执行
  138. this.$nextTick(() => {
  139. this.$store.commit('update_loading', false);
  140. });
  141. })
  142. .catch((response) => {
  143. console.log(response);
  144. });
  145. },
  146. // 获取搜索专辑
  147. getSingerResource() {
  148. //与后端交互
  149. api.getSearchResource(this.$route.query.keywords, 100, 30, 0)
  150. .then((response) => {
  151. this.singer = response.data.result.artists;
  152. })
  153. .catch((response) => {
  154. console.log(response);
  155. });
  156. },
  157. // 获取搜索歌手
  158. getAlbumResource() {
  159. api.getSearchResource(this.$route.query.keywords, 10, 30, 0)
  160. .then((response) => {
  161. this.albums = response.data.result.albums;
  162. })
  163. .catch((response) => {
  164. console.log(response);
  165. });
  166. },
  167. // 获取搜索歌单
  168. getPlayListResource() {
  169. api.getSearchResource(this.$route.query.keywords, 1000, 30, 0)
  170. .then((response) => {
  171. this.playlist = response.data.result.playlists;
  172. })
  173. .catch((response) => {
  174. console.log(response);
  175. });
  176. },
  177. // 获取搜索用户
  178. getUserResource() {
  179. api.getSearchResource(this.$route.query.keywords, 1002, 30, 0)
  180. .then((response) => {
  181. this.user = response.data.result.userprofiles;
  182. })
  183. .catch((response) => {
  184. console.log(response);
  185. });
  186. },
  187. // 获取搜索MV
  188. getMvResource() {
  189. api.getSearchResource(this.$route.query.keywords, 1004, 30, 0)
  190. .then((response) => {
  191. this.mvs = response.data.result.mvs;
  192. })
  193. .catch((response) => {
  194. console.log(response);
  195. });
  196. }
  197. },
  198. components: {
  199. Tab,
  200. TabItem,
  201. Swiper,
  202. SwiperItem,
  203. vSingleList,
  204. vSingerList,
  205. vAlbumList,
  206. vPlayLists,
  207. vUserList,
  208. vMvList
  209. }
  210. };
  211. </script>
  212. <style lang="stylus" rel="stylesheet/stylus" scoped>
  213. @import "search.styl";
  214. </style>

  1. //singerList.vue
  2. <template>
  3. <ul class="singer-list">
  4. <li class="singer-card" v-for="(data, index) in singer" @click="jumpSingerDetail(data.id)" :key="index">
  5. <img v-lazy="data.picUrl + '?param=200y200'" lazy="loading" class="avatar">
  6. <p class="singer-name">
  7. <span class="name" style="-webkit-box-orient: vertical;">{{data.name}}</span>
  8. <span class="trans" v-show="data.trans">({{data.trans}})</span>
  9. </p>
  10. </li>
  11. </ul>
  12. </template>
  13. <script>
  14. export default {
  15. name: 'v-singer-list',
  16. props: {
  17. singer: {
  18. type: Array,
  19. default: []
  20. }
  21. },
  22. methods: {
  23. jumpSingerDetail(id) {
  24. this.$router.push({
  25. path: '/singer/' + id
  26. });
  27. }
  28. }
  29. };
  30. </script>
  31. <style lang="stylus" rel="stylesheet/stylus" scoped>
  32. @import 'singerList.styl';
  33. </style>
  1. //albumList.vue
  2. <template>
  3. <ul class="album-list">
  4. <v-album-card :data="data" v-for="(data, index) in albums" :key="index"></v-album-card>
  5. </ul>
  6. </template>
  7. <script>
  8. import vAlbumCard from '../../card/searchCard/albumCard';
  9. export default {
  10. name: 'v-album-list',
  11. components: {
  12. vAlbumCard
  13. },
  14. props: {
  15. albums: {
  16. type: Array,
  17. default: []
  18. }
  19. }
  20. };
  21. </script>
  22. <style lang="stylus" rel="stylesheet/stylus" scoped>
  23. @import 'albumList.styl';
  24. </style>
  1. //userList.vue
  2. <template>
  3. <ul class="user-list">
  4. <li v-for="(data, index) in user" class="user-card" @click="jumpUserDetail(data.userId)" :key="index">
  5. <img v-lazy="data.avatarUrl + '?param=200y200'" lazy="loading" class="avatarImage">
  6. <div class="avatar-info">
  7. <p class="avatar-name">
  8. {{data.nickname}}
  9. <span class="gender-man" v-if="data.gender === 1"><i class="man-icon"></i></span>
  10. <span class="gender-female" v-else><i class="female-icon"></i></span>
  11. </p>
  12. <p class="avatar-intro" style="-webkit-box-orient: vertical;">{{data.signature}}</p>
  13. </div>
  14. </li>
  15. </ul>
  16. </template>
  17. <!-- v-if v-else的使用 -->
  18. <script>
  19. export default {
  20. name: 'v-user-card',
  21. props: {
  22. user: {
  23. type: Array,
  24. default: []
  25. }
  26. },
  27. methods: {
  28. jumpUserDetail(id) {
  29. this.$router.push({
  30. path: '/user/' + id
  31. });
  32. }
  33. }
  34. };
  35. </script>
  36. <style lang="stylus" rel="stylesheet/stylus" scoped>
  37. @import 'userList.styl';
  38. </style>
  1. //mvList.vue
  2. <template>
  3. <ul class="mv-list">
  4. <li class="mv-card" v-for="(data, index) in MVs" style="flex: 0 0 49.5%" @click="jumpMvDetail(data.id)" :key="index">
  5. <img v-lazy="data.cover + '?param=400y200'" lazy="loading" class="mv-image">
  6. <h2 style="-webkit-box-orient: vertical;">{{data.name}}</h2>
  7. <p style="-webkit-box-orient: vertical;">{{data.artistName}}</p>
  8. </li>
  9. </ul>
  10. </template>
  11. <script>
  12. export default {
  13. name: 'v-mv-list',
  14. props: {
  15. MVs: {
  16. type: Array,
  17. default: []
  18. }
  19. },
  20. methods: {
  21. jumpMvDetail(id) {
  22. this.$router.push({
  23. path: '/mv/' + id
  24. });
  25. }
  26. }
  27. };
  28. </script>
  29. <style lang="stylus" rel="stylesheet/stylus" scoped>
  30. @import 'mvList.styl';
  31. </style>

  1. //user.vue
  2. <template>
  3. <transition name="fade">
  4. <div class="user-detail">
  5. <div class="user-info" :style="{'background-image': 'url(' + backgroundImage + ')'}">
  6. <x-header :left-options="{backText: ''}" style="background-color:inherit; width: 100%;">{{userInfo.nickname}}</x-header>
  7. <img v-lazy="avatarImage + '?param=200y200'" lazy="loading">
  8. <p class="user-name">
  9. {{userInfo.nickname}}
  10. <span class="gender-man" v-if="userInfo.gender === 1"><i class="man-icon"></i></span>
  11. <span class="gender-female" v-else><i class="female-icon"></i></span>
  12. </p>
  13. </div>
  14. <div class="tab-list">
  15. <tab :line-width=2 active-color='#b72712' defaultColor='#666' bar-active-color='#b72712' v-model="index">
  16. <tab-item class="vux-center" :selected="type === item" v-for="(item, index) in tabList" @click="type = item" :key="index">{{item}}</tab-item>
  17. </tab>
  18. <swiper v-model="index" height="100%" :show-dots="false">
  19. <swiper-item :key="0">
  20. <div class="tab-swiper vux-center">
  21. <div class="play-lists-detail">
  22. <ul style="list-style: none;">
  23. <li v-for="(data, index) in playlist" :key="index">
  24. <v-play-lists-card :data="data"></v-play-lists-card>
  25. </li>
  26. </ul>
  27. </div>
  28. </div>
  29. </swiper-item>
  30. <swiper-item :key="1">
  31. <!--<div class="tab-swiper vux-center">-->
  32. <!--<div class="hot-single-list">-->
  33. <!--<ul>-->
  34. <!--<li v-for="(data, order) in playlist">-->
  35. <!--<v-single-card :data="data" :order="order"></v-single-card>-->
  36. <!--</li>-->
  37. <!--</ul>-->
  38. <!--</div>-->
  39. <!--</div>-->
  40. </swiper-item>
  41. </swiper>
  42. </div>
  43. </div>
  44. </transition>
  45. </template>
  46. <script type="text/ecmascript-6">
  47. import api from '../../../api';
  48. import { XHeader, Tab, TabItem, Swiper, SwiperItem } from 'vux';
  49. import vPlayListsCard from '../../../components/card/detail/playlists';
  50. const list = () => ['歌单', '关于TA'];
  51. export default {
  52. data () {
  53. return {
  54. tName: '歌单',
  55. type: '歌单',
  56. tabList: list(),
  57. index: 0,
  58. backgroundColor: '',
  59. userInfo: {},
  60. playlist: {}
  61. };
  62. },
  63. mounted: function() {
  64. this.getUserInfo();
  65. },
  66. methods: {
  67. back () {
  68. this.$router.go(-1);
  69. },
  70. getUserInfo () {
  71. this.$store.commit('update_loading', true);
  72. //与后端交互获取资源
  73. api.getUserPlaylistResource(this.$route.params.id)
  74. .then((response) => {
  75. this.playlist = response.data.playlist;
  76. this.userInfo = response.data.playlist[0].creator;
  77. // $nextTick() 在dom 重新渲染完后执行
  78. this.$nextTick(() => {
  79. this.$store.commit('update_loading', false);
  80. });
  81. })
  82. .catch((response) => {
  83. console.log(response);
  84. });
  85. }
  86. },
  87. computed: {
  88. backgroundImage() {
  89. return '' || (this.userInfo.backgroundUrl + '?param=500y500');
  90. },
  91. avatarImage() {
  92. return '' || this.userInfo.avatarUrl;
  93. }
  94. },
  95. components: {
  96. Tab,
  97. TabItem,
  98. Swiper,
  99. SwiperItem,
  100. XHeader,
  101. vPlayListsCard
  102. }
  103. };
  104. </script>
  105. <style lang="less" scoped>
  106. .vux-swiper {
  107. height: 100%;
  108. }
  109. .vux-slider {
  110. height: 100%;
  111. }
  112. .tab-swiper {
  113. background-color: #fff;
  114. height: 100%;
  115. }
  116. </style>
  117. <style lang="stylus" rel="stylesheet/stylus">
  118. @import "user.styl";
  119. </style>
  1. //playlists.vue
  2. <template>
  3. <transition name="fade">
  4. <div class="playlist">
  5. <div class="fixed-title" :style="{'background': 'rgba(183, 39, 18, '+ opacity +')'}" style="transition: opacity .1s;" v-show="!isShowDetail">
  6. <x-header :left-options="{backText: ''}" style="background-color:transparent">{{tName}}</x-header>
  7. </div>
  8. <div class="playlist-info" :style="{'background-image': 'url(' + playListImage + '?param=500y500'+ ')'}" v-show="!isShowDetail">
  9. <div class="playlist-info-blur">
  10. <div class="playlist-intro">
  11. <img v-lazy="playListImage" class="playlist-image" lazy="loading" alt="photo" @click="showDetail()">
  12. <div class="playlist-intro-other">
  13. <p class="playlist-title" style="-webkit-box-orient: vertical;">{{playlist.name}}</p>
  14. <div class="playlist-creator" @click="jumpUserDetail(creator.userId)">
  15. <img v-lazy="creatorImage + '?param=100y100'" lazy="loading">
  16. <span class="playlist-nickname" style="-webkit-box-orient: vertical;">{{creator.nickname}}</span>
  17. <span class="more"> > </span>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="playlist-status">
  22. <div class="playCount">
  23. <span class="file"><i class="icon-file"></i></span>
  24. <span>{{playlist.playCount}}</span>
  25. </div>
  26. <div class="commentCount">
  27. <span class="comment" @click="jumpCommentDetail()"><i class="icon-comment"></i></span>
  28. <span>{{playlist.commentCount}}</span>
  29. </div>
  30. <div class="shareCount">
  31. <span class="share"><i class="icon-share"></i></span>
  32. <span>{{playlist.shareCount}}</span>
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. <div class="play-list" v-show="!isShowDetail">
  38. <v-play-all :data="commonSongs"></v-play-all>
  39. <ul>
  40. <li v-for="(data, index) in list" :key='index'>
  41. <v-single-card :data="data" :index="index"></v-single-card>
  42. </li>
  43. </ul>
  44. </div>
  45. <v-play-list-detail :data="playlist" v-show="isShowDetail"></v-play-list-detail>
  46. </div>
  47. </transition>
  48. </template>
  49. <script>
  50. import api from '../../../api';
  51. import { XHeader } from 'vux';
  52. import vPlayAll from '../../../components/playAll/playAll.vue';
  53. import vSingleCard from '../../../components/card/detail/singleCard.vue';
  54. import vPlayListDetail from './playListDetail';
  55. export default {
  56. data () {
  57. return {
  58. playlist: {},
  59. tName: '歌单',
  60. creator: {},
  61. data: [],
  62. index: '',
  63. list: [],
  64. commonSongs: [],
  65. backgroundColor: '',
  66. opacity: 0,
  67. isShowDetail: false
  68. };
  69. },
  70. // 解除keep-alive的缓存
  71. beforeRouteEnter: (to, from, next) => {
  72. next(vm => {
  73. window.onscroll = () => {
  74. let opa = window.pageYOffset / 222;
  75. if (opa > 1) {
  76. vm.tName = vm.playlist.name;
  77. vm.opacity = 1;
  78. } else {
  79. vm.tName = '歌单';
  80. vm.opacity = 0;
  81. }
  82. };
  83. });
  84. },
  85. // 路由离开时清除onscroll事件
  86. beforeRouteLeave: (to, from, next) => {
  87. window.onscroll = null;
  88. next();
  89. },
  90. mounted: function() {
  91. let self = this;
  92. this.getPlayListDetail();
  93. this.$root.$on('close-detail', (condition) => {
  94. self.isShowDetail = condition;
  95. });
  96. },
  97. methods: {
  98. showDetail () {
  99. this.isShowDetail = true;
  100. },
  101. jumpUserDetail(id) {
  102. this.$router.push({
  103. path: '/user/' + id
  104. });
  105. },
  106. jumpCommentDetail() {
  107. this.$router.push({
  108. path: '/playListComment/' + this.$route.params.id
  109. });
  110. },
  111. getPlayListDetail () {
  112. //与后端交互获取数据
  113. this.$store.commit('update_loading', true);
  114. api.getPlaylistDetailResource(this.$route.params.id).then((response) => {
  115. this.playlist = response.data.playlist;
  116. this.list = response.data.playlist.tracks;
  117. this.creator = response.data.playlist.creator;
  118. this.songsToCommon(this.list);
  119. // $nextTick() 在dom 重新渲染完后执行
  120. this.$nextTick(() => {
  121. this.$store.commit('update_loading', false);
  122. });
  123. }).catch((error) => {
  124. console.log('加载歌单信息出错:' + error);
  125. });
  126. },
  127. songsToCommon (items) {
  128. let vm = this;
  129. this.commonSongs = items.map(function (item) {
  130. return {
  131. 'id': item.id,
  132. 'name': item.name,
  133. 'singer': vm.getAuthorList(item.ar),
  134. 'albumPic': item.al.picUrl,
  135. 'location': '',
  136. 'album': item.al.id
  137. };
  138. });
  139. },
  140. getAuthorList(authorInfo) {
  141. return authorInfo.map(function (item) {
  142. return item.name;
  143. }).toString();
  144. }
  145. },
  146. computed: {
  147. playListImage() {
  148. return '' || (this.playlist.picUrl);
  149. },
  150. creatorImage() {
  151. return '' || this.creator.avatarUrl;
  152. }
  153. },
  154. components: {
  155. XHeader,
  156. vPlayAll,
  157. vSingleCard,
  158. vPlayListDetail
  159. }
  160. };
  161. </script>
  162. <style lang="stylus" rel="stylesheet/stylus" scoped>
  163. @import "playlists.styl";
  164. </style>

本文学习自这位非常美丽的小姐姐,表白你哇

cloud-music的更多相关文章

  1. On cloud, be cloud native

    本来不想起一个英文名,但是想来想去都没能想出一个简洁地表述该意思的中文释义,所以就用了一个英文名称,望见谅. Cloud Native是一个刚刚由VMware所提出一年左右的名词.其表示在设计并实现一 ...

  2. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(六)

    (六)在Website Cloud中添加site 1新建Website,并打开 使用前面创建的用户 newbee@waplab.com 登录租户Portal,新建一个website 新建完成后, 可以 ...

  3. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(五)

    (五)注册Website Cloud 1 注册Website Cloud 添加Website Cloud   连接Website Cloud 注意, endpoint 是使用Management Se ...

  4. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(四)

    (四)搭建Website Cloud环境 1安装CONTROLLER主机 在开始安装Web site Cloud之前,读者应该对该服务的拓扑结构有个大概了解. 如图: Controller是非常重要的 ...

  5. 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(二)

    前言 (二)建立虚拟网络环境,以及域控和DNS服务器   1搭建虚拟网络环境 在Azure上创建虚拟网络.本例选择的是东南亚数据中心.后面在创建虚机的时候,也选择这个数据中心. VNet Name: ...

  6. spring/spring boot/spring cloud开发总结

    背景        针对RPC远程调用,都在使用dubbo.dubbox等,我们也是如此.由于社区暂停维护.应对未来发展,我们准备尝试新技术(或许这时候也不算什么新技术了吧),选择使用了spring ...

  7. Oracle Sales Cloud:管理沙盒(定制化)小细节2——使用对象触发器更新数字字段

    在上一篇 "管理沙盒(定制化)小细节1" 的随笔中,我们使用公式法在 "业务机会" 对象(单头)上建立了 "利润合计" 字段,并将它等于 & ...

  8. Oracle Sales Cloud:管理沙盒(定制化)小细节1——利用公式创建字段并显示在前端页面

    Oracle Sales Cloud(Oracle 销售云)是一套基于Oracle云端的CRM管理系统.由于 Oracle 销售云是基于 Oracle 云环境的,它与传统的管理系统相比,显著特点之一便 ...

  9. Oracle Sales Cloud:报告和分析(BIEE)小细节2——利用变量和过滤器传参(例如,根据提示展示不同部门的数据)

    在上一篇随笔中,我们建立了部门和子部门的双提示,并将部门和子部门做了关联.那么,本篇随笔我们重点介绍利用建好的双提示进行传参. 在操作之前,我们来看一个报告和分析的具体需求: [1] 两个有关联的提示 ...

  10. Oracle Sales Cloud:报告和分析(BIEE)小细节1——创建双提示并建立关联(例如,部门和子部门提示)

    Oracle Sales Cloud(Oracle 销售云)是一套基于Oracle云端的客户商机管理系统,通过提供丰富的功能来帮助提高销售效率,更好地去了解客户,发现和追踪商机,为最终的销售成交 (d ...

随机推荐

  1. Python - 集合与元素之数据类型和变量总结

    变量 变量的作用:保存状态(程序的运行本质是一系列的变化,变量的目的就是用来保存状态,变量值的变化就构成了程序运行的不同结果.) 例如:cs枪战中,一个人的生命可以表示为life = True 表示存 ...

  2. hibernate 注释多表 级联操作

    一对多模型(单向) 说明: 一个客户对应多个地址,通过客户可以获得该客户的多个地址的信息.客户和地址是一对多的关系,并且客户与地址是单向关联的关系. 映射策略 # 外键关联:两个表的关系定义在一个表中 ...

  3. yum与rpm常用选项

    rpm常用的命令组合: rpm 1.对系统中已安装软件的查询-q:查询系统已安装的软件-qa:查询系统所有已安装包-qf:查询一个已经安装的文件属于哪个软件包-ql:查询已安装软件包都安装到何处-qi ...

  4. Redis使用:聚合类型为空时,会自动被Redis删除

    项目中使用Redis来记录用户的上线和下线信息,其中用到了集合(sets)类型,某用户上线时,向sets中添加数据,下线时将相应数据从sets中删除,考虑当该用户的所有实例都下线时,需要将sets删除 ...

  5. 利用jquery模拟select效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. ubuntu 安装 go 编译环境

    参考: http://wiki.ubuntu.org.cn/Golang 从仓库安装(apt-get) sudo apt-get install golang 修改环境变量: vim /etc/env ...

  7. step()动画

    <style type="text/css"> .hi { width: 50px; height: 72px; background-image: url(" ...

  8. 网页上PNG透明图片的运用(ie6+滤镜)

    PNG ( Portable Network Graphics ) 格式的无损压缩和半透明特性对增强网页效果减少网页体积有着重要的作用,但由于 IE6 不支持 PNG,所以一直未能得到广泛的应用. 虽 ...

  9. hashhMap

    # hashMap原理 # HashMap是一个双列集合,是线程不安全的.以key.value的形式储存值.底层是由数组+链表+红黑树组成的,数组是HashMap的主干,链表则是主要为了解决哈希冲突而 ...

  10. JAVA利用JXL导出/生成 EXCEL1

    /** * 导出导出采暖市场部收入.成本.利润明细表 * @author JIA-G-Y */ public String exporExcel(String str) { String str=Se ...