|
|
@@ -0,0 +1,403 @@
|
|
|
+<template>
|
|
|
+ <div class="course-red-packet-statistics">
|
|
|
+ <!-- 查询条件 -->
|
|
|
+ <el-card class="search-card">
|
|
|
+ <el-form :model="queryParams" ref="queryParams" label-width="80px" inline>
|
|
|
+ <el-form-item label="筛选类型" prop="status">
|
|
|
+ <el-select v-model="queryParams.changeType" placeholder="请选择筛选类型" clearable style="width: 100%" @change="changeType">
|
|
|
+ <el-option label="按销售公司" :value="1"></el-option>
|
|
|
+ <el-option label="按员工" :value="2"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="公司名" prop="companyId" v-if="queryParams.changeType ==1 ">
|
|
|
+ <el-select filterable style="width: 220px" v-model="queryParams.companyIds"
|
|
|
+ @change="handleSeller" placeholder="请选择公司名"
|
|
|
+ clearable size="small"
|
|
|
+ multiple >
|
|
|
+ <el-option
|
|
|
+ v-for="item in companys"
|
|
|
+ :key="item.companyId"
|
|
|
+ :label="item.companyName"
|
|
|
+ :value="item.companyId"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="选择员工" prop="userIds" v-if="queryParams.changeType ==2 ">
|
|
|
+ <select-tree
|
|
|
+ v-model="selectedCompanyList"
|
|
|
+ :raw-data="deptList"
|
|
|
+ :parentSelectable="true"
|
|
|
+ placeholder="请选择销售"
|
|
|
+ :multiple="true"
|
|
|
+ component-width="300px"
|
|
|
+ :max-display-tags="3"
|
|
|
+ :check-strictly="false"
|
|
|
+ :return-leaf-only="false"
|
|
|
+ ></select-tree>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="状态" prop="status">
|
|
|
+ <el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 100%">
|
|
|
+ <el-option label="全部" value=""></el-option>
|
|
|
+ <el-option label="发送中" value="0"></el-option>
|
|
|
+ <el-option label="已发送" value="1"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="创建时间" prop="createTime">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="createTimeText"
|
|
|
+ type="datetimerange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ @change="createChange"
|
|
|
+ :default-time="['00:00:00', '23:59:59']"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <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"
|
|
|
+ v-hasPermi="['course:courseRedPacketLog:countExport']"
|
|
|
+ >导出
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24" class="text-right">
|
|
|
+ <el-button type="primary" @click="handleSearch">查询</el-button>
|
|
|
+ <el-button @click="resetQuery">重置</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <!-- 统计结果 -->
|
|
|
+ <el-card class="result-card">
|
|
|
+ <div slot="header">
|
|
|
+ <span>红包发送统计</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-table :data="statisticsData" border style="width: 100%" v-loading="loading"
|
|
|
+ show-summary :summary-method="getSummaries"> >
|
|
|
+ <el-table-column prop="companyName" label="公司名称" align="center"></el-table-column>
|
|
|
+ <div v-if="queryParams.changeType==2">
|
|
|
+ <el-table-column prop="nickName" label="员工姓名" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="companyUserId" label="员工编号" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="deptId" label="部门编号" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="deptName" label="部门昵称" align="center"></el-table-column>
|
|
|
+ </div>
|
|
|
+ <el-table-column prop="amount" label="已发红包金额" align="center"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination
|
|
|
+ v-show="total>0"
|
|
|
+ :total="total"
|
|
|
+ :page.sync="queryParams.pageNum"
|
|
|
+ :limit.sync="queryParams.pageSize"
|
|
|
+ @pagination="getList"
|
|
|
+ />
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {getCompanyList} from "@/api/company/company";
|
|
|
+import {getUserList} from "@/api/company/companyUser";
|
|
|
+import SelectTree from '@/components/TreeSelect/index.vue'
|
|
|
+import { getDeptData } from '@/api/system/employeeStats'
|
|
|
+import {
|
|
|
+ exportCourseRedPacketLogCountExport,
|
|
|
+ getRedPacketLogCount
|
|
|
+} from '@/api/course/courseRedPacketLog'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'courseRedPacketLogCount',
|
|
|
+ components: { SelectTree },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ // 总条数
|
|
|
+ total: 0,
|
|
|
+ companys:[],
|
|
|
+ companyUserList:[],
|
|
|
+ selectedCompanyList: [],
|
|
|
+ deptList: [],
|
|
|
+ createTimeText: [],
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ changeType: 1,
|
|
|
+ companyId: null,
|
|
|
+ companyIds: null,
|
|
|
+ companyUserId: null,
|
|
|
+ startTime:null,
|
|
|
+ endTime:null,
|
|
|
+ status: null,
|
|
|
+ sTime:null,
|
|
|
+ eTime:null,
|
|
|
+ userIds: null
|
|
|
+ },
|
|
|
+ exportLoading: false,
|
|
|
+ statisticsData: [],
|
|
|
+ loading: false,
|
|
|
+ pageInfo: {
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ getCompanyList().then(response => {
|
|
|
+ this.companys = response.data;
|
|
|
+ if(this.companys!=null&&this.companys.length>0){
|
|
|
+ this.companyId=this.companys[0].companyId;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ getDeptData().then(response => {
|
|
|
+ this.deptList = response.data;
|
|
|
+ })
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+
|
|
|
+ changeType(){
|
|
|
+ this.statisticsData=[];
|
|
|
+ if (this.queryParams.changeType == 1){
|
|
|
+ this.selectedCompanyList=[];
|
|
|
+ }
|
|
|
+ if (this.queryParams.changeType == 2){
|
|
|
+ this.queryParams.companyIds=null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ getSummaries(param) {
|
|
|
+ const { columns, data } = param; // data 就是当前表格的 statisticsData
|
|
|
+ const sums = [];
|
|
|
+
|
|
|
+ columns.forEach((column, index) => {
|
|
|
+ if (index === 0) {
|
|
|
+ sums[index] = '总计';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (column.property === 'amount') {
|
|
|
+ // 直接从当前表格数据计算
|
|
|
+ const total = data.reduce((sum, item) => {
|
|
|
+ return sum + (parseFloat(item.amount) || 0);
|
|
|
+ }, 0);
|
|
|
+ sums[index] = '¥' + this.formatAmount(total);
|
|
|
+ } else {
|
|
|
+ sums[index] = '';
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return sums;
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ // 格式化金额(不四舍五入,保留两位小数)
|
|
|
+ formatAmount(value) {
|
|
|
+ if (isNaN(value)) return '0.00';
|
|
|
+
|
|
|
+ // 方法1:使用 Math.floor 截断
|
|
|
+ const truncated = Math.floor(value * 100) / 100;
|
|
|
+
|
|
|
+ // 方法2:更精确的截断方法
|
|
|
+ // const truncated = Number(value.toString().match(/^\d+(?:\.\d{0,2})?/));
|
|
|
+
|
|
|
+ return truncated.toFixed(2);
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ handleSearch() {
|
|
|
+ this.pageInfo.currentPage = 1
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+
|
|
|
+ createChange(createTime) {
|
|
|
+ if (createTime && createTime.length >= 2) {
|
|
|
+ if(!this.checkDateRangeLimit(createTime)){
|
|
|
+ this.createTimeText = null;
|
|
|
+ this.queryParams.sTime=null;
|
|
|
+ this.queryParams.eTime=null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.queryParams.sTime = this.formatDate(createTime[0]) || null;
|
|
|
+ this.queryParams.eTime = this.formatDate(createTime[1]) || null;
|
|
|
+ } else {
|
|
|
+ this.createTimeText = [];
|
|
|
+ this.queryParams.sTime = null;
|
|
|
+ this.queryParams.eTime = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ formatDate(date) {
|
|
|
+ if (!date) return ''
|
|
|
+
|
|
|
+ // 确保 date 是 Date 对象
|
|
|
+ let dateObj = date
|
|
|
+ if (typeof date === 'string') {
|
|
|
+ dateObj = new Date(date)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果转换失败,返回空字符串
|
|
|
+ if (!(dateObj instanceof Date) || isNaN(dateObj.getTime())) {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用更安全的格式化方法
|
|
|
+ const year = dateObj.getFullYear()
|
|
|
+ const month = String(dateObj.getMonth() + 1).padStart(2, '0')
|
|
|
+ const day = String(dateObj.getDate()).padStart(2, '0')
|
|
|
+ const hours = String(dateObj.getHours()).padStart(2, '0')
|
|
|
+ const minutes = String(dateObj.getMinutes()).padStart(2, '0')
|
|
|
+ const seconds = String(dateObj.getSeconds()).padStart(2, '0')
|
|
|
+
|
|
|
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
|
|
+ },
|
|
|
+ checkDateRangeLimit(dateRange) {
|
|
|
+ if (dateRange && dateRange.length >= 2) {
|
|
|
+ const startDate = new Date(dateRange[0]);
|
|
|
+ const endDate = new Date(dateRange[1]);
|
|
|
+
|
|
|
+ // 设置时间为当天开始,避免时间部分影响计算
|
|
|
+ startDate.setHours(0, 0, 0, 0);
|
|
|
+ endDate.setHours(0, 0, 0, 0);
|
|
|
+
|
|
|
+ const timeDiff = Math.abs(endDate - startDate);
|
|
|
+ const diffDays = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
|
|
|
+
|
|
|
+ if (diffDays > 31) { // maxDays-1 因为包含起始日
|
|
|
+ this.$message.warning('时间区间不能超过一个月');
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ handleSeller(){
|
|
|
+
|
|
|
+ if(this.queryParams.companyId != null) {
|
|
|
+ getUserList(this.queryParams.companyId).then(res=>{
|
|
|
+ if(res.code === 200) {
|
|
|
+ this.companyUserList = res.data
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ resetQuery() {
|
|
|
+ this.$refs.queryParams.resetFields();
|
|
|
+ this.createTimeText = [];
|
|
|
+ this.queryParams.dateRange = [];
|
|
|
+ this.selectedCompanyList = [];
|
|
|
+ this.statisticsData=[];
|
|
|
+ this.handleSearch()
|
|
|
+ },
|
|
|
+
|
|
|
+ getList() {
|
|
|
+
|
|
|
+ if (this.queryParams.changeType == 1 && this.queryParams.companyIds.length == 0) {
|
|
|
+ return this.$message.warning('请选择公司');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.isEmptyArray(this.createTimeText)) {
|
|
|
+ this.$message.warning('请选择创建时间');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log(this.queryParams.changeType)
|
|
|
+ console.log(this.selectedCompanyList)
|
|
|
+
|
|
|
+ if (this.queryParams.changeType == 2){
|
|
|
+ if( this.selectedCompanyList != null && this.selectedCompanyList.length > 0) {
|
|
|
+ this.queryParams.userIds = this.selectedCompanyList;
|
|
|
+ }else {
|
|
|
+ return this.$message.warning('请选择员工');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.loading = true
|
|
|
+ // 查询统计
|
|
|
+ getRedPacketLogCount(this.queryParams).then(response => {
|
|
|
+ this.statisticsData = response.data.list;
|
|
|
+ this.total = response.data.total;
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 添加辅助方法
|
|
|
+ isEmptyArray(arr) {
|
|
|
+ return !arr || arr.length === 0;
|
|
|
+ },
|
|
|
+ handleSizeChange(val) {
|
|
|
+ this.pageInfo.pageSize = val
|
|
|
+ this.pageInfo.currentPage = 1
|
|
|
+ this.getList()
|
|
|
+ },
|
|
|
+
|
|
|
+ handleCurrentChange(val) {
|
|
|
+ this.pageInfo.currentPage = val
|
|
|
+ this.getList()
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 导出按钮操作 */
|
|
|
+ handleExport() {
|
|
|
+
|
|
|
+ if(this.selectedCompanyList != null && this.selectedCompanyList.length > 0) {
|
|
|
+ this.queryParams.userIds = this.selectedCompanyList;
|
|
|
+ }else {
|
|
|
+ this.queryParams.userIds = [];
|
|
|
+ }
|
|
|
+ const queryParams = this.queryParams;
|
|
|
+ this.$confirm('是否确认导出所有红包记录数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(() => {
|
|
|
+ const loadingInstance = this.$loading({
|
|
|
+ lock: true,
|
|
|
+ text: '正在导出数据,请稍候...',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)'
|
|
|
+ });
|
|
|
+
|
|
|
+ this.exportLoading = true;
|
|
|
+
|
|
|
+ return exportCourseRedPacketLogCountExport(queryParams).finally(res=>{
|
|
|
+ loadingInstance.close();
|
|
|
+ })
|
|
|
+ }).then(response => {
|
|
|
+ this.download(response.msg);
|
|
|
+ this.exportLoading = false;
|
|
|
+ }).catch(() => {}).finally(res=>{
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.course-red-packet-statistics {
|
|
|
+ padding: 20px;
|
|
|
+
|
|
|
+ .search-card {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .result-card {
|
|
|
+ .pagination-container {
|
|
|
+ margin-top: 20px;
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .text-right {
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|