|
|
@@ -0,0 +1,322 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+
|
|
|
+ <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
|
|
|
+ <el-form-item label="所属部门" prop="deptId">
|
|
|
+ <treeselect style="width:205.4px" v-model="queryParams.deptId" :options="deptTreeOptions" :show-count="true" placeholder="请选择所属部门" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="项目" prop="project">
|
|
|
+ <el-select filterable v-model="queryParams.project" placeholder="请选择项目"
|
|
|
+ clearable size="small">
|
|
|
+ <el-option
|
|
|
+ v-for="item in projectList"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="训练营" prop="trainingCampId">
|
|
|
+ <el-select filterable v-model="queryParams.trainingCampId" placeholder="请选择训练营"
|
|
|
+ clearable size="small" @change="handleCampChange">
|
|
|
+ <el-option
|
|
|
+ v-for="item in camps"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <treeselect style="width: 220px" v-model="queryParams.periodId" :options="deptOptions"
|
|
|
+ clearable :show-count="true" placeholder="请选择归属营期" value-consists-of="LEAF_PRIORITY"
|
|
|
+ :normalizer="normalizer" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-form-item label="看课时间" prop="createTime">
|
|
|
+ <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd"
|
|
|
+ type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
|
|
|
+ @change="xdChange"></el-date-picker>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
|
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-row :gutter="10" class="mb8">
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="warning"
|
|
|
+ plain
|
|
|
+ icon="el-icon-download"
|
|
|
+ size="mini"
|
|
|
+ :loading="exportLoading"
|
|
|
+ @click="handleExport"
|
|
|
+ >导出</el-button>
|
|
|
+ </el-col>
|
|
|
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-table v-loading="loading" border :data="packageList">
|
|
|
+ <el-table-column label="所属销售部门" align="center" prop="salesDept"/>
|
|
|
+ <el-table-column label="销售数" align="center" prop="salesCount" />
|
|
|
+ <el-table-column label="所属销售公司" align="center" prop="salesCompany"/>
|
|
|
+ <el-table-column label="完课数" align="center" prop="finishedCount" />
|
|
|
+ <el-table-column label="未完课" align="center" prop="unfinishedCount" />
|
|
|
+ <el-table-column label="完课率" align="center" prop="completionRate" />
|
|
|
+ <el-table-column label="未看数" align="center" prop="notWatchedCount" />
|
|
|
+ <el-table-column label="历史疗法订单数" align="center" prop="historyOrderCount" />
|
|
|
+ </el-table>
|
|
|
+ <div class="total-summary">
|
|
|
+ <span class="total-title">总计:</span>
|
|
|
+ <span class="total-item">完课数: {{ calculatedTotalData.finishedCount }}</span>
|
|
|
+ <span class="total-item">未完课: {{ calculatedTotalData.unfinishedCount }}</span>
|
|
|
+ <span class="total-item">完课率: {{ calculatedTotalData.completionRate }}</span>
|
|
|
+ <span class="total-item">未看数: {{ calculatedTotalData.notWatchedCount }}</span>
|
|
|
+ <span class="total-item">历史疗法订单数: {{ calculatedTotalData.historyOrderCount }}</span>
|
|
|
+ </div>
|
|
|
+ <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
|
|
|
+ @pagination="getList" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {
|
|
|
+ feiShuWatchLogReport, exportFeiShuWatchLogReport
|
|
|
+} from "@/api/store/package";
|
|
|
+import Treeselect from "@riophae/vue-treeselect";
|
|
|
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
|
|
+import { getCampList, getPeriodList } from "@/api/store/storeProduct";
|
|
|
+import { getCompanyList } from "@/api/company/company";
|
|
|
+import { selectDeptTree } from "@/api/company/companyDept";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "FeiShuWatchlogReportDept",
|
|
|
+ components: { Treeselect },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ normalizer: function(node) {
|
|
|
+ return {
|
|
|
+ id: node.id || node.dictValue,
|
|
|
+ label: node.label || node.dictLabel,
|
|
|
+ children: node.children
|
|
|
+ }
|
|
|
+ },
|
|
|
+ projectList: [],
|
|
|
+ companys: [],
|
|
|
+ camps: [],
|
|
|
+ deptOptions: [],
|
|
|
+ deptTreeOptions: [],
|
|
|
+ calculatedTotalData: {
|
|
|
+ finishedCount: 0,
|
|
|
+ unfinishedCount: 0,
|
|
|
+ completionRate: 0,
|
|
|
+ notWatchedCount: 0,
|
|
|
+ historyOrderCount: 0
|
|
|
+ },
|
|
|
+ loading: true,
|
|
|
+ exportLoading: false,
|
|
|
+ showSearch: true,
|
|
|
+ total: 0,
|
|
|
+ createTime: null,
|
|
|
+ packageList: [],
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ project: null,
|
|
|
+ trainingCampId: null,
|
|
|
+ periodId: null,
|
|
|
+ sTime: null,
|
|
|
+ eTime: null,
|
|
|
+ deptId: null,
|
|
|
+ dimension: 'company'
|
|
|
+ }
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getTreeselect(this.$store.state.user.user.companyId);
|
|
|
+ if (!this.queryParams.dimension) {
|
|
|
+ this.queryParams.dimension = 'company';
|
|
|
+ }
|
|
|
+ getCampList({ "pageNum": 1, "pageSize": 100 }).then(response => {
|
|
|
+ this.camps = response.data.list;
|
|
|
+ if (this.camps != null && this.camps.length > 0) {
|
|
|
+ this.companyId = this.camps[0].dictValue;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ getCompanyList().then(response => {
|
|
|
+ this.companys = response.data;
|
|
|
+ this.companys.push({ companyId: "-1", companyName: "无" });
|
|
|
+ });
|
|
|
+ this.getList();
|
|
|
+ this.getDicts("sys_course_project").then(e => {
|
|
|
+ this.projectList = e.data;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getList() {
|
|
|
+ this.loading = true;
|
|
|
+ feiShuWatchLogReport(this.queryParams).then(response => {
|
|
|
+ this.packageList = response.rows;
|
|
|
+ this.total = response.total;
|
|
|
+ this.calculateTotals();
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ calculateTotals() {
|
|
|
+ this.calculatedTotalData = {
|
|
|
+ finishedCount: 0,
|
|
|
+ unfinishedCount: 0,
|
|
|
+ completionRate: 0,
|
|
|
+ notWatchedCount: 0,
|
|
|
+ historyOrderCount: 0
|
|
|
+ };
|
|
|
+ this.packageList.forEach(item => {
|
|
|
+ this.calculatedTotalData.finishedCount += Number(item.finishedCount) || 0;
|
|
|
+ this.calculatedTotalData.unfinishedCount += Number(item.unfinishedCount) || 0;
|
|
|
+ this.calculatedTotalData.notWatchedCount += Number(item.notWatchedCount) || 0;
|
|
|
+ this.calculatedTotalData.historyOrderCount += Number(item.historyOrderCount) || 0;
|
|
|
+ });
|
|
|
+ const totalCount = this.calculatedTotalData.finishedCount + this.calculatedTotalData.unfinishedCount;
|
|
|
+ if (totalCount > 0) {
|
|
|
+ this.calculatedTotalData.completionRate = (this.calculatedTotalData.finishedCount / totalCount * 100).toFixed(2) + '%';
|
|
|
+ } else {
|
|
|
+ this.calculatedTotalData.completionRate = '0%';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getTreeselect(companyId) {
|
|
|
+ selectDeptTree({ companyId: companyId }).then(response => {
|
|
|
+ this.deptTreeOptions = response.data;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleCampChange(val) {
|
|
|
+ this.queryParams.trainingCampId = val;
|
|
|
+ this.queryParams.periodId = null;
|
|
|
+ if (val) {
|
|
|
+ this.getPeriodByCamp(val);
|
|
|
+ } else {
|
|
|
+ this.deptOptions = [];
|
|
|
+ }
|
|
|
+ this.handleQuery();
|
|
|
+ },
|
|
|
+ getPeriodByCamp(campId) {
|
|
|
+ getPeriodList({ campId: campId }).then(response => {
|
|
|
+ this.deptOptions = response.data.list || [];
|
|
|
+ }).catch(() => {
|
|
|
+ this.deptOptions = [];
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleQuery() {
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ resetQuery() {
|
|
|
+ this.resetForm("queryForm");
|
|
|
+ this.createTime = null;
|
|
|
+ this.queryParams.sTime = null;
|
|
|
+ this.queryParams.eTime = null;
|
|
|
+ this.handleQuery();
|
|
|
+ },
|
|
|
+ handleExport() {
|
|
|
+ this.$confirm('是否确认导出飞书看课统计(部门)数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(() => {
|
|
|
+ this.exportLoading = true;
|
|
|
+ return exportFeiShuWatchLogReport(this.queryParams);
|
|
|
+ }).then(response => {
|
|
|
+ this.download(response.msg);
|
|
|
+ this.exportLoading = false;
|
|
|
+ }).catch(() => {});
|
|
|
+ },
|
|
|
+ xdChange() {
|
|
|
+ if (this.createTime != null) {
|
|
|
+ this.queryParams.sTime = this.createTime[0];
|
|
|
+ this.queryParams.eTime = this.createTime[1];
|
|
|
+ } else {
|
|
|
+ this.queryParams.sTime = null;
|
|
|
+ this.queryParams.eTime = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+.icon-button {
|
|
|
+ border-radius: 0;
|
|
|
+}
|
|
|
+.avatar-uploader .el-upload {
|
|
|
+ border: 1px dashed #d9d9d9;
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.avatar-uploader .el-upload:hover {
|
|
|
+ border-color: #409EFF;
|
|
|
+}
|
|
|
+.avatar-uploader-icon {
|
|
|
+ font-size: 28px;
|
|
|
+ color: #8c939d;
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
+ line-height: 150px !important;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.total-summary {
|
|
|
+ margin-top: 15px;
|
|
|
+ padding: 15px 20px;
|
|
|
+ background: linear-gradient(135deg, #f5f7fa 0%, #e4e7f4 100%);
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.total-title {
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #303133;
|
|
|
+ margin-right: 20px;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+.total-item {
|
|
|
+ margin-right: 25px;
|
|
|
+ padding: 5px 10px;
|
|
|
+ background: white;
|
|
|
+ border-radius: 3px;
|
|
|
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
|
+ display: inline-block;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+.total-item::before {
|
|
|
+ content: "";
|
|
|
+ display: inline-block;
|
|
|
+ width: 3px;
|
|
|
+ height: 3px;
|
|
|
+ background: #409eff;
|
|
|
+ border-radius: 50%;
|
|
|
+ margin-right: 5px;
|
|
|
+ vertical-align: middle;
|
|
|
+}
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .total-summary {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ }
|
|
|
+ .total-title {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+ .total-item {
|
|
|
+ margin-right: 10px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|