<!-- API 访问日志列表 -->
<template>
    <el-scrollbar class="vue-box">
        <div class="c-card">
            <!-- 参数栏 -->
            <div class="c-title">检索参数</div>
            <el-form class="select-form" :inline="true" label-width="7em" @submit.native.prevent @keyup.enter="state.p.pageNo = 1; f5();">
                <in-input name="请求 ID：" v-model="state.p.id" placeholder="精确定位"></in-input>
                <in-input name="请求 IP：" v-model="state.p.reqIp" placeholder="IP 筛选"></in-input>
                <in-input name="请求 API：" v-model="state.p.reqApi" placeholder="API 接口筛选"></in-input>
                <in-item class="ok-item">
                    <el-button type="primary" icon="el-icon-Search" @click="state.p.pageNo = 1; f5()">查询</el-button>
                </in-item>
                <br>
                <in-input name="携带Token：" v-model="state.p.reqToken" placeholder="定向跟踪 Token"></in-input>
                <in-input name="UserId：" v-model="state.p.userId" placeholder="定向跟踪用户"></in-input>
                <in-input name="AdminId：" v-model="state.p.adminId" placeholder="定向跟踪用户"></in-input>
                <br>
                <in-input name="Res状态码：" v-model="state.p.resCode" placeholder="状态码筛选"></in-input>
                <in-item name="请求时间：">
                    <el-date-picker v-model="state.p.sTime" type="datetime" placeholder="开始日期" /> -
                    <el-date-picker v-model="state.p.eTime" type="datetime" placeholder="结束日期" />
                </in-item>
                <br>
                <in-item name="综合排序：" class="c-item">
                    <el-radio-group v-model="state.p.sortType" class="s-radio-text">
                        <el-radio label="id">默认</el-radio>
                        <el-radio label="start_time">请求时间</el-radio>
                        <el-radio label="cost_time">请求耗时</el-radio>
                    </el-radio-group>
                </in-item>
            </el-form>
            <!-- ------------- 快捷按钮 ------------- -->
            <div class="fast-btn">
                <el-button type="primary" icon="el-icon-Plus" @click="copyAll()">复制全部</el-button>
                <el-button type="danger" plain icon="el-icon-Delete" @click="deleteByIds()">批量删除</el-button>
                <el-button type="danger" plain icon="el-icon-Delete" @click="deleteByStartEnd()">范围删除</el-button>
                <el-button type="warning" plain icon="el-icon-Download" @click="sa.exportExcel()">导出</el-button>
                <el-button type="success" plain icon="el-icon-View" @click="f5StaData()">统计数据</el-button>
                <el-button plain icon="el-icon-Refresh" @click="sa.f5CurrView()">重置</el-button>
            </div>
            <!-- ------------- 数据列表 ------------- -->
            <el-table ref="data-table" class="data-table" :data="state.dataList" size="small">
                <el-table-column type="selection" width="45px" />
                <el-table-column label="请求id" width="150px">
                    <template #default="s">
                        <div style="font-weight: bold;">{{ s.row.id }}</div>
                    </template>
                </el-table-column>
                <el-table-column label="请求 IP" width="130px">
                    <template #default="s">
                        <p class="req-ip">{{ (s.row.reqIp) }}</p>
                    </template>
                </el-table-column>
                <el-table-column label="请求接口" width="290px">
                    <template #default="s">
                        <div class="req-box">
                            <p class="req-type" :class=" 'req-type-' + s.row.reqType?.toLowerCase() ">
                                <b>{{ s.row.reqType }}：</b>
                                <span>{{ s.row.reqApi }}</span>
                            </p>
                            <p class="req-p" @click="seeReqParame(s.row)">{{ s.row.reqParame }}</p>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column label="请求返回" min-width="370px">
                    <template #default="s">
                        <div class="res-box">
                            <p class="res-code" :class=" 'res-code-' + s.row.resCode ">{{ s.row.resCode }} - {{ s.row.resMsg }}</p>
                            <p class="req-string" @click="seeResString(s.row)"> {{ s.row.resString }} </p>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column label="请求账号" width="150px">
                    <template #default="s">
                        <p v-if="s.row.userId === 0">userId：&nbsp;&nbsp;&nbsp;0</p>
                        <p v-else>userId：&nbsp;&nbsp;&nbsp;<el-link @click="sa.alert(s.row.userId)">{{ s.row.userId }}</el-link>
                        </p>
                        <p v-if="s.row.adminId === 0">adminId：0</p>
                        <p v-else>adminId：<el-link @click="sa.$page.openAdminInfo(s.row.adminId)">{{ s.row.adminId }}</el-link>
                        </p>
                    </template>
                </el-table-column>
                <el-table-column v-if="!sa.isNull(state.p.reqToken) " label="携带 Token" width="150px">
                    <template #default="s">
                        <div style="width: 130px;">{{ s.row.reqToken }}</div>
                    </template>
                </el-table-column>
                <el-table-column label="请求时间" width="280px">
                    <template #default="s">
                        <p>
                            开始：{{ sa.forDate(s.row.startTime, 'yyyy-MM-dd HH:mm:ss.ms') }} -
                            <b>{{ sa.isNull(sa.forDate2(s.row.startTime), '无') }}</b>
                        </p>
                        <p>
                            结束：{{ sa.forDate(s.row.endTime, 'yyyy-MM-dd HH:mm:ss.ms') }} -
                            <b style="color: green;">耗时：{{ (s.row.costTime + 0.0) / 1000 }}s</b>
                        </p>
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="120px" fixed="right">
                    <template #default="s">
                        <el-link type="primary" @click="copy(s.row)">复制</el-link> &nbsp;
                        <el-link type="primary" @click="del(s.row)" v-if="state.way === 1">删除</el-link>
                    </template>
                </el-table-column>
            </el-table>
            <!-- ------------- 分页按钮 ------------- -->
            <div class="page-box">
                <el-pagination
                    background layout="total, prev, pager, next, sizes, jumper"
                    v-model:current-page="state.p.pageNo" v-model:page-size="state.p.pageSize" :total="state.dataCount"
                    :page-sizes="[1, 10, 20, 30, 40, 50, 100]"
                    @current-change="f5()" @size-change="f5()">
                </el-pagination>
            </div>
        </div>
    </el-scrollbar>
