提交 8baf5bd8 编写于 作者: !阳仔's avatar !阳仔

add master

上级
MIT License
Copyright (c) 2022 CSDN 技术社区
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# CSDN数据可视化
## 预览地址
- 线上预览地址:[https://csdn.gitcode.host/csdn-datav](https://csdn.gitcode.host/csdn-datav)
## 开发文档
- 开发文档: [develop.md](https://gitcode.net/csdn/csdn-datav/-/blob/master/doc/develop.md)
- API接口: [api.md](https://gitcode.net/csdn/csdn-datav/-/blob/master/doc/api.md)
## 一、前言
关于开源重要性不多赘述。直接进入主题,我们相信开源的价值,认可这种协作模式能带来更大的价值,同时我们也希望99%的开发者都愿意参与到开源建设中,通过开源学习,成长,找到有相同目标的伙伴,通过参与开源项目建设,可以共享开源的成果。
当前的绝大多数开源项目,大多靠企业、开源基金会或个人赞助,大部分开源贡献者靠着“大爱”在幸苦的维护项目,能获得回报的是少数,这样会打击开源参与者的积极性。
基于此,我们提出「新开源」概念,不回避**参与开源建设能够获得什么回报**这样的问题,**探索开源商业化**,为开源寻找可持续发展之路。
“CSDN数据可视化”就是这样一个项目。
CSDN数据可视化是一个由CSDN内部发起,但完全以开源方式运作的项目,该项目将以开放+新开源的形态去运作。
**开放**:我们将脱敏开放CSDN的内部数据,比如:用户原力值、省/城市原力总分、作者粉丝分布、创作动态等各种数据来支持项目发展。
**新开源**:我们在这个过程中将直面开源商业化,探索项目商业化的可能性,我们计划将该项目的绝大多数甚至全部商业收入分享给所有开源贡献者。
## 二、项目介绍
### 2.1、项目目标:
通过开源和社区项目,让 CSDN 有 “每天值得看” 的独特数据可视化, 成为中国第一名的真实 IT 数据展示平台。
### 2.2、V0.1版本主要功能:
页面展示:
1. 通过中国地图展示各省技术贡献热度值;(暂定:计算各地区TOP1000原力值总分)
2. 在地图上可展示各区域原力分TOP1头像;(点击可进入主页)
3. 点击省份可展示该区域内创作者原力分TOP100;
其他展示:
- 发起者及贡献者头像;
- 开源项目地址;
- 开源项目技术栈;
- 服务支持:[CSDN开发云](https://dev.csdn.net/)
### 2.3、项目技术栈:
vue+echarts(暂定,纯前端项目)
### 2.4、测试/线上服务器支持:
[CSDN开发云](https://dev.csdn.net/)
### 2.5、项目奖励:
设定项目贡献分,可通过参与项目开发、项目宣传、测试、内容共建、技术问答等方式获得贡献分,贡献任务由项目发起者发布。
项目贡献分由CSDN平台及赞助者提供。
### 2.6、项目商业化探索方向(贡献者共同探讨):
- To学习者:如何从零开始建设一个数据可视化项目。(将发布内容共建任务从零开始用文字、图片、视频、代码等方式记录项目开发过程)
- ToC:付费(或会员)可查看更有价值的数据。(待议)
- ToB:设置广告位,接受B端付费广告。(暂定:广告投放需项目贡献者投票确定)
## 三、贡献者招募
- 项目技术/管理顾问:可以根据需求制定合理的技术方案并拆解开发任务;
- 产品:对项目有浓厚的兴趣,了解CSDN,最好是CSDN用户;
- 设计:暂由CSDN UED团队成员担任;
- 开发贡献者:对开源贡献感兴趣,能根据发布的开发任务完成功能开发;
- 开源项目会议记录:有较好的文字功底,参与开源项目讨论,并记录开源项目沟通成果并对外发布;
- 知识共创者:对本项目技术栈较为了解,CSDN博主,根据项目发展共建知识体系;
- 种子用户:对该项目感兴趣,并愿意参与早期项目讨论及功能测试;
### 四、项目参与答疑
待整理
### 五、可视化地图设计图
- 综合热榜
- 省份排名
- 贡献者
- 粉丝分布
[点击查看设计稿链接](https://gitcode.net/oslabs/csdn-datav/-/wikis/home)
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
# csdn-datav
2
## 环境准备
```bash
# 大小写敏感
git config core.ignorecase false
# 修改NPM国内镜像加速
npm config set registry https://registry.npmmirror.com/
# 设置你git提交用户名/邮箱,注意本项目尽量不要带--global
git config user.name "git用户名"
git config user.emall "git邮箱"
```
* *注意*:设置git提交的user.email与[CSDN账号邮箱](https://i.csdn.net/#/user-center/account) 保持一致,避免个人真实信息泄露
## 项目启动
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
{
"name": "csdn-datav",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build && npm run copy",
"lint": "vue-cli-service lint",
"copy": "shx cp ./dist/index.html ./dist/404.html"
},
"dependencies": {
"axios": "^0.27.2",
"clipboard": "^2.0.11",
"core-js": "^3.8.3",
"echarts": "^5.3.3",
"element-ui": "^2.15.9",
"node-sass": "^6.0.1",
"sass-loader": "^10.0.1",
"vant": "^2.12.9",
"vue": "^2.6.14",
"vue-router": "^3.1.3"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"babel-plugin-import": "^1.13.3",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"postcss": "^8.2.8",
"postcss-pxtorem": "^5.1.1",
"shx": "^0.3.4",
"vue-template-compiler": "^2.6.14"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
module.exports = {
plugins: {
'autoprefixer': {
overrideBrowserslist: ['> 0.15% in CN']
},
'postcss-pxtorem': {
rootValue: 37.5, // 结果为:设计稿元素尺寸/16,比如元素宽320px,最终页面会换算成 20rem
propList: ['*'], // 是一个存储哪些将被转换的属性列表,这里设置为['*']全部,假设需要仅对边框进行设置,可以写['*', '!border*']
unitPrecision: 5, // 保留rem小数点多少位
// selectorBlackList: ['.radius'], //则是一个对css选择器进行过滤的数组,比如你设置为['fs'],那例如fs-xl类名,里面有关px的样式将不被转换,这里也支持正则写法。
replace: true, // 这个真不知到干嘛用的。有知道的告诉我一下
mediaQuery: false, // 媒体查询( @media screen 之类的)中不生效
exclude: function (file) {
if (file.indexOf('components/element-ui') !== -1) { // elementui
return true
} else if (file.indexOf('view/pc') !== -1) {
return true
}
return false
}
}
}
}
此差异已折叠。
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="https://g.csdnimg.cn/static/logo/favicon32.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=968f3f24decdc7564a37458565d50ad7&plugin=AMap.Scale,AMap.ToolBar"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
<script>
function isMobile () {
var ua = window.navigator.userAgent
if ( ua.match(/Android/i) || ua.match(/webOS/i) || ua.match(/SymbianOS/i) || ua.match(/iPhone/i) || ua.match(/iPad/i) || ua.match(/iPod/i) || ua.match(/BlackBerry/i) || ua.match(/Windows Phone/i) ) {
return true
} else {
return false
}
}
function setFontsize() {
let vWidth = document.documentElement.clientWidth
if (vWidth === 0) {
setTimeout(function() {
setFontsize();
}, 100);
return;
}
document.documentElement.style.fontSize = vWidth / 10 + 'px';
}
if(isMobile()) {
setFontsize()
}
</script>
</html>
<template>
<!-- -->
<div class="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
data(){
return {
}
},
methods: {
}
}
</script>
<style scoped>
*{
-webkit-font-smoothing: antialiased;
}
</style>
\ No newline at end of file
import Vue from 'vue';
let Bus = new Vue();
export default Bus;
\ No newline at end of file
export const isMobile = () => {
var ua = window.navigator.userAgent
if (
ua.match(/Android/i) ||
ua.match(/webOS/i) ||
ua.match(/SymbianOS/i) ||
ua.match(/iPhone/i) ||
ua.match(/iPad/i) ||
ua.match(/iPod/i) ||
ua.match(/BlackBerry/i) ||
ua.match(/Windows Phone/i)
) {
return true;
} else {
return false;
}
}
\ No newline at end of file
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
/*
Write your variables here. All available variables can be
found in element-ui/packages/theme-chalk/src/common/var.scss.
For example, to overwrite the theme color:
*/
$--color-primary: #3399ea;
$--color-danger: #FC5531;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@import "~element-ui/packages/theme-chalk/src/index";
import Vue from 'vue';
import './element-variables.scss';
import {
Popover
} from 'element-ui';
Vue.use(Popover)
\ No newline at end of file
import {
Message
} from 'element-ui'
let messageInstance = null
let time = ''
const resetMessage = (options) => {
if (messageInstance) {
messageInstance.close()
}
if (typeof options === 'string') {
options = {
message: options
}
}
if (options.duration === 0) {
time = 0
} else if (options.duration === 5000) {
time = 5000
} else {
time = 1500
}
messageInstance = Message({ ...options, duration: time })
return messageInstance
}
;['error', 'success', 'info', 'warning'].forEach(type => {
resetMessage[type] = options => {
if (typeof options === 'string') {
options = {
message: options
}
}
options.type = type
return resetMessage(options)
}
})
export default resetMessage
/**
* @Author : wzk
* @Date : 2021/3/17Wednesday12
* @Last Modified by : wzk
* @Last Modified time : 2021/3/17Wednesday12
* @Description:
**/
import Vue from "vue";
import {
Button,
Tab,
Tabs,
AddressEdit,
Field,
Checkbox,
CheckboxGroup,
Toast,
PullRefresh,
List,
RadioGroup,
Radio,
Cell,
CellGroup,
Col,
Row,
Stepper,
Divider,
Form,
Empty,
Uploader,
Popup,
Rate
} from "vant";
Vue.use(Rate);
Vue.use(Popup);
Vue.use(Button);
Vue.use(Tab);
Vue.use(Tabs);
Vue.use(AddressEdit);
Vue.use(Field);
Vue.use(Checkbox);
Vue.use(CheckboxGroup);
Vue.use(Toast);
Vue.use(PullRefresh);
Vue.use(List);
Vue.use(Radio);
Vue.use(RadioGroup);
Vue.use(Cell);
Vue.use(Col);
Vue.use(Row);
Vue.use(Stepper);
Vue.use(Divider);
Vue.use(Form);
Vue.use(CellGroup);
Vue.use(Empty);
Vue.use(Uploader);
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import router from './router.js'
import './components/element-ui/element.js'
import './components/vant-ui'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
// index.js 文件内容
import Vue from 'vue';
import VueRouter from 'vue-router';
import {isMobile} from "@/common/util"
// 定义路由, 创建路由配置项
const routes = [
{
path: '/',
name: 'pcmap',
component: () => import('./view/pc/home.vue'),
beforeEnter (to, from, next) {
if (!isMobile()) {
next();
} else {
next({
path:'/m' ,
});
}
},
children: [
{
path: '',
redirect: 'force'
},
{
path: 'force',
component: () => import('./view/pc/force.vue'),
meta: {
title: '全网博主原力排名 - 开源实验室',
navTitle:'原力排名',
name:'全网博主原力排名',
pageSpm: '1011.2266'
}
},
{
path: 'fans',
component: () => import('./view/pc/fans.vue'),
meta: {
title: '全网博主铁粉排名 - 开源实验室',
name:'全网博主铁粉排名',
navTitle:'铁粉排名',
pageSpm: '1011.2266'