| @@ -229,6 +229,7 @@ organizations=组织 | |||||
| images = 云脑镜像 | images = 云脑镜像 | ||||
| search=搜索 | search=搜索 | ||||
| code=代码 | code=代码 | ||||
| data_analysis=数字看板 | |||||
| repo_no_results=未找到匹配的项目。 | repo_no_results=未找到匹配的项目。 | ||||
| dataset_no_results = 未找到匹配的数据集。 | dataset_no_results = 未找到匹配的数据集。 | ||||
| user_no_results=未找到匹配的用户。 | user_no_results=未找到匹配的用户。 | ||||
| @@ -2162,19 +2163,6 @@ repos.stars=点赞数 | |||||
| repos.forks=派生数 | repos.forks=派生数 | ||||
| repos.issues=任务数 | repos.issues=任务数 | ||||
| repos.size=大小 | repos.size=大小 | ||||
| repos.id=ID | |||||
| repos.projectName=项目名称 | |||||
| repos.isPrivate=私有 | |||||
| repos.openi=OpenI指数 | |||||
| repos.visit=浏览量 | |||||
| repos.download=代码下载量 | |||||
| repos.pr=PR数 | |||||
| repos.commit=Commit数 | |||||
| repos.closedIssues=已解决任务数 | |||||
| repos.contributor=贡献者数 | |||||
| repos.yes=是 | |||||
| repos.no=否 | |||||
| datasets.dataset_manage_panel=数据集管理 | datasets.dataset_manage_panel=数据集管理 | ||||
| datasets.owner=所有者 | datasets.owner=所有者 | ||||
| @@ -0,0 +1 @@ | |||||
| <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1636355832057" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8359" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M1024 767.6928c0 7.168-2.8672 12.0832-8.4992 14.9504L571.2896 1021.8496 569.1392 1021.8496C567.7056 1023.2832 565.5552 1024 562.688 1024c-2.8672 0-5.0176-0.7168-6.4512-2.1504L554.1888 1021.8496 109.9776 782.6432C104.2432 779.776 101.376 774.8608 101.376 767.6928L101.376 255.1808 101.376 253.0304c0-1.3312 0.7168-2.8672 2.1504-4.3008L103.5264 246.5792l4.3008-4.3008 2.1504-2.1504L554.1888 1.024c5.7344-1.3312 11.3664-1.3312 17.1008 0l444.2112 239.2064 2.1504 2.1504 4.3008 4.3008 0 2.1504L1024 253.0304l0 2.1504L1024 767.6928zM135.5776 757.0432l410.0096 222.1056 0-474.112L135.5776 282.9312 135.5776 757.0432zM154.8288 255.1808 562.688 475.136l407.8592-219.9552L562.688 35.2256 154.8288 255.1808zM989.7984 757.0432l0-474.112L579.7888 505.0368l0 474.112L989.7984 757.0432z" p-id="8360"></path></svg> | |||||
| @@ -33,8 +33,9 @@ const ( | |||||
| // tplExploreOrganizations explore organizations page template | // tplExploreOrganizations explore organizations page template | ||||
| tplExploreOrganizations base.TplName = "explore/organizations" | tplExploreOrganizations base.TplName = "explore/organizations" | ||||
| // tplExploreCode explore code page template | // tplExploreCode explore code page template | ||||
| tplExploreCode base.TplName = "explore/code" | |||||
| tplExploreImages base.TplName = "explore/images" | |||||
| tplExploreCode base.TplName = "explore/code" | |||||
| tplExploreImages base.TplName = "explore/images" | |||||
| tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis" | |||||
| ) | ) | ||||
| // Home render home page | // Home render home page | ||||
| @@ -501,6 +502,10 @@ func ExploreImages(ctx *context.Context) { | |||||
| ctx.HTML(200, tplExploreImages) | ctx.HTML(200, tplExploreImages) | ||||
| } | } | ||||
| func ExploreDataAnalysis(ctx *context.Context) { | |||||
| ctx.HTML(200, tplExploreExploreDataAnalysis) | |||||
| } | |||||
| // NotFound render 404 page | // NotFound render 404 page | ||||
| func NotFound(ctx *context.Context) { | func NotFound(ctx *context.Context) { | ||||
| ctx.Data["Title"] = "Page Not Found" | ctx.Data["Title"] = "Page Not Found" | ||||
| @@ -325,6 +325,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
| m.Get("/organizations", routers.ExploreOrganizations) | m.Get("/organizations", routers.ExploreOrganizations) | ||||
| m.Get("/code", routers.ExploreCode) | m.Get("/code", routers.ExploreCode) | ||||
| m.Get("/images", routers.ExploreImages) | m.Get("/images", routers.ExploreImages) | ||||
| m.Get("/data_analysis", routers.ExploreDataAnalysis) | |||||
| }, ignSignIn) | }, ignSignIn) | ||||
| m.Combo("/install", routers.InstallInit).Get(routers.Install). | m.Combo("/install", routers.InstallInit).Get(routers.Install). | ||||
| Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost) | Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost) | ||||
| @@ -37,6 +37,7 @@ | |||||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | ||||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | ||||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | ||||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{else if .IsLandingPageHome}} | {{else if .IsLandingPageHome}} | ||||
| @@ -29,6 +29,7 @@ | |||||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | ||||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | ||||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | ||||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{else if .IsLandingPageHome}} | {{else if .IsLandingPageHome}} | ||||
| @@ -0,0 +1,14 @@ | |||||
| {{template "base/head" .}} | |||||
| <div id="data_analysis" style="height: 100%;"> | |||||
| </div> | |||||
| {{template "base/footer" .}} | |||||
| <style> | |||||
| .full.height { | |||||
| flex-grow: 1; | |||||
| padding-bottom: 53px; | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,123 @@ | |||||
| <template> | |||||
| <div style="height:100%"> | |||||
| <el-tabs tab-position="left" v-model="activeName" style="height:100%" @tab-click="handleClick" > | |||||
| <el-tab-pane label="概览" name="first" > | |||||
| <span slot="label"> | |||||
| <el-image style="width: 13px; height: 13px" src="/img/overview.png"> | |||||
| </el-image> | |||||
| 概览 | |||||
| </span> | |||||
| <div >概览.......</div> | |||||
| <div >概览.......</div> | |||||
| <div >概览.......</div><div >概览.......</div> | |||||
| <div >概览.......</div> | |||||
| </el-tab-pane> | |||||
| <el-tab-pane label="项目分析" name="second" id="second" > | |||||
| <ProAnalysis ref='ProAnalysis'id="pro" v-if="isRouterAlive"></ProAnalysis> | |||||
| <span slot="label"> | |||||
| <el-image style="width: 13px; height: 13px" src="/img/pro.svg"> | |||||
| </el-image> | |||||
| 项目分析 | |||||
| </span> | |||||
| </el-tab-pane> | |||||
| <el-tab-pane name="third" > | |||||
| <span slot='label'> | |||||
| <el-image style="width: 13px; height: 13px" src="/img/name.png"> | |||||
| </el-image> | |||||
| 用户分析 | |||||
| </span> | |||||
| <UserAnalysis ref='UserAnalysis' id ="usr"></UserAnalysis> | |||||
| </el-tab-pane> | |||||
| </el-tabs> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import ProAnalysis from './ProAnalysis.vue' | |||||
| import UserAnalysis from './UserAnalysis.vue' | |||||
| export default { | |||||
| components:{ | |||||
| 'ProAnalysis':ProAnalysis, | |||||
| 'UserAnalysis':UserAnalysis, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| activeName:"second", | |||||
| loading:true, | |||||
| loading1:true, | |||||
| isRouterAlive: true, | |||||
| isSecond:true, | |||||
| isThird:false, | |||||
| } | |||||
| }, | |||||
| methods:{ | |||||
| handleClick(tab, event){ | |||||
| if(tab.name=="second"){ | |||||
| this.reload() | |||||
| //document.getElementById('usr').style.display="none" | |||||
| //document.getElementById("pro").style.display='block' | |||||
| //this.$refs.ProAnalysis.getAllProList("all",7) | |||||
| this.isSecond = true | |||||
| this.isThird = false | |||||
| this.$refs.ProAnalysis.getAllProList("all",7) | |||||
| } | |||||
| if(tab.name=="third"){ | |||||
| // document.getElementById('usr').style.display="block" | |||||
| // document.getElementById("pro").style.display='none' | |||||
| //this.$refs.UserAnalysis.getUserList("all_usr",7) | |||||
| this.isSecond = false | |||||
| this.isThird = true | |||||
| } | |||||
| }, | |||||
| reload () { | |||||
| this.isRouterAlive = false | |||||
| this.$nextTick(() => (this.isRouterAlive = true)) | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| /deep/ .is-active{ | |||||
| color: #238BFC ; | |||||
| background-color: #FFFF ; | |||||
| } | |||||
| /deep/ .ui-container{ | |||||
| background-color: #FFFF; | |||||
| } | |||||
| /deep/ .el-tabs--left .el-tabs__header.is-left{ | |||||
| background-color:#F5F5F6; | |||||
| width: 12.43%; | |||||
| } | |||||
| .el-tabs--left .el-tabs__header.is-left | |||||
| html, | |||||
| body, | |||||
| /deep/ .el-container { | |||||
| padding: 0px; | |||||
| margin: 0px; | |||||
| height: 100%; | |||||
| } | |||||
| /deep/ .el-tabs--left .el-tabs__item.is-left { | |||||
| text-align: left; | |||||
| } | |||||
| /deep/ .el-tabs__item { | |||||
| padding: 0px 20px 0px 20px; | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,923 @@ | |||||
| <template> | |||||
| <div style="width: 100%;"> | |||||
| <div id = "pro_main"> | |||||
| <div style="margin-top: 10px;"> | |||||
| <b class="pro_item">项目分析</b> <span class="update_time">数据更新时间:{{lastUpdatedTime}}/{{recordBeginTime}}</span> | |||||
| </div> | |||||
| <bar-label :width="'95%'" :height="'500px'"></bar-label> | |||||
| <div style="margin-top: 20px;"> | |||||
| <span class="sta_iterm">统计周期:</span> | |||||
| <button type="button" class='btn' id ="yesterday" v-bind:class="{colorChange:1==dynamic}" @click="getAllProList('yesterday',1)">昨天</button> | |||||
| <button type="button" class='btn' id = "current_week" v-bind:class="{colorChange:2==dynamic}" @click="getAllProList('current_week',2)">本周</button> | |||||
| <button type="button" class='btn' id = "current_month" v-bind:class="{colorChange:3==dynamic}" @click="getAllProList('current_month',3)">本月</button> | |||||
| <button type="button" class='btn' id = "last_month" v-bind:class="{colorChange:4==dynamic}" @click="getAllProList('last_month',4)">上月</button> | |||||
| <button type="button" class='btn' id = "monthly" v-bind:class="{colorChange:5==dynamic}" @click="getAllProList('monthly',5)">近30天</button> | |||||
| <button type="button" class='btn' id = "current_year" v-bind:class="{colorChange:6==dynamic}" @click="getAllProList('current_year',6)">今年</button> | |||||
| <button type="button" class='btn' id = "all" v-bind:class="{colorChange:7==dynamic}" @click="getAllProList('all',7)">所有</button> | |||||
| <span style="margin-left: 20px;"> | |||||
| <el-date-picker | |||||
| v-model="value_time" | |||||
| prefix-icon="el-icon-time" | |||||
| @change="getAllProList('',0)" | |||||
| type="daterange" | |||||
| size='small' | |||||
| range-separator="至" | |||||
| start-placeholder="开始日期" | |||||
| end-placeholder="结束日期"> | |||||
| </el-date-picker> | |||||
| </span> | |||||
| <span style="float:right; margin-right: 20px;"> | |||||
| <div style="display:inline-block;margin-left: 20px; "> | |||||
| <i class="el-icon-download"></i> | |||||
| <span ><a>下载报告</a> </span> | |||||
| </div> | |||||
| <span style="display:inline-block;margin-left: 20px; "> | |||||
| <el-input size="small" placeholder="输入项目关键字搜索" v-model="search" class="input-with-select" @keyup.enter.native="searchName() "><i slot="suffix" class="el-input__icon el-icon-search"></i> | |||||
| </el-input> | |||||
| </span> | |||||
| </span> | |||||
| </div> | |||||
| <div style="margin-top: 30px;"> | |||||
| <el-table | |||||
| :data="tableData" | |||||
| style="width: 100%" | |||||
| :header-cell-style="tableHeaderStyle" | |||||
| :cell-style='cellStyle'> | |||||
| <el-table-column | |||||
| label="ID" | |||||
| align="center" | |||||
| prop="repo_id" | |||||
| stripe | |||||
| > | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| label="项目名称" | |||||
| width="125px" | |||||
| align="center" | |||||
| prop="name" | |||||
| style="color:#0366D6 100%;" | |||||
| > | |||||
| <template slot-scope="scope"> | |||||
| <a @click=goToDetailPage(scope.row.repo_id,scope.row.name)>{{scope.row.name}} </a> | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="isPrivate" | |||||
| label="私有" | |||||
| align="center"> | |||||
| <template slot-scope="scope"> | |||||
| {{scope.row.isPrivate|changeType}} | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="openi" | |||||
| label="OpenI指数" | |||||
| align="center"> | |||||
| <template slot-scope="scope"> | |||||
| {{scope.row.openi | rounding}} | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="view" | |||||
| label="浏览量" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="download" | |||||
| label="代码下载量" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="pr" | |||||
| label="PR" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="commit" | |||||
| label="Commit数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="watch" | |||||
| label="关注数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="star" | |||||
| label="点赞数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="fork" | |||||
| label="派生数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="issue" | |||||
| label="任务数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="issueClosed" | |||||
| label="已解决任务" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="contributor" | |||||
| label="贡献者数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| </div> | |||||
| <div style="margin-top:50px;text-align:center"> | |||||
| <el-pagination | |||||
| background | |||||
| @current-change="handleCurrentChange" | |||||
| :current-page="page" | |||||
| :page-size="pageSize" | |||||
| layout="prev, pager, next" | |||||
| :total="totalNum"> | |||||
| </el-pagination> | |||||
| </div> | |||||
| </div> | |||||
| <div id ="pro_detail" style="display:none;width: 100%;"> | |||||
| <div style="margin-top: 10px;"> | |||||
| <b class="pro_item">OpenI / {{this.pro_name}}</b> <span class="update_time">数据更新时间:{{tableDataIDTotal.lastUpdatedTime}}/{{tableDataIDTotal.recordBeginTime}}</span> | |||||
| </div> | |||||
| <div style="margin-top: 10px;"> | |||||
| 项目描述:{{tableDataIDTotal.description | discriptionFun}} | |||||
| </div> | |||||
| <div style="margin-top:20px"> | |||||
| <el-row > | |||||
| <el-col :span='4' class="items"> | |||||
| 项目创建时间 </br> | |||||
| {{tableDataIDTotal.creatTime}} | |||||
| </el-col> | |||||
| <el-col :span='4' class="items"> | |||||
| OPenI指数 </br> | |||||
| {{tableDataIDTotal.openi | rounding}} | |||||
| </el-col> | |||||
| <el-col :span='4' class="items"> | |||||
| 评论数 </br> | |||||
| {{tableDataIDTotal.comment}} | |||||
| </el-col> | |||||
| <el-col :span='4' class="items"> | |||||
| 浏览数 </br> | |||||
| {{tableDataIDTotal.view}} | |||||
| </el-col> | |||||
| <el-col :span='4' class="items"> | |||||
| 代码下载量 </br> | |||||
| {{tableDataIDTotal.download}} | |||||
| </el-col> | |||||
| <el-col :span='4' style="text-align: center;"> | |||||
| 任务完成比例 </br> | |||||
| {{tableDataIDTotal.issueClosedRatio}} | |||||
| </el-col> | |||||
| </el-row> | |||||
| </div> | |||||
| <div style="margin-top:30px;"> | |||||
| <el-row :gutter="20"> | |||||
| <el-col :span=18 > | |||||
| <div class="item_l" id="charts"> | |||||
| <div style="font-size:14px;color:#409eff;margin:20px 5px;">OpenI指数:{{tableDataIDTotal.openi | rounding}}</div> | |||||
| <div > | |||||
| <el-col :span='8' id="radar_openi" :style="{width: '400px', height: '300px'}"></el-col> | |||||
| <el-col :span='16' id="line_openi" :style="{width: '600px', height: '300px',float:'right'}"></el-col> | |||||
| </div> | |||||
| </div> | |||||
| </el-col> | |||||
| <el-col :span=6 > | |||||
| <div class="item_r"> | |||||
| <div style="font-size:14px;color:rgb(0,0,0);margin:20px 5px;">贡献者TOP10</div> | |||||
| <div> | |||||
| <el-table | |||||
| :data="tableDataContTop10" | |||||
| style="width: 100%" | |||||
| stripe | |||||
| :header-cell-style="tableHeaderStyle" | |||||
| > | |||||
| <el-table-column | |||||
| label="用户名" | |||||
| align="center" | |||||
| prop="user"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| label="身份" | |||||
| align="center" | |||||
| prop="mode"> | |||||
| <template slot-scope="scope"> | |||||
| {{scope.row.mode | showMode}} | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="PR" | |||||
| label="pr" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="commit" | |||||
| label="commit" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| </div> | |||||
| </div> | |||||
| </el-col> | |||||
| </el-row> | |||||
| </div> | |||||
| <div style="margin-top: 20px;"> | |||||
| <span class="sta_iterm">统计周期:</span> | |||||
| <button type="button" class='btn' id ="yesterday_pro" v-bind:class="{colorChange:1==dynamic_pro}" @click="getOneProList(pro_id,'yesterday',true,1),getOneProList(pro_id,'yesterday',false,1)">昨天</button> | |||||
| <button type="button" class='btn' id = "current_week_pro" v-bind:class="{colorChange:2==dynamic_pro}" @click="getOneProList(pro_id,'current_week',true,2),getOneProList(pro_id,'current_week',false,2)">本周</button> | |||||
| <button type="button" class='btn' id = "current_month_pro" v-bind:class="{colorChange:3==dynamic_pro}" @click="getOneProList(pro_id,'current_month',true,3),getOneProList(pro_id,'current_month',false,3)">本月</button> | |||||
| <button type="button" class='btn' id = "last_month_pro" v-bind:class="{colorChange:4==dynamic_pro}" @click="getOneProList(pro_id,'last_month',true,4),getOneProList(pro_id,'last_month',false,4)">上月</button> | |||||
| <button type="button" class='btn' id = "monthly_pro" v-bind:class="{colorChange:5==dynamic_pro}" @click="getOneProList(pro_id,'monthly',true,5),getOneProList(pro_id,'monthly',false,5)">近30天</button> | |||||
| <button type="button" class='btn' id = "current_year_pro" v-bind:class="{colorChange:6==dynamic}" @click="getOneProList(pro_id,'current_year',true,6),getOneProList(pro_id,'current_year',false,6)">今年</button> | |||||
| <button type="button" class='btn' id = "all_pro" v-bind:class="{colorChange:7==dynamic_pro}" @click="getOneProList(pro_id,'all',true,7),getOneProList(pro_id,'all',false,7)">所有</button> | |||||
| <span style="margin-left: 20px;"> | |||||
| <el-date-picker | |||||
| v-model="create_time_pro" | |||||
| prefix-icon="el-icon-time" | |||||
| @change="getOneProList(pro_id,'',true,0),getOneProList(pro_id,'',false,0)" | |||||
| type="daterange" | |||||
| size='small' | |||||
| range-separator="至" | |||||
| start-placeholder="开始日期" | |||||
| end-placeholder="结束日期"> | |||||
| </el-date-picker> | |||||
| </span> | |||||
| <span style="float:right; margin-right: 20px;"> | |||||
| <div style="display:inline-block;margin-left: 20px; "> | |||||
| <i class="el-icon-download"></i> | |||||
| <span ><a>下载报告</a> </span> | |||||
| </div> | |||||
| </span> | |||||
| </div> | |||||
| <div class="item_echart" id ='linecharts'> | |||||
| <div style="margin-top:10px;margin-left: 5px;"> | |||||
| <label for="label" @change='clickCheckBox'> | |||||
| <input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="浏览量"/>浏览量 | |||||
| <input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="下载量"/>下载量 | |||||
| <input type="checkbox" class="checkboxchart" name="checkboxchart" checked="checked" value="commit"/>commit | |||||
| </label> | |||||
| </div> | |||||
| <div id ="selectData" style="width: 1280px;height: 300px;"> | |||||
| </div> | |||||
| </div> | |||||
| <div style="margin-top: 30px;"> | |||||
| <el-table | |||||
| :data="tableDataID.slice((currentPage-1)*pageSize,currentPage*pageSize)" | |||||
| style="width: 100%" | |||||
| :header-cell-style="tableHeaderStyle" | |||||
| :cell-style='cellStyle'> | |||||
| <el-table-column | |||||
| label="日期" | |||||
| align="center" | |||||
| prop="date" | |||||
| stripe | |||||
| > | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| label="浏览量" | |||||
| align="center" | |||||
| prop="view"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="download" | |||||
| label="下载量" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="commit" | |||||
| label="commit" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| </div> | |||||
| <div style="margin-top:50px;text-align:center"> | |||||
| <el-pagination | |||||
| background | |||||
| @current-change="handleCurrentChangeID" | |||||
| :current-page="currentPage" | |||||
| :page-size="pageSize1" | |||||
| layout="prev, pager, next" | |||||
| :total="tableDataID.length"> | |||||
| </el-pagination> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| // import barLabel from './basic/barLabel.vue'; | |||||
| export default{ | |||||
| name:'ProAnalysis', | |||||
| components: { | |||||
| // barLabel, | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| recordBeginTime:'', | |||||
| lastUpdatedTime:'', | |||||
| page:1, | |||||
| pageSize:10, | |||||
| params:{type:'all',page:1,pagesize:10,beginTime:'',endTime:'',q:'',sort:'openi'}, | |||||
| tableData: [], | |||||
| totalPage:0, | |||||
| totalNum:0, | |||||
| pickerOptions: { | |||||
| }, | |||||
| value_time: '', | |||||
| search:'', | |||||
| dynamic:7, | |||||
| //单个项目参数 | |||||
| currentPage:1, | |||||
| pageSize1:10, | |||||
| paramsID:{type:'all' ,beginTime:'',endTime:'',openi:'false'}, | |||||
| tableDataIDTotal: [], | |||||
| tableDataID: [], | |||||
| tableDataIDOpenI:[], | |||||
| tableDataContTop10:[], | |||||
| create_time_pro: '', | |||||
| dynamic_pro:7, | |||||
| pro_name:'', | |||||
| pro_id:'', | |||||
| radarOpenI:'', | |||||
| echartsOITd:'', | |||||
| echartsSelectData:'', | |||||
| option:'', | |||||
| }; | |||||
| }, | |||||
| methods: { | |||||
| handleCurrentChange(val){ | |||||
| console.log(val) | |||||
| this.params.page = val | |||||
| switch(this.params.type){ | |||||
| case "yesterday":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,1) | |||||
| break | |||||
| } | |||||
| case "current_week":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,2) | |||||
| break | |||||
| } | |||||
| case "current_month":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,3) | |||||
| break | |||||
| } | |||||
| case "last_month":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,4) | |||||
| break | |||||
| } | |||||
| case "monthly":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,5) | |||||
| break | |||||
| } | |||||
| case "current_year":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,6) | |||||
| break | |||||
| } | |||||
| case "all":{ | |||||
| this.value_time='' | |||||
| this.getAllProList(this.params.type,7) | |||||
| break | |||||
| } | |||||
| case "":{ | |||||
| // this.value_time='' | |||||
| this.getAllProList(this.params.type,0) | |||||
| break | |||||
| } | |||||
| } | |||||
| }, | |||||
| formatDate(myyear,mymonth,myweekday) { | |||||
| // var myyear = this.date.getFullYear(); | |||||
| // var mymonth = this.date.getMonth() + 1; | |||||
| // var myweekday = this.date.getDate(); | |||||
| if (mymonth < 10) { | |||||
| mymonth = "0" + mymonth; | |||||
| } | |||||
| if (myweekday < 10) { | |||||
| myweekday = "0" + myweekday; | |||||
| } | |||||
| return (myyear + "-" + mymonth + "-" + myweekday); | |||||
| }, | |||||
| getAllProList(type_val,index){ | |||||
| console.log("类型:"+type_val) | |||||
| this.dynamic = index | |||||
| if (typeof type_val=="undefined" || type_val=="null" || type_val==""){ | |||||
| this.params.type='' | |||||
| this.params.beginTime=this.formatDate(this.value_time[0].getFullYear(),this.value_time[0].getMonth() + 1,this.value_time[0].getDate()) | |||||
| this.params.endTime=this.formatDate(this.value_time[1].getFullYear(),this.value_time[1].getMonth() + 1,this.value_time[1].getDate()) | |||||
| }else{ | |||||
| this.params.type=type_val | |||||
| this.params.beginTime='' | |||||
| this.params.endTime='' | |||||
| this.value_time=[] | |||||
| } | |||||
| this.$axios.get('../api/v1/projectboard/project',{ | |||||
| params:this.params | |||||
| }).then((res)=>{ | |||||
| this.recordBeginTime=res.data.recordBeginTime | |||||
| this.lastUpdatedTime=res.data.lastUpdatedTime | |||||
| this.tableData = res.data.pageRecords | |||||
| this.totalPage=res.data.totalPage | |||||
| this.totalNum = this.totalPage*this.params.pagesize | |||||
| console.log("this.totalPage:"+this.totalPage) | |||||
| }) | |||||
| }, | |||||
| searchName(){ | |||||
| this.params.q = this.search | |||||
| this.params.page = 1 | |||||
| this.getAllProList("all",7) | |||||
| }, | |||||
| goToDetailPage(pro_id,pro_name){ | |||||
| document.getElementById("pro_main").style.display="none"; | |||||
| document.getElementById("pro_detail").style.display="block"; | |||||
| console.log(pro_id) | |||||
| console.log(pro_name) | |||||
| this.pro_name=pro_name; | |||||
| this.pro_id=pro_id; | |||||
| this.getOneProData(pro_id); | |||||
| this.getOneProList(pro_id,"monthly",true,5); | |||||
| this.getOneProList(pro_id,"monthly",false,5); | |||||
| }, | |||||
| tableHeaderStyle({row,column,rowIndex,columnIndex}){ | |||||
| if(rowIndex===0){ | |||||
| return 'background:#f5f5f6;color:#606266' | |||||
| } | |||||
| }, | |||||
| cellStyle({row,column,rowIndex,columnIndex}){ | |||||
| if(rowIndex%2 === 1){ | |||||
| return 'background:#f5f5f6;color:#606266' | |||||
| } | |||||
| }, | |||||
| handleCurrentChangeID(currentPage){ | |||||
| this.currentPage = currentPage; | |||||
| }, | |||||
| getOneProData(pro_id){ | |||||
| this.$axios.get('../api/v1/projectboard/project/'+pro_id,{ | |||||
| }).then((res)=>{ | |||||
| this.tableDataIDTotal = res.data | |||||
| this.tableDataContTop10=res.data.top10 | |||||
| // this.drawLine() | |||||
| this.drawRadarOpenI() | |||||
| }) | |||||
| }, | |||||
| getOneProList(pro_id,type_val,bool_val,index){ | |||||
| this.dynamic_pro=index | |||||
| console.log("日期类型:"+type_val) | |||||
| if (typeof type_val=="undefined" || type_val=="null" || type_val==""){ | |||||
| this.paramsID.type='' | |||||
| this.paramsID.beginTime= this.formatDate(this.create_time_pro[0].getFullYear(),this.create_time_pro[0].getMonth() + 1,this.create_time_pro[0].getDate()) | |||||
| this.paramsID.endTime=this.formatDate(this.create_time_pro[1].getFullYear(),this.create_time_pro[1].getMonth() + 1,this.create_time_pro[1].getDate()) | |||||
| }else{ | |||||
| this.create_time_pro=[] | |||||
| this.paramsID.type=type_val | |||||
| this.paramsID.beginTime='' | |||||
| this.paramsID.endTime='' | |||||
| } | |||||
| this.paramsID.openi=bool_val | |||||
| this.$axios.get('../api/v1/projectboard/project/'+pro_id+"/period",{ | |||||
| params:this.paramsID | |||||
| }).then((res)=>{ | |||||
| if (bool_val){ | |||||
| this.tableDataIDOpenI = res.data | |||||
| this.drawOpenItrend() | |||||
| }else{ | |||||
| this.tableDataID = res.data | |||||
| this.drawSelectData() | |||||
| } | |||||
| }) | |||||
| }, | |||||
| drawRadarOpenI(){ | |||||
| var ydata = [this.roundingF(this.tableDataIDTotal.impact),this.roundingF(this.tableDataIDTotal.completeness),this.roundingF(this.tableDataIDTotal.liveness),this.tableDataIDTotal.projectHealth,this.roundingF(this.tableDataIDTotal.teamHealth),this.roundingF(this.tableDataIDTotal.growth)] | |||||
| console.log("ydata:",ydata) | |||||
| var i = -1; | |||||
| var option = { | |||||
| titile:{ | |||||
| text:"" | |||||
| }, | |||||
| tooltip: { | |||||
| trigger: 'item', | |||||
| backgroundColor:'rgba(255,255,255,0.8)', | |||||
| color:'black', | |||||
| borderWidth:'1', | |||||
| borderColor:'gray', | |||||
| textStyle:{ | |||||
| color:'black' | |||||
| }, | |||||
| position: 'right' | |||||
| },//提示层 | |||||
| legend: { | |||||
| data: ['name1'] | |||||
| }, | |||||
| radar: { | |||||
| name: { | |||||
| textStyle: { | |||||
| color: 'rgb(0,0,0)', //字体颜色 | |||||
| borderRadius: 3, //圆角 | |||||
| padding: [3, 5] //padding | |||||
| } | |||||
| }, | |||||
| slpitNumber:5, | |||||
| center: ['50%', '50%'], | |||||
| indicator: [{ | |||||
| name: '社区影响力', | |||||
| max: 100 | |||||
| }, | |||||
| { | |||||
| name: '项目成熟度', | |||||
| max: 100 | |||||
| }, | |||||
| { | |||||
| name: '开发活跃度', | |||||
| max: 100 | |||||
| }, | |||||
| { | |||||
| name: '项目健康度', | |||||
| max: 100 | |||||
| }, | |||||
| { | |||||
| name: '团队健康度', | |||||
| max: 100 | |||||
| }, | |||||
| { | |||||
| name: '项目发展趋势', | |||||
| max: 100 | |||||
| } | |||||
| ], | |||||
| }, | |||||
| series: [{ | |||||
| type: 'radar', | |||||
| lineStyle:{ | |||||
| width:2, | |||||
| color: 'rgb(0,255,0)' | |||||
| }, | |||||
| data: [{ | |||||
| value: ydata, | |||||
| }] | |||||
| }] | |||||
| } | |||||
| this.radarOpenI.setOption(option) | |||||
| }, | |||||
| drawOpenItrend(){ | |||||
| var xdata_openI=[] | |||||
| var ydata_openI=[] | |||||
| for(var i =0;i<this.tableDataIDOpenI.length;i++){ | |||||
| xdata_openI.push(this.tableDataIDOpenI[this.tableDataIDOpenI.length-1-i].date); | |||||
| ydata_openI.push(this.roundingF(this.tableDataIDOpenI[i].openi)) | |||||
| } | |||||
| console.log("ydata_openI:"+ydata_openI) | |||||
| console.log(xdata_openI) | |||||
| var option = { | |||||
| title : { | |||||
| text: 'OpenI指数趋势', | |||||
| textStyle: { | |||||
| fontSize: 12, | |||||
| }, | |||||
| left:'center', | |||||
| top:'bottom', | |||||
| subtext: '', | |||||
| }, | |||||
| tooltip : { | |||||
| trigger: 'axis', | |||||
| backgroundColor:'rgba(255,255,255,0.8)', | |||||
| color:'black', | |||||
| borderWidth:'1', | |||||
| borderColor:'gray', | |||||
| textStyle:{ | |||||
| color:'black' | |||||
| }, | |||||
| }, | |||||
| legend: { | |||||
| orient: 'vertical', | |||||
| top:'top', | |||||
| }, | |||||
| // calculable : true, | |||||
| xAxis : [ | |||||
| { | |||||
| type : 'category', | |||||
| boundaryGap: false, | |||||
| data : xdata_openI, | |||||
| } | |||||
| ], | |||||
| yAxis : [ | |||||
| { | |||||
| type : 'value', | |||||
| } | |||||
| ], | |||||
| series : [ | |||||
| { | |||||
| data: ydata_openI, | |||||
| type: 'line', | |||||
| areaStyle: { | |||||
| color:'red', | |||||
| opacity: 0.3, | |||||
| origin:"start" | |||||
| }, | |||||
| // lineStyle:{ | |||||
| // width:2, | |||||
| // color: '#409effd6' | |||||
| // }, | |||||
| } | |||||
| ] | |||||
| }; | |||||
| this.echartsOITd.setOption(option) | |||||
| }, | |||||
| drawSelectData(){ | |||||
| var xdata=[] | |||||
| var ydata_view=[] | |||||
| var ydata_download=[] | |||||
| var ydata_commit=[] | |||||
| for(var i =0;i<this.tableDataIDOpenI.length;i++){ | |||||
| xdata.push(this.tableDataIDOpenI[this.tableDataID.length-1-i].date); | |||||
| ydata_view.push(this.roundingF(this.tableDataID[i].view)) | |||||
| ydata_download.push(this.roundingF(this.tableDataID[i].download)) | |||||
| ydata_commit.push(this.roundingF(this.tableDataID[i].commit)) | |||||
| } | |||||
| console.log("ydata_openI:"+ydata_download) | |||||
| console.log(xdata) | |||||
| this.option = { | |||||
| title : { | |||||
| text: '', | |||||
| textStyle: { | |||||
| fontSize: 12, | |||||
| }, | |||||
| left:'center', | |||||
| top:'bottom', | |||||
| subtext: '', | |||||
| }, | |||||
| tooltip : { | |||||
| trigger: 'axis', | |||||
| backgroundColor:'rgba(255,255,255,0.8)', | |||||
| color:'black', | |||||
| borderWidth:'1', | |||||
| borderColor:'gray', | |||||
| textStyle:{ | |||||
| color:'black' | |||||
| }, | |||||
| }, | |||||
| legend: { | |||||
| data:['浏览量','下载量','commit'], | |||||
| // orient: 'vertical', | |||||
| // top:'top', | |||||
| }, | |||||
| toolbox: { | |||||
| show : false, | |||||
| feature : { | |||||
| mark : {show: true}, | |||||
| dataView : {show: false, readOnly: false}, | |||||
| magicType : {show: true, type: ['line', 'bar']}, | |||||
| restore : {show: false}, | |||||
| saveAsImage : {show: true} | |||||
| } | |||||
| }, | |||||
| calculable : true, | |||||
| xAxis : [ | |||||
| { | |||||
| type : 'category', | |||||
| data : xdata, | |||||
| } | |||||
| ], | |||||
| yAxis : [ | |||||
| { | |||||
| type : 'value', | |||||
| } | |||||
| ], | |||||
| series : [ | |||||
| { name:"浏览量", | |||||
| data: ydata_view, | |||||
| type: 'line', | |||||
| areaStyle: {}, | |||||
| }, | |||||
| { | |||||
| name:"下载量", | |||||
| data: ydata_download, | |||||
| type: 'line', | |||||
| areaStyle: {}, | |||||
| }, | |||||
| { | |||||
| name:"commit", | |||||
| data: ydata_commit, | |||||
| type: 'line', | |||||
| areaStyle: {}, | |||||
| }, | |||||
| ] | |||||
| }; | |||||
| this.echartsSelectData.setOption(this.option) | |||||
| // // 使用刚指定的选择项数据显示图表。 | |||||
| // var selectArr = this.echartsSelectData.getOption().legend[0].data;//legend所有值 | |||||
| // var checkboxs=document.getElementsByName('checkboxchart'); | |||||
| // $(".checkboxchart").click(function(){ | |||||
| // var obj = {}; | |||||
| // for(var i=0; i<checkboxs.length; i++){ | |||||
| // if(checkboxs[i].checked){ | |||||
| // obj[selectArr[i]] = true; | |||||
| // }else{ | |||||
| // obj[selectArr[i]] = false; | |||||
| // } | |||||
| // } | |||||
| // option.legend.selected = obj; | |||||
| // this.echartsSelectData.setOption(option); | |||||
| // }); | |||||
| }, | |||||
| roundingF(value){ | |||||
| return Number(value).toFixed(2) | |||||
| }, | |||||
| clickCheckBox(){ | |||||
| // 使用刚指定的选择项数据显示图表。 | |||||
| var selectArr = this.echartsSelectData.getOption().legend[0].data;//legend所有值 | |||||
| var checkboxs=document.getElementsByName('checkboxchart'); | |||||
| // $(".checkboxchart").click(function(){ | |||||
| var obj = {}; | |||||
| for(var i=0; i<checkboxs.length; i++){ | |||||
| if(checkboxs[i].checked){ | |||||
| obj[selectArr[i]] = true; | |||||
| }else{ | |||||
| obj[selectArr[i]] = false; | |||||
| } | |||||
| } | |||||
| this.option.legend.selected = obj; | |||||
| this.echartsSelectData.setOption(this.option); | |||||
| // }); | |||||
| } | |||||
| }, | |||||
| filters:{ | |||||
| rounding (value) { | |||||
| return Number(value).toFixed(2) | |||||
| }, | |||||
| changeType(value){ | |||||
| if(value=='false'){ | |||||
| return "否" | |||||
| }else{ | |||||
| return "是" | |||||
| } | |||||
| }, | |||||
| discriptionFun(value){ | |||||
| if(value==''){ | |||||
| return "暂无描述" | |||||
| } | |||||
| }, | |||||
| showMode(value){ | |||||
| if(value==1){ | |||||
| return "可读权限" | |||||
| }else if(value==2){ | |||||
| return "可写权限" | |||||
| }else if(value==3){ | |||||
| return "管理员" | |||||
| }else if(value==4){ | |||||
| return "所有者" | |||||
| }else{ | |||||
| return "未定义" | |||||
| } | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| // document.getElementById("all").style.outline="none" | |||||
| // document.getElementById("all").focus() | |||||
| this.getAllProList("all",7) | |||||
| console.log("id:"+this.pro_id); | |||||
| // document.getElementById('radar_openi').style.width = document.getElementById('charts').offsetWidth*0.4+'px' | |||||
| // document.getElementById('line_openi').style.width = document.getElementById('charts').offsetWidth*0.6+'px' | |||||
| // document.getElementById('selectData').style.width = document.getElementById('linecharts').offsetWidth+'px' | |||||
| this.radarOpenI = this.$echarts.init(document.getElementById('radar_openi')) | |||||
| this.echartsOITd = this.$echarts.init(document.getElementById('line_openi')) | |||||
| this.echartsSelectData = this.$echarts.init(document.getElementById('selectData')) | |||||
| // window.onresize=function(){ | |||||
| // this.radarOpenI.resize(); | |||||
| // this.echartsOITd.resize(); | |||||
| // this.echartsSelectData.resize(); | |||||
| // } | |||||
| // console.log("this.radarOpenI:"+this.radarOpenI) | |||||
| }, | |||||
| created() { | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .pro_item{ | |||||
| font-size: 16px; | |||||
| color: rgba(16, 16, 16, 100); | |||||
| font-family: SourceHanSansSC-bold; | |||||
| } | |||||
| .sta_item{ | |||||
| font-size: 14px; | |||||
| color: rgb(0 0 0); | |||||
| font-family: SourceHanSansSC-bold; | |||||
| } | |||||
| .update_time{ | |||||
| line-height: 17px; | |||||
| font-size: 12px; | |||||
| color:rgba(187, 187, 187, 100); | |||||
| margin-left: 10px; | |||||
| } | |||||
| .btn{ | |||||
| line-height: 1.5; | |||||
| margin: -3px; | |||||
| border: 1px solid #409eff; | |||||
| background: #FFFF; | |||||
| color: #409eff; | |||||
| width: 60px; | |||||
| height: 30px; | |||||
| border-radius:4px ; | |||||
| } | |||||
| .btn:focus, | |||||
| .btn:active{ | |||||
| background-color:#409effd6 ; | |||||
| } | |||||
| /deep/ .el-date-picker { | |||||
| width: 200px; | |||||
| } | |||||
| .colorChange { | |||||
| background-color: #409effd6; | |||||
| } | |||||
| .items{ | |||||
| text-align: center; | |||||
| border-right:2px solid rgba(219, 219, 219, 100); | |||||
| } | |||||
| .item_l{ | |||||
| margin-right: 5px; | |||||
| border:1px solid rgba(219, 219, 219, 100); | |||||
| height: 370px; | |||||
| width: 100%; | |||||
| } | |||||
| .item_r{ | |||||
| margin-right:5px; | |||||
| border:1px solid rgba(219, 219, 219, 100); | |||||
| height: 370px; | |||||
| } | |||||
| .item_echart{ | |||||
| margin-top: 10px; | |||||
| margin-right: 5px; | |||||
| border:1px solid rgba(219, 219, 219, 100); | |||||
| height: 350px; | |||||
| width: 100%; | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,415 @@ | |||||
| <template> | |||||
| <div> | |||||
| <div style="margin-top: 10px;"> | |||||
| <b class="pro_item">用户分析</b> <span class="update_time">数据更新时间:{{lastUpdatedTime}}/{{recordBeginTime}}</span> | |||||
| </div> | |||||
| <div style="margin-top: 20px;"> | |||||
| <span class="sta_iterm">统计周期:</span> | |||||
| <button type="button" class='btn' id ="yesterday_usr" v-bind:class="{colorChange:1==dynamic}" @click="getUserList('yesterday_usr',1)">昨天</button> | |||||
| <button type="button" class='btn' id = "current_week_usr" v-bind:class="{colorChange:2==dynamic}" @click="getUserList('current_week_usr',2)">本周</button> | |||||
| <button type="button" class='btn' id = "current_month_usr" v-bind:class="{colorChange:3==dynamic}" @click="getUserList('current_month_usr',3)">本月</button> | |||||
| <button type="button" class='btn' id = "last_month_usr" v-bind:class="{colorChange:4==dynamic}" @click="getUserList('last_month_usr',4)">上月</button> | |||||
| <button type="button" class='btn' id = "monthly_usr" v-bind:class="{colorChange:5==dynamic}" @click="getUserList('monthly_usr',5)">近30天</button> | |||||
| <button type="button" class='btn' id = "current_year_usr" v-bind:class="{colorChange:6==dynamic}" @click="getUserList('current_year_usr',6)">今年</button> | |||||
| <button type="button" class='btn' id = "all_usr" v-bind:class="{colorChange:7==dynamic}" @click="getUserList('all_usr',7)">所有</button> | |||||
| <span style="margin-left: 20px;"> | |||||
| <el-date-picker | |||||
| v-model="value_time" | |||||
| prefix-icon="el-icon-time" | |||||
| @change="getUserList('',0)" | |||||
| type="daterange" | |||||
| size='small' | |||||
| unlink-panels | |||||
| range-separator="至" | |||||
| start-placeholder="开始日期" | |||||
| end-placeholder="结束日期"> | |||||
| </el-date-picker> | |||||
| </span> | |||||
| <span style="float:right; margin-right: 20px;"> | |||||
| <a style="display:inline-block;margin-left: 20px; " id = 'download'> | |||||
| <i class="el-icon-download"></i> | |||||
| <span ><a @click="exportData()">下载报告</a> </span> | |||||
| </a> | |||||
| <span style="display:inline-block;margin-left: 20px; "> | |||||
| <el-input size="small" placeholder="输入用户名搜索" v-model="search" class="input-with-select" @keyup.enter.native="searchName() "><i slot="suffix" class="el-input__icon el-icon-search"></i> | |||||
| </el-input> | |||||
| </span> | |||||
| </span> | |||||
| </div> | |||||
| <div style="margin-top: 30px;"> | |||||
| <el-table | |||||
| :data="tableData.slice((currentPage-1)*pageSize,currentPage*pageSize)" | |||||
| style="width: 100%" | |||||
| :header-cell-style="tableHeaderStyle" | |||||
| :cell-style='cellStyle'> | |||||
| <el-table-column | |||||
| label="ID" | |||||
| prop="ID" | |||||
| align="center" | |||||
| stripe | |||||
| > | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| label="用户名" | |||||
| align="center" | |||||
| prop="Name" | |||||
| width="100px"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="CodeMergeCount" | |||||
| label="PR数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="CommitCount" | |||||
| label="commit数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="IssueCount" | |||||
| label="提出任务数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="CommentCount" | |||||
| label="评论数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="FocusRepoCount" | |||||
| label="关注项目数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="StarRepoCount" | |||||
| label="点赞项目数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="LoginCount" | |||||
| label="登录次数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="WatchedCount" | |||||
| label="关注者数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="CommitCodeSize" | |||||
| label="commit代码行数" | |||||
| width="115px" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="SolveIssueCount" | |||||
| label="已解决任务数" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="EncyclopediasCount" | |||||
| label="百科页面贡献次数" | |||||
| width="130px" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="CreateRepoCount" | |||||
| label="创建项目" | |||||
| align="center"> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="RegistDate" | |||||
| label="用户注册时间" | |||||
| width="120px" | |||||
| align="center"> | |||||
| <template slot-scope="scope"> | |||||
| {{scope.row.RegistDate | transformTimestamp}} | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| prop="CountDate" | |||||
| label="系统统计时间" | |||||
| width="120px" | |||||
| align="center"> | |||||
| <template slot-scope="scope"> | |||||
| {{scope.row.CountDate | transformTimestamp}} | |||||
| </template> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| </div> | |||||
| <div style="margin-top:50px;text-align:center"> | |||||
| <el-pagination | |||||
| background | |||||
| @current-change="handleCurrentChange" | |||||
| :current-page="currentPage" | |||||
| :page-size="pageSize" | |||||
| layout="prev, pager, next" | |||||
| :total="tableData.length"> | |||||
| </el-pagination> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import { export2Excel } from '../excel/util.js' | |||||
| export default{ | |||||
| name:'UserAnalysis', | |||||
| data() { | |||||
| return { | |||||
| type_val:'', | |||||
| recordBeginTime:'', | |||||
| lastUpdatedTime:'', | |||||
| currentPage:1, | |||||
| pageSize:10, | |||||
| params:{startDate:'',endDate:''}, | |||||
| tableData: [], | |||||
| pickerOptions: { | |||||
| }, | |||||
| value_time: '', | |||||
| search:'', | |||||
| data:'', | |||||
| columns: [{title: 'ID',key: 'ID'},{title: '用户名',key: 'Name'},{title: 'PR数',key: 'CommitCount'},{title: '提出任务数',key: 'IssueCount'},{title: '评论数',key: 'CommentCount'},{title: '关注项目数',key: 'FocusRepoCount'},{title: '点赞项目数',key: 'StarRepoCount'},{title: '登录次数',key: 'LoginCount'},{title:'关注者数',key:'WatchedCount'},{title:'commit代码行数',key:'CommitCodeSize'},{title:'已解决任务数',key:'SolveIssueCount'},{title:'百科页面贡献次数',key:'EncyclopediasCount'},{title:'创建项目',key:'CreateRepoCount'},{title:'加入时间',key:'RegistDate'}], | |||||
| blob:'', | |||||
| fileName:'', | |||||
| dynamic:7, | |||||
| params_pro:{type:'all',page:1,pagesize:10,beginTime:'',endTime:'',q:'',sort:'openi'}, | |||||
| }; | |||||
| }, | |||||
| methods: { | |||||
| exportData(){ | |||||
| export2Excel(this.columns,this.tableData,"测试下载excel") | |||||
| }, | |||||
| handleCurrentChange(currentPage){ | |||||
| this.currentPage = currentPage; | |||||
| }, | |||||
| formatDate(myyear,mymonth,myweekday) { | |||||
| // var myyear = this.date.getFullYear(); | |||||
| // var mymonth = this.date.getMonth() + 1; | |||||
| // var myweekday = this.date.getDate(); | |||||
| if (mymonth < 10) { | |||||
| mymonth = "0" + mymonth; | |||||
| } | |||||
| if (myweekday < 10) { | |||||
| myweekday = "0" + myweekday; | |||||
| } | |||||
| return (myyear + "-" + mymonth + "-" + myweekday); | |||||
| }, | |||||
| // 获得某月的天数 | |||||
| getMonthDays(nowYear,month){ | |||||
| let monthStartDate = new Date(nowYear, month, 1); | |||||
| let monthEndDate = new Date(nowYear, month + 1, 1); | |||||
| let days = (monthEndDate - monthStartDate)/(1000 * 60 * 60 * 24); | |||||
| return days; | |||||
| }, | |||||
| getUserList(type_val,index){ | |||||
| this.dynamic = index; | |||||
| console.log("dj:"+type_val) | |||||
| var now = new Date(); // 当前日期 | |||||
| var nowDayOfWeek = now.getDay(); // 今天本周的第几天 | |||||
| var nowDay = now.getDate(); // 当前日 | |||||
| var nowMonth = now.getMonth(); // 当前月 | |||||
| var nowYear = now.getFullYear(); // 当前年 | |||||
| var today = this.formatDate(nowYear,nowMonth+1,nowDay); | |||||
| let lastMonthDate = new Date(); // 上月日期 | |||||
| lastMonthDate.setDate(1); | |||||
| lastMonthDate.setMonth(lastMonthDate.getMonth()-1); | |||||
| let lastYear = lastMonthDate.getYear(); | |||||
| let lastMonth = lastMonthDate.getMonth(); | |||||
| if (typeof type_val=="undefined" || type_val=="null" || type_val==""){ | |||||
| this.params.startDate= this.formatDate(this.value_time[0].getFullYear(),this.value_time[0].getMonth() + 1,this.value_time[0].getDate()); | |||||
| this.params.endDate = this.formatDate(this.value_time[1].getFullYear(),this.value_time[1].getMonth() + 1,this.value_time[1].getDate()); | |||||
| }else{ | |||||
| switch(type_val){ | |||||
| case "yesterday_usr":{ | |||||
| var now = new Date(); | |||||
| var tmp = new Date(now.setTime(now.getTime()-24*60*60*1000)); | |||||
| var yesterday = this.formatDate(tmp.getFullYear(),tmp.getMonth()+1,tmp.getDate()); | |||||
| this.params.startDate = yesterday | |||||
| this.params.endDate = yesterday | |||||
| this.value_time=[] | |||||
| document.getElementById("yesterday_usr").style.backgroundColor="409effd6" | |||||
| document.getElementById("current_week_usr") | |||||
| break | |||||
| } | |||||
| case "current_week_usr":{ | |||||
| var now = new Date(); // 当前日期 | |||||
| var nowDayOfWeek = now.getDay(); // 今天本周的第几天 | |||||
| var day = nowDayOfWeek || 7; | |||||
| this.params.startDate = this.formatDate(now.getFullYear(), nowMonth+1, nowDay + 1 - day); | |||||
| this.params.endDate = today | |||||
| this.value_time=[] | |||||
| break | |||||
| } | |||||
| case "current_month_usr":{ | |||||
| this.params.startDate = this.formatDate(nowYear,nowMonth+1,1); | |||||
| this.params.endDate = today | |||||
| this.value_time=[] | |||||
| break | |||||
| } | |||||
| case "last_month_usr":{ | |||||
| this.params.startDate=this.formatDate(nowYear, lastMonth+1, 1); | |||||
| this.params.endDate=this.formatDate(nowYear, lastMonth+1, this.getMonthDays(nowYear,lastMonth)); | |||||
| this.value_time=[] | |||||
| break | |||||
| } | |||||
| case "monthly_usr":{ | |||||
| var temp=new Date(now - 1000 * 60 * 60 * 24 * 30) | |||||
| this.params.startDate = this.formatDate(temp.getFullYear(),temp.getMonth()+1,temp.getDate()); | |||||
| this.params.endDate = today | |||||
| this.value_time=[] | |||||
| break | |||||
| } | |||||
| case "current_year_usr":{ | |||||
| this.params.startDate = this.formatDate(now.getFullYear(), 1, 1); | |||||
| this.params.endDate = today | |||||
| this.value_time=[] | |||||
| break | |||||
| } | |||||
| case "all_usr":{ | |||||
| console.log("e:"+today) | |||||
| this.params.startDate = this.formatDate(2000, 1, 1); //this.recordBeginTime// | |||||
| this.params.endDate = today | |||||
| this.value_time=[] | |||||
| break | |||||
| } | |||||
| } | |||||
| }; | |||||
| this.$axios.get('../tool/query_user_static',{ | |||||
| params:this.params | |||||
| }).then((res)=>{ | |||||
| this.currentPage = 1 | |||||
| this.tableData = res.data | |||||
| }) | |||||
| this.$axios.get('../api/v1/projectboard/project',{ | |||||
| params:this.params_pro | |||||
| }).then((res)=>{ | |||||
| this.recordBeginTime=res.data.recordBeginTime | |||||
| this.lastUpdatedTime=res.data.lastUpdatedTime | |||||
| }) | |||||
| }, | |||||
| searchName(){ | |||||
| // this.params.q = this.search | |||||
| // this.params.page = 1 | |||||
| // this.getUserList("all_usr") | |||||
| var search = this.search; | |||||
| this.getUserList("all_usr",7) | |||||
| this.tableData = this.tableData.filter(data => !search || data.Name.toLowerCase().includes(search.toLowerCase())) | |||||
| }, | |||||
| goToDetailPage(pro_id,pro_name){ | |||||
| sessionStorage.setItem("pro_id",pro_id); | |||||
| sessionStorage.setItem("pro_name",pro_name); | |||||
| document.getElementById("pro_main").style.display="none"; | |||||
| document.getElementById("pro_detail").style.display="block"; | |||||
| }, | |||||
| tableHeaderStyle({row,column,rowIndex,columnIndex}){ | |||||
| if(rowIndex===0){ | |||||
| return 'background:#f5f5f6;color:#606266' | |||||
| } | |||||
| }, | |||||
| cellStyle({row,column,rowIndex,columnIndex}){ | |||||
| if(rowIndex%2 === 1){ | |||||
| return 'background:#f5f5f6;color:#606266' | |||||
| } | |||||
| }, | |||||
| }, | |||||
| filters:{ | |||||
| transformTimestamp(timestamp){ | |||||
| console.log("timestamp",timestamp) | |||||
| let a = new Date(timestamp*1000); | |||||
| const date = new Date(a); | |||||
| const Y = date.getFullYear() + '/'; | |||||
| const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '/'; | |||||
| const D = (date.getDate() < 10 ? '0'+date.getDate() : date.getDate()) + ' '; | |||||
| const h = (date.getHours() < 10 ? '0'+date.getHours() : date.getHours()) + ':'; | |||||
| const m = (date.getMinutes() <10 ? '0'+date.getMinutes() : date.getMinutes());// + ':' ; | |||||
| // const s = (date.getSeconds() <10 ? '0'+date.getSeconds() : date.getSeconds()) ; // 秒 | |||||
| const dateString = Y + M + D + h + m ;//+ s; | |||||
| console.log('dateString', dateString); // > dateString 2021-07-06 14:23 | |||||
| return dateString; | |||||
| }, | |||||
| // transformTimestamp(timestamp){ | |||||
| // var dateString= new Date(timestamp); | |||||
| // return dateString.toLocaleDateString().replace(/\//g, "-") + " " + dateString.toTimeString().substr(0, 8); | |||||
| // }, | |||||
| }, | |||||
| mounted() { | |||||
| document.getElementById("all_usr").style.outline="none" | |||||
| document.getElementById("all_usr").focus() | |||||
| this.getUserList("all_usr",7) | |||||
| }, | |||||
| created() { | |||||
| }, | |||||
| watch:{ | |||||
| search(val){ | |||||
| if(!val){ | |||||
| this.getUserList("all_usr",7) | |||||
| } | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .pro_item{ | |||||
| font-size: 16px; | |||||
| color: rgba(16, 16, 16, 100); | |||||
| font-family: SourceHanSansSC-bold; | |||||
| } | |||||
| .sta_item{ | |||||
| font-size: 14px; | |||||
| color: rgb(0 0 0); | |||||
| font-family: SourceHanSansSC-bold; | |||||
| } | |||||
| .update_time{ | |||||
| line-height: 17px; | |||||
| font-size: 12px; | |||||
| color:rgba(187, 187, 187, 100); | |||||
| margin-left: 10px; | |||||
| } | |||||
| .btn{ | |||||
| line-height: 1.5; | |||||
| margin: -3px; | |||||
| border: 1px solid #409effd6; | |||||
| background: #FFFF; | |||||
| color: #409eff; | |||||
| width: 60px; | |||||
| height: 30px; | |||||
| border-radius:4px ; | |||||
| } | |||||
| .btn:focus, | |||||
| .btn:active{ | |||||
| background-color:#409effd6 ; | |||||
| } | |||||
| /deep/ .el-date-picker { | |||||
| width: 200px; | |||||
| } | |||||
| /deep/ .el-table { | |||||
| font-size: 12px; | |||||
| } | |||||
| .colorChange { | |||||
| background-color: #409effd6; | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,179 @@ | |||||
| /* eslint-disable */ | |||||
| /* Blob.js | |||||
| * A Blob implementation. | |||||
| * 2014-05-27 | |||||
| * | |||||
| * By Eli Grey, http://eligrey.com | |||||
| * By Devin Samarin, https://github.com/eboyjr | |||||
| * License: X11/MIT | |||||
| * See LICENSE.md | |||||
| */ | |||||
| /*global self, unescape */ | |||||
| /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, | |||||
| plusplus: true */ | |||||
| /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ | |||||
| (function (view) { | |||||
| "use strict"; | |||||
| view.URL = view.URL || view.webkitURL; | |||||
| if (view.Blob && view.URL) { | |||||
| try { | |||||
| new Blob; | |||||
| return; | |||||
| } catch (e) {} | |||||
| } | |||||
| // Internally we use a BlobBuilder implementation to base Blob off of | |||||
| // in order to support older browsers that only have BlobBuilder | |||||
| var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { | |||||
| var | |||||
| get_class = function(object) { | |||||
| return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; | |||||
| } | |||||
| , FakeBlobBuilder = function BlobBuilder() { | |||||
| this.data = []; | |||||
| } | |||||
| , FakeBlob = function Blob(data, type, encoding) { | |||||
| this.data = data; | |||||
| this.size = data.length; | |||||
| this.type = type; | |||||
| this.encoding = encoding; | |||||
| } | |||||
| , FBB_proto = FakeBlobBuilder.prototype | |||||
| , FB_proto = FakeBlob.prototype | |||||
| , FileReaderSync = view.FileReaderSync | |||||
| , FileException = function(type) { | |||||
| this.code = this[this.name = type]; | |||||
| } | |||||
| , file_ex_codes = ( | |||||
| "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " | |||||
| + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" | |||||
| ).split(" ") | |||||
| , file_ex_code = file_ex_codes.length | |||||
| , real_URL = view.URL || view.webkitURL || view | |||||
| , real_create_object_URL = real_URL.createObjectURL | |||||
| , real_revoke_object_URL = real_URL.revokeObjectURL | |||||
| , URL = real_URL | |||||
| , btoa = view.btoa | |||||
| , atob = view.atob | |||||
| , ArrayBuffer = view.ArrayBuffer | |||||
| , Uint8Array = view.Uint8Array | |||||
| ; | |||||
| FakeBlob.fake = FB_proto.fake = true; | |||||
| while (file_ex_code--) { | |||||
| FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; | |||||
| } | |||||
| if (!real_URL.createObjectURL) { | |||||
| URL = view.URL = {}; | |||||
| } | |||||
| URL.createObjectURL = function(blob) { | |||||
| var | |||||
| type = blob.type | |||||
| , data_URI_header | |||||
| ; | |||||
| if (type === null) { | |||||
| type = "application/octet-stream"; | |||||
| } | |||||
| if (blob instanceof FakeBlob) { | |||||
| data_URI_header = "data:" + type; | |||||
| if (blob.encoding === "base64") { | |||||
| return data_URI_header + ";base64," + blob.data; | |||||
| } else if (blob.encoding === "URI") { | |||||
| return data_URI_header + "," + decodeURIComponent(blob.data); | |||||
| } if (btoa) { | |||||
| return data_URI_header + ";base64," + btoa(blob.data); | |||||
| } else { | |||||
| return data_URI_header + "," + encodeURIComponent(blob.data); | |||||
| } | |||||
| } else if (real_create_object_URL) { | |||||
| return real_create_object_URL.call(real_URL, blob); | |||||
| } | |||||
| }; | |||||
| URL.revokeObjectURL = function(object_URL) { | |||||
| if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { | |||||
| real_revoke_object_URL.call(real_URL, object_URL); | |||||
| } | |||||
| }; | |||||
| FBB_proto.append = function(data/*, endings*/) { | |||||
| var bb = this.data; | |||||
| // decode data to a binary string | |||||
| if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { | |||||
| var | |||||
| str = "" | |||||
| , buf = new Uint8Array(data) | |||||
| , i = 0 | |||||
| , buf_len = buf.length | |||||
| ; | |||||
| for (; i < buf_len; i++) { | |||||
| str += String.fromCharCode(buf[i]); | |||||
| } | |||||
| bb.push(str); | |||||
| } else if (get_class(data) === "Blob" || get_class(data) === "File") { | |||||
| if (FileReaderSync) { | |||||
| var fr = new FileReaderSync; | |||||
| bb.push(fr.readAsBinaryString(data)); | |||||
| } else { | |||||
| // async FileReader won't work as BlobBuilder is sync | |||||
| throw new FileException("NOT_READABLE_ERR"); | |||||
| } | |||||
| } else if (data instanceof FakeBlob) { | |||||
| if (data.encoding === "base64" && atob) { | |||||
| bb.push(atob(data.data)); | |||||
| } else if (data.encoding === "URI") { | |||||
| bb.push(decodeURIComponent(data.data)); | |||||
| } else if (data.encoding === "raw") { | |||||
| bb.push(data.data); | |||||
| } | |||||
| } else { | |||||
| if (typeof data !== "string") { | |||||
| data += ""; // convert unsupported types to strings | |||||
| } | |||||
| // decode UTF-16 to binary string | |||||
| bb.push(unescape(encodeURIComponent(data))); | |||||
| } | |||||
| }; | |||||
| FBB_proto.getBlob = function(type) { | |||||
| if (!arguments.length) { | |||||
| type = null; | |||||
| } | |||||
| return new FakeBlob(this.data.join(""), type, "raw"); | |||||
| }; | |||||
| FBB_proto.toString = function() { | |||||
| return "[object BlobBuilder]"; | |||||
| }; | |||||
| FB_proto.slice = function(start, end, type) { | |||||
| var args = arguments.length; | |||||
| if (args < 3) { | |||||
| type = null; | |||||
| } | |||||
| return new FakeBlob( | |||||
| this.data.slice(start, args > 1 ? end : this.data.length) | |||||
| , type | |||||
| , this.encoding | |||||
| ); | |||||
| }; | |||||
| FB_proto.toString = function() { | |||||
| return "[object Blob]"; | |||||
| }; | |||||
| FB_proto.close = function() { | |||||
| this.size = this.data.length = 0; | |||||
| }; | |||||
| return FakeBlobBuilder; | |||||
| }(view)); | |||||
| view.Blob = function Blob(blobParts, options) { | |||||
| var type = options ? (options.type || "") : ""; | |||||
| var builder = new BlobBuilder(); | |||||
| if (blobParts) { | |||||
| for (var i = 0, len = blobParts.length; i < len; i++) { | |||||
| builder.append(blobParts[i]); | |||||
| } | |||||
| } | |||||
| return builder.getBlob(type); | |||||
| }; | |||||
| }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); | |||||
| @@ -0,0 +1,141 @@ | |||||
| /* eslint-disable */ | |||||
| require('script-loader!file-saver'); | |||||
| require('./Blob'); | |||||
| require('script-loader!xlsx/dist/xlsx.core.min'); | |||||
| function generateArray(table) { | |||||
| var out = []; | |||||
| var rows = table.querySelectorAll('tr'); | |||||
| var ranges = []; | |||||
| for (var R = 0; R < rows.length; ++R) { | |||||
| var outRow = []; | |||||
| var row = rows[R]; | |||||
| var columns = row.querySelectorAll('td'); | |||||
| for (var C = 0; C < columns.length; ++C) { | |||||
| var cell = columns[C]; | |||||
| var colspan = cell.getAttribute('colspan'); | |||||
| var rowspan = cell.getAttribute('rowspan'); | |||||
| var cellValue = cell.innerText; | |||||
| if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue; | |||||
| //Skip ranges | |||||
| ranges.forEach(function (range) { | |||||
| if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) { | |||||
| for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null); | |||||
| } | |||||
| }); | |||||
| //Handle Row Span | |||||
| if (rowspan || colspan) { | |||||
| rowspan = rowspan || 1; | |||||
| colspan = colspan || 1; | |||||
| ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}}); | |||||
| } | |||||
| ; | |||||
| //Handle Value | |||||
| outRow.push(cellValue !== "" ? cellValue : null); | |||||
| //Handle Colspan | |||||
| if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null); | |||||
| } | |||||
| out.push(outRow); | |||||
| } | |||||
| return [out, ranges]; | |||||
| }; | |||||
| function datenum(v, date1904) { | |||||
| if (date1904) v += 1462; | |||||
| var epoch = Date.parse(v); | |||||
| return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); | |||||
| } | |||||
| function sheet_from_array_of_arrays(data, opts) { | |||||
| var ws = {}; | |||||
| var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}; | |||||
| for (var R = 0; R != data.length; ++R) { | |||||
| for (var C = 0; C != data[R].length; ++C) { | |||||
| if (range.s.r > R) range.s.r = R; | |||||
| if (range.s.c > C) range.s.c = C; | |||||
| if (range.e.r < R) range.e.r = R; | |||||
| if (range.e.c < C) range.e.c = C; | |||||
| var cell = {v: data[R][C]}; | |||||
| if (cell.v == null) continue; | |||||
| var cell_ref = XLSX.utils.encode_cell({c: C, r: R}); | |||||
| if (typeof cell.v === 'number') cell.t = 'n'; | |||||
| else if (typeof cell.v === 'boolean') cell.t = 'b'; | |||||
| else if (cell.v instanceof Date) { | |||||
| cell.t = 'n'; | |||||
| cell.z = XLSX.SSF._table[14]; | |||||
| cell.v = datenum(cell.v); | |||||
| } | |||||
| else cell.t = 's'; | |||||
| ws[cell_ref] = cell; | |||||
| } | |||||
| } | |||||
| if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range); | |||||
| return ws; | |||||
| } | |||||
| function Workbook() { | |||||
| if (!(this instanceof Workbook)) return new Workbook(); | |||||
| this.SheetNames = []; | |||||
| this.Sheets = {}; | |||||
| } | |||||
| function s2ab(s) { | |||||
| var buf = new ArrayBuffer(s.length); | |||||
| var view = new Uint8Array(buf); | |||||
| for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | |||||
| return buf; | |||||
| } | |||||
| export function export_table_to_excel(id) { | |||||
| var theTable = document.getElementById(id); | |||||
| console.log('a') | |||||
| var oo = generateArray(theTable); | |||||
| var ranges = oo[1]; | |||||
| /* original data */ | |||||
| var data = oo[0]; | |||||
| var ws_name = "SheetJS"; | |||||
| console.log(data); | |||||
| var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); | |||||
| /* add ranges to worksheet */ | |||||
| // ws['!cols'] = ['apple', 'banan']; | |||||
| ws['!merges'] = ranges; | |||||
| /* add worksheet to workbook */ | |||||
| wb.SheetNames.push(ws_name); | |||||
| wb.Sheets[ws_name] = ws; | |||||
| var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); | |||||
| saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") | |||||
| } | |||||
| function formatJson(jsonData) { | |||||
| console.log(jsonData) | |||||
| } | |||||
| export function export_json_to_excel(th, jsonData, defaultTitle) { | |||||
| /* original data */ | |||||
| var data = jsonData; | |||||
| data.unshift(th); | |||||
| var ws_name = "SheetJS"; | |||||
| var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); | |||||
| /* add worksheet to workbook */ | |||||
| wb.SheetNames.push(ws_name); | |||||
| wb.Sheets[ws_name] = ws; | |||||
| var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); | |||||
| var title = defaultTitle || '列表' | |||||
| saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx") | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| export function export2Excel(columns,list,filename){ | |||||
| require.ensure([], () => { | |||||
| const { export_json_to_excel } = require('./Export2Excel'); | |||||
| let tHeader = [] | |||||
| let filterVal = [] | |||||
| console.log(columns) | |||||
| if(!columns){ | |||||
| return; | |||||
| } | |||||
| columns.forEach(item =>{ | |||||
| tHeader.push(item.title) | |||||
| filterVal.push(item.key) | |||||
| }) | |||||
| const data = list.map(v => filterVal.map(j => v[j])) | |||||
| export_json_to_excel(tHeader, data, filename); | |||||
| }) | |||||
| } | |||||
| @@ -13,7 +13,7 @@ import qs from 'qs'; | |||||
| import 'jquery.are-you-sure'; | import 'jquery.are-you-sure'; | ||||
| import './vendor/semanticdropdown.js'; | import './vendor/semanticdropdown.js'; | ||||
| import {svg} from './utils.js'; | import {svg} from './utils.js'; | ||||
| import echarts from 'echarts' | |||||
| import initContextPopups from './features/contextpopup.js'; | import initContextPopups from './features/contextpopup.js'; | ||||
| import initGitGraph from './features/gitgraph.js'; | import initGitGraph from './features/gitgraph.js'; | ||||
| import initClipboard from './features/clipboard.js'; | import initClipboard from './features/clipboard.js'; | ||||
| @@ -35,8 +35,9 @@ import {createCodeEditor} from './features/codeeditor.js'; | |||||
| import MinioUploader from './components/MinioUploader.vue'; | import MinioUploader from './components/MinioUploader.vue'; | ||||
| import ObsUploader from './components/ObsUploader.vue'; | import ObsUploader from './components/ObsUploader.vue'; | ||||
| import EditAboutInfo from './components/EditAboutInfo.vue'; | import EditAboutInfo from './components/EditAboutInfo.vue'; | ||||
| import Images from './components/Images.vue' | |||||
| import EditTopics from './components/EditTopics.vue' | |||||
| import Images from './components/Images.vue'; | |||||
| import EditTopics from './components/EditTopics.vue'; | |||||
| import DataAnalysis from './components/DataAnalysis.vue' | |||||
| import Contributors from './components/Contributors.vue' | import Contributors from './components/Contributors.vue' | ||||
| Vue.use(ElementUI); | Vue.use(ElementUI); | ||||
| @@ -44,6 +45,10 @@ Vue.prototype.$axios = axios; | |||||
| Vue.prototype.qs = qs; | Vue.prototype.qs = qs; | ||||
| const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | ||||
| Object.defineProperty(Vue.prototype, '$echarts', { | |||||
| value: echarts | |||||
| }) | |||||
| function htmlEncode(text) { | function htmlEncode(text) { | ||||
| return jQuery('<div />') | return jQuery('<div />') | ||||
| .text(text) | .text(text) | ||||
| @@ -2972,6 +2977,7 @@ $(document).ready(async () => { | |||||
| initVueEditTopic(); | initVueEditTopic(); | ||||
| initVueContributors(); | initVueContributors(); | ||||
| initVueImages(); | initVueImages(); | ||||
| initVueDataAnalysis(); | |||||
| initTeamSettings(); | initTeamSettings(); | ||||
| initCtrlEnterSubmit(); | initCtrlEnterSubmit(); | ||||
| initNavbarContentToggle(); | initNavbarContentToggle(); | ||||
| @@ -3713,7 +3719,20 @@ function initVueImages() { | |||||
| render: h => h(Images) | render: h => h(Images) | ||||
| }); | }); | ||||
| } | } | ||||
| function initVueDataAnalysis() { | |||||
| const el = document.getElementById('data_analysis'); | |||||
| console.log("el",el) | |||||
| if (!el) { | |||||
| return; | |||||
| } | |||||
| new Vue({ | |||||
| el: '#data_analysis', | |||||
| render: h => h(DataAnalysis) | |||||
| }); | |||||
| } | |||||
| // 新增 | // 新增 | ||||
| function initObsUploader() { | function initObsUploader() { | ||||
| const el = document.getElementById('obsUploader'); | const el = document.getElementById('obsUploader'); | ||||