</template>

<script setup name="apilog-list">
import {getCurrentInstance, onMounted, reactive} from "vue";
const {proxy} = getCurrentInstance();


// ------------------ 数据 ------------------
const state = reactive({
    p: { // 查询参数
        pageNo: 1,
        pageSize: 10,
        id: '',
        reqToken: '',
        reqIp: '',
        reqApi: '',
        resCode: '',
        userId: '',
        adminId: '',
        sTime: '',
        eTime: '',
        sortType: 'id'
    },
    way: sa.p('way', 1),
    dataCount: 0,
    dataList: [], // 数据集合
    isNewestSta: false,	// 当前是否为最新统计数据
    staData: {
        cost_time_count: 0,		// 总计耗时
    }
})

// 组价加载时执行 
onMounted(function (){
    f5();
});

// ------------------ 函数 ------------------
// 查询数据 
const f5 = function() {
    const p2 = sa.copyJSON(state.p);
    p2.sTime = sa.forDatetime(p2.sTime)
    p2.eTime = sa.forDatetime(p2.eTime)
    sa.ajax('/SgApilog/getList', sa.removeNull(p2), function(res) {
        state.dataList = res.data; // 数据
        state.dataCount = res.dataCount; // 数据总数
        state.isNewestSta = false;
    });
};

// 统计数据
const f5StaData = function() {
    var fn = function() {
        var str = '<b>总计请求：' + state.dataCount + ' 次</b><br/>' +
            '<b>总计耗时：' + getDuration(state.staData.cost_time_count) + ' </b>';
        str = '<big>' + str + '</big>'
        sa.layer.alert(str, { title: '统计数据' });
    };
    if (state.isNewestSta) {
        fn()
    } else {
        sa.ajax('/SgApilog/staBy', sa.removeNull(state.p), function(res) {
            state.staData = res.data;
            state.isNewestSta = true;
            fn();
        });
    }
};
// 复制
const copy = function(data) {
    sa.copyText(JSON.stringify(data));
    sa.ok2('已成功复制到剪贴板');
};
// 复制全部
const copyAll = function() {
    sa.copyText(JSON.stringify(state.dataList));
    sa.ok2('已成功复制到剪贴板');
};
// 查看：访问参数
const seeReqParame = function(data) {
    var jsonStr = data.reqParame;
    jsonStr = JSON.stringify(JSON.parse(jsonStr), null, '\t');
    layer.prompt({
        title: '请求参数',
        shadeClose: true,	// 点击遮罩关闭
        formType: 2,		// 多行输入
        value: jsonStr,		// 要显示的字符串
        maxlength: 9999999999,	// 最大输入字符长度
        area: ['600px', '400px'],	// 弹窗尺寸
        yes: function(index, layero){
            layer.close(index); // 如果设定了yes回调，需进行手工关闭
        }
    })
};
// 查看：返回参数
const seeResString = function(data) {
    var jsonStr = data.resString;
    jsonStr = JSON.stringify(JSON.parse(jsonStr), null, '\t');
    layer.prompt({
        title: '返回参数',
        shadeClose: true,	// 点击遮罩关闭
        formType: 2,		// 多行输入
        value: jsonStr,		// 要显示的字符串
        maxlength: 9999999999,	// 最大输入字符长度
        area: ['600px', '400px'],	// 弹窗尺寸
        yes: function(index, layero){
            layer.close(index); // 如果设定了yes回调，需进行手工关闭
        }
    })
};
// 删除
const del = function(data) {
    sa.confirm('是否删除，此操作不可撤销', function() {
        sa.ajax('/SgApilog/delete?id=' + data.id, function(res) {
            sa.arrayDelete(state.dataList, data);
            sa.ok('删除成功');
            sa.f5TableHeight();		// 刷新表格高度
        })
    });
};
// 批量删除
const deleteByIds = function() {
    // 获取选中元素的id列表
    let selection = proxy.$refs['data-table'].getSelectionRows();
    let ids = sa.getArrayField(selection, 'id');
    if(selection.length === 0) {
        return sa.msg('请至少选择一条数据');
    }
    // 提交删除
    sa.confirm(`是否删除选中的 ${selection.length} 条数据？此操作不可撤销`, function() {
        sa.ajax('/SgApilog/deleteByIds', { ids: ids.join(',') }, function(res) {
            sa.arrayDelete(state.dataList, selection);
            sa.ok('删除成功');
        })
    });
};
// 根据日期批量删除
const deleteByStartEnd = function() {
    sa.showModel('选择日期范围批量删除', () => import('./apilog-list-delete'));
};
// 计算耗时
const getDuration = function(my_time) {
    var days = my_time / 1000 / 60 / 60 / 24;
    var daysRound = Math.floor(days);
    var hours = my_time / 1000 / 60 / 60 - (24 * daysRound);
    var hoursRound = Math.floor(hours);
    var minutes = my_time / 1000 / 60 - (24 * 60 * daysRound) - (60 * hoursRound);
    var minutesRound = Math.floor(minutes);
    var seconds = my_time / 1000 - (24 * 60 * 60 * daysRound) - (60 * 60 * hoursRound) - (60 * minutesRound);
    seconds = parseInt(seconds);
    if (daysRound >= 1) {
        return daysRound + '天' + hoursRound + '小时';
    } else if (hoursRound >= 1) {
        return hoursRound + '小时' + hoursRound + '分';
    } else if (minutesRound >= 1) {
        return minutesRound + '分' + seconds + '秒';
    } else {
        return seconds + '秒';
    }
};

// 对外开放函数 
defineExpose({f5});

</script>

<style scoped lang="scss">
// 请求IP 
.req-ip{color: #409EFF; border: 1px #409EFF solid; border-radius: 1px; padding: 3px 5px; display: inline-block; line-height: 16px;}

// 不同的请求类型，加上不同的颜色 
.req-box{padding: 3px 8px; background-color: #ECF5FF; color: #888; border-radius: 1px;}
.req-type{color: #FF5722;}
.req-type.req-type-post{color: blue;}
.req-type.req-type-get{color: green;}

// 请求返回体单元格, 不同返回状态码，不同文字颜色
.res-box{padding: 3px 8px; background-color: #f0f9eb; color: #888; border-radius: 1px;}
.res-code{color: red;}
.res-code-200{color: green;}
.res-code-500,.res-code-501{color: red;}

// 请求参数和请求返回体强制一行显示 
.req-p, .req-string{line-height: 1.5; cursor: pointer; white-space: nowrap; overflow:hidden; text-overflow: ellipsis;}

.fast-btn{margin-top: -10px;}
.select-form :deep(.el-form-item__label){color: #333 !important;}

// 日期输入框 
.vue-box :deep(.el-date-editor){width: 190px !important;}
</style>
