<template>
    <div class="VisitSchedule-all" v-loading.fullscreen.lock="fullscreenLoading" element-loading-text="耗时较长请耐心等待">
        <el-dialog :before-close="handleBeforeClose" :close-on-click-modal="false" title="请示文件预览" :visible.sync="RequestDocumentVisible" @close="handleDialogClose">
            <div>
                <div class="RequestDocument-box" style="white-space:pre-line;height: 500px;overflow-y: auto;"
                    v-html="RequestDocument"></div>
                <div class="RequestDocument-btn">
                    <el-button @click="BusinessInvitationInstructionsFileDown" type="primary">下载请示文件</el-button>
                    <el-button @click="cancelStream" type="primary">取消生成</el-button>
                </div>
            </div>
        </el-dialog>
        <el-dialog :close-on-click-modal="false" width="400px" title="单位" :visible.sync="UnitVisible">
            <el-form>
                <el-form-item label="团组单位:" :label-width="formLabelWidth">
                    <el-input v-model="unitone" autocomplete="off"></el-input>
                </el-form-item>
                <el-form-item label="拜访单位:" :label-width="formLabelWidth">
                    <el-input v-model="unittwo" autocomplete="off"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button type="primary" @click="UnitSave('覆盖', unitid)">覆 盖</el-button>
                <el-button type="primary" @click="UnitSave('追加', unitid)">追 加</el-button>
            </div>
        </el-dialog>
        <div class="VisitSchedule-search-head">
            <el-form ref="form" label-width="75px">
                <el-form-item style="width: 340px;" label="团组名称:">
                    <el-select @change="ApprovalJourneyInit" filterable v-model="diid" placeholder="请选择团组名称">
                        <el-option v-for="(item, index) in groupList" :key="index" :label="item.teamName"
                            :value="item.id"></el-option>
                    </el-select>
                </el-form-item>
            </el-form>
            <div style="display: flex;gap: 5px;">
                <div style="flex: 1">
                    <el-select filterable v-model="blackCodeId" placeholder="请选择黑屏代码">
                        <el-option v-for="(item, index) in blackCodeList" :key="index" :label="item.title"
                            :value="item.id"></el-option>
                    </el-select>
                </div>
                <div>
                    <el-button style="margin-left: 0px;" @click="CreateApprovalJourney"
                        type="primary">导入机票信息</el-button>
                    <el-button style="margin-left: 0px;" @click="BusinessEnterpriseContinueWrite"
                        type="primary">整篇AI编写</el-button>
                    <el-button style="margin-left: 0px;" @click="BusinessJourneyFileDown"
                        type="primary">AI生成公务行程</el-button>
                    <!-- <el-button style="margin-left: 0px;" @click="BusinessInvitationInstructionsFile" type="primary">AI生成请示文件</el-button> -->
                    <el-button style="margin-left: 0px;" @click="BusinessInvitationInstructionsFileContentStream"
                        type="primary">AI生成请示文件</el-button>
                    <el-select style="width: auto;" filterable v-model="fileIndex" placeholder="请选择文件类型">
                        <el-option v-for="(item, index) in fileTempList" :key="index" :label="item.fileName"
                            :value="item.index"></el-option>
                    </el-select>
                    <el-button @click="ExportApprovalJourneyWord" type="primary">导出日程</el-button>
                    <el-button style="margin-left: 0px;" @click="SaveApprovalJourney" type="primary">保存</el-button>
                    <el-button style="margin-left: 0px;" @click="DeleteApprovalJourney" type="primary">删除</el-button>
                </div>
            </div>
        </div>
        <div class="VisitSchedule-content">
            <div class="VisitSchedule-content-title">出访行程</div>
            <div class="VisitSchedule-content-info">
                团组名:{{ groupInfo.teamName }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;团组号:{{ groupInfo.tourCode
                }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;出访日期:{{ groupInfo.visitStartDate + '~' + groupInfo.visitEndDate
                }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ groupInfo.visitDays + '天/' + groupInfo.visitPNumber + '人' }}
            </div>
            <div class="VisitSchedule-content-table">
                <div v-for="(item, index) in tablearr" :key="index" class="VisitSchedule-content-ul">
                    <div class="content-ul-title">{{ item.date }}</div>
                    <div v-for="(items, index) in item.chiList" :key="index" class="VisitSchedule-content-li">
                        <div class="VisitSchedule-content-time">
                            <el-time-picker is-range format='HH:mm' value-format='HH:mm' v-model="items.timeInterval"
                                :default-value="value1" range-separator="至" start-placeholder="开始时间"
                                end-placeholder="结束时间" placeholder="选择时间范围">
                            </el-time-picker>
                        </div>
                        <div class="VisitSchedule-content-remark">
                            <el-input type="textarea" :rows="2" placeholder="请输入内容" v-model="items.details">
                            </el-input>
                        </div>
                        <div class="VisitSchedule-content-btn">
                            <el-button @click="openunit(items)" type="primary">AI续写</el-button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
import { streamRequestGET, streamRequestPOST } from '@/store/streamRequest';
export default {
    data() {
        return {
            diid: '',
            groupList: [],
            tablearr: [],
            userId: '',
            value1: ['', ''],
            textarea: '',
            ss: [0, 0],
            groupInfo: {},
            fullscreenLoading: false,
            blackCodeId: '',
            blackCodeList: [],
            fileTempList: [],
            fileIndex: 1,
            UnitVisible: false,
            formLabelWidth: '70px',
            unitone: '',
            unittwo: '',
            RequestDocumentVisible: false,
            RequestDocument: '',
            typewriterText: '',
            typewriterTimer: null,
            typewriterQueue: [],
            isTyping: false,
            isStreaming: false,      // 是否正在流式传输
            autoScrollEnabled: true,
            streamController: null,    // 保存控制器，用于中断
            downbtn:true,
            downbtns:false,
            ContentText:''
        }
    },
    computed: {
        displayContent() {
            // 如果需要 Markdown 渲染
            if (this.$marked && typeof this.$marked === 'function') {
                return this.$marked(this.typewriterText || this.RequestDocument);
            }
            return (this.typewriterText || this.RequestDocument).replace(/\n/g, '<br/>');
        }
    },

    watch: {
        // 监听打字机文本变化，智能滚动
        typewriterText() {
            if (this.autoScrollEnabled) {
                this.scrollToBottom();
            }
        }
    },

    methods: {
        //报批行程初始化
        ApprovalJourneyInit() {
            this.groupInfo = {};
            this.tablearr = [];
            this.fullscreenLoading = true;
            this.blackCodeId = '';
            this.blackCodeList = [];

            var url = "/api/Groups/ApprovalJourneyInit"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid == '' ? -1 : that.diid,
                    userId: that.userId,
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.groupList = res.data.data.groupList;
                    if (that.diid == '') {
                        that.diid = that.groupList[0].id;
                    }
                    that.tablearr = res.data.data.content;
                    for (let i = 0; i < that.tablearr.length; i++) {
                        for (let a = 0; a < that.tablearr[i].chiList.length; a++) {
                            if (that.tablearr[i].chiList[a].timeInterval.length == 1) {
                                that.tablearr[i].chiList[a].timeInterval = that.value1;
                            }
                        }
                    }
                    that.unitone = res.data.data.groupInfo.clientUnit;
                    that.groupInfo = res.data.data.groupInfo;
                    that.fullscreenLoading = false;
                    that.blackCodeList = res.data.data.blackCodeList;
                    that.fileTempList = res.data.data.fileTempList;
                } else {
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                    that.fullscreenLoading = false;
                }
            }).catch(function (error) {
                that.$message.error('请联系信息部！');
            });
        },
        openunit(val) {
            this.UnitVisible = true;
            this.unitid = val;
            this.unittwo = "";
        },
        //单位保存
        UnitSave(val, id) {
            this.fullscreenLoading = true;
            var url = "/api/Groups/ApprovalJourneyAiWrite"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    clientName: that.unitone,
                    clientPurpose: that.unittwo
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.fullscreenLoading = false;
                    if (val == '追加') {
                        id.details += ',' + res.data.data;
                    } else {
                        id.details = res.data.data;
                    }
                    that.$message({
                        message: res.data.msg,
                        type: 'success'
                    });
                    that.UnitVisible = false;
                } else {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.$message.error('请联系信息部！');
            });
        },
        //报批行程保存
        SaveApprovalJourney() {
            var url = "/api/Groups/SaveApprovalJourney"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    userId: that.userId,
                    arr: that.tablearr
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.$message({
                        message: res.data.msg,
                        type: 'success'
                    });
                    that.ApprovalJourneyInit();
                } else {
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.$message.error('请联系信息部！');
            });
        },
        /**
         * 滚动到底部
         */
        scrollToBottom() {
            this.$nextTick(() => {
                const container = document.querySelector('.RequestDocument-box');
                if (container && this.autoScrollEnabled) {
                    container.scrollTop = container.scrollHeight;
                }
            });
        },

        /**
         * 滚动事件处理
         */
        handleScroll(e) {
            const container = e.target;
            const isAtBottom = container.scrollHeight - container.scrollTop <= container.clientHeight + 50;

            if (isAtBottom) {
                this.autoScrollEnabled = true;
            } else {
                this.autoScrollEnabled = false;
            }
        },

        /**
         * 打字机效果
         */
        startTypewriter(text, speed = 0) {
            if (this.isTyping) {
                this.typewriterQueue.push(text);
                return;
            }

            this.isTyping = true;
            let index = 0;
            const fullText = text;

            const type = () => {
                if (index < fullText.length) {
                    this.typewriterText += fullText[index];
                    index++;
                    this.typewriterTimer = setTimeout(type, speed);
                } else {
                    this.isTyping = false;
                    this.RequestDocument = this.typewriterText;

                    // 处理队列中的下一个文本
                    if (this.typewriterQueue.length > 0) {
                        const nextText = this.typewriterQueue.shift();
                        this.startTypewriter(nextText, speed);
                    }
                }
            };

            type();
        },

        /**
         * 重置打字机状态
         */
        resetTypewriter() {
            if (this.typewriterTimer) {
                clearTimeout(this.typewriterTimer);
                this.typewriterTimer = null;
            }
            this.typewriterText = '';
            this.RequestDocument = '';
            this.typewriterQueue = [];
            this.isTyping = false;
            this.autoScrollEnabled = true;
        },

        /**
         * 流式传输完成后的处理
         */
        onStreamComplete() {
            console.log('✅ 流式传输已完成');
            this.isStreaming = false;
        },

        /**
         * 流式接收并显示请示文件（带完成回调）
         */
        BusinessInvitationInstructionsFileContentStream() {
            // 重置状态
            this.resetTypewriter();
            this.isStreaming = true;
            
            this.fullscreenLoading = true;
            // 绑定滚动事件
            this.$nextTick(() => {
                const container = document.querySelector('.RequestDocument-box');
                if (container) {
                    container.addEventListener('scroll', this.handleScroll);
                }
            });

            const url = "http://132.232.92.186:8888/api/Groups/BusinessInvitationInstructionsFileContentStream";
            const that = this;
            this.ContentText = '';
            // 发起流式请求，传入完成回调
            this.streamController = streamRequestPOST(
                url,
                { diid: that.diid },
                (data) => {
                    that.RequestDocumentVisible = true;
                    that.fullscreenLoading = false;
                    // 处理流式返回的数据
                    let newText = '';
                    if (typeof data === 'string') {
                        newText = data;
                    } else if (data.text) {
                        newText = data.text;
                    } else if (data.content) {
                        newText = data.content;
                    } else {
                        newText = JSON.stringify(data);
                    }
                    if (newText) {
                        that.startTypewriter(newText, 0);
                    }
                    if (data.phase=='content') {
                        that.ContentText += data.text;
                    }
                },(error) => {
                    // 错误处理
                    console.error('流式请求失败:', error);
                    that.isStreaming = false;
                    that.$message.error('获取请示文件失败，请关闭弹窗界面后，再重试！');
                },(res) => {
                    // 完成回调 - 流式传输真正结束时触发
                    if (that.RequestDocumentVisible==false&&that.fullscreenLoading == true) {
                       that.$message.error('没有信息无法生成！');
                    }
                    that.fullscreenLoading = false;
                    that.onStreamComplete();
                }
            );
        },

        /**
         * 手动中断流式请求
         */
        cancelStream() {
            this.$confirm('此操作将停止生成数据，且下次操作需要重新开始生成, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                if (this.streamController) {
                    this.RequestDocumentVisible = false;
                    this.streamController.abort();
                    this.isStreaming = false;
                    this.$message.info('已停止生成');
                }else {
                    this.$message.warning('没有正在生成的数据数据已生成完毕');
                }
            }).catch(() => {});
        },

        /**
         * Dialog 关闭时的处理
         */
        handleBeforeClose(done){
            if (this.isStreaming) {
                this.$confirm('内容正在生成中，确定要关闭吗？下次将需要重新开始生成。', '提示', {
                    confirmButtonText: '确定关闭',
                    cancelButtonText: '继续生成',
                    type: 'warning',
                    distinguishCancelAndClose: true
                }).then(() => {
                    // 用户确认关闭
                    // 中断进行中的请求
                    if (this.streamController) {
                        this.streamController.abort();
                    }
                    done(); // 执行关闭
                }).catch(() => {
                    // 用户取消关闭，不做任何操作
                    console.log('用户取消关闭，继续生成');
                });
                return;
            }
            done();
        },
        handleDialogClose() {
            
            // 移除滚动事件监听
            const container = document.querySelector('.RequestDocument-box');
            if (container) {
                container.removeEventListener('scroll', this.handleScroll);
            }
            // 重置状态
            this.resetTypewriter();
            this.isStreaming = false;
        },
        //下载请示文件
        BusinessInvitationInstructionsFileDown() {
            if (this.isStreaming) {
                this.$message.warning('请等待内容生成完毕后再下载！');
                return;
            }
            this.fullscreenLoading = true;
            var url = "/api/Groups/BusinessInvitationInstructionsFileDown"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                    content: that.ContentText
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: "导出成功！",
                        type: 'success'
                    });
                    window.open(res.data.data)
                } else {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        type: "error"
                    });
                }
            })
        },
        //报批行程删除
        DeleteApprovalJourney() {
            var url = "/api/Groups/DeleteApprovalJourney"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                    userId: that.userId,
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.$message({
                        message: res.data.msg,
                        type: 'success'
                    });
                    that.ApprovalJourneyInit();
                } else {
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.$message.error('请联系信息部！');
            });
        },
        //报批行程导入机票信息
        CreateApprovalJourney() {

            if (!this.blackCodeId) {
                this.$message({
                    message: '请选择黑屏代码',
                    duration: 1000,
                    type: "error"
                });
                return;
            }

            var url = "/api/Groups/CreateApprovalJourney"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                    userid: that.userId,
                    BlackCodeId: that.blackCodeId
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.$message({
                        message: res.data.msg,
                        type: 'success'
                    });
                    that.tablearr = res.data.data;
                    for (let i = 0; i < that.tablearr.length; i++) {
                        for (let a = 0; a < that.tablearr[i].chiList.length; a++) {
                            if (that.tablearr[i].chiList[a].timeInterval.length == 1) {
                                that.tablearr[i].chiList[a].timeInterval = that.value1;
                            }
                        }
                    }
                } else {
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.$message.error('请联系信息部！');
            });
        },
        //报批行程导出
        ExportApprovalJourneyWord() {
            if (!this.fileIndex) {
                this.$message({
                    message: '请选择文件类型',
                    duration: 1000,
                    type: "error"
                });
                return;
            }

            this.fullscreenLoading = true;
            var url = "/api/Groups/ExportApprovalJourneyWord"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                    fileIndex: this.fileIndex
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.$message({
                        message: "导出成功！",
                        type: 'success'
                    });
                    that.fullscreenLoading = false;
                    window.open(res.data.data)
                } else {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.fullscreenLoading = false;
                that.$message.error('请联系信息部！');
            });
        },
        //报批行程框架导出
        BusinessJourneyFileDown() {
            if (!this.blackCodeId) {
                this.$message({
                    message: '请选择文件类型',
                    duration: 1000,
                    type: "error"
                });
                return;
            }
            this.fullscreenLoading = true;

            var url = "/api/Groups/BusinessJourneyFileDown"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                    blackCodeId: this.blackCodeId
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.$message({
                        message: "导出成功！",
                        type: 'success'
                    });
                    that.fullscreenLoading = false;
                    window.open(res.data.data)
                } else {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.fullscreenLoading = false;
                that.$message.error('请联系信息部！');
            });
        },
        //请示文件导出
        BusinessInvitationInstructionsFile() {
            this.fullscreenLoading = true;
            var url = "/api/Groups/BusinessInvitationInstructionsFile"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: "导出成功！",
                        type: 'success'
                    });
                    window.open(res.data.data)
                } else {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.fullscreenLoading = false;
                that.$message.error('请联系信息部！');
            });
        },
        //拜访内容续写
        BusinessEnterpriseContinueWrite() {
            this.fullscreenLoading = true;
            var url = "/api/Groups/BusinessEnterpriseContinueWrite"
            var that = this
            this.$axios({
                method: 'post',
                url: url,
                headers: {
                    Authorization: 'Bearer '
                },
                data: {
                    diid: that.diid,
                }
            }).then(function (res) {
                if (res.data.code == 200) {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        type: 'success'
                    });
                    that.tablearr = res.data.data.jsonResult;
                    for (let i = 0; i < that.tablearr.length; i++) {
                        for (let a = 0; a < that.tablearr[i].chiList.length; a++) {
                            if (that.tablearr[i].chiList[a].timeInterval.length == 1) {
                                that.tablearr[i].chiList[a].timeInterval = that.value1;
                            }
                        }
                    }
                } else {
                    that.fullscreenLoading = false;
                    that.$message({
                        message: res.data.msg,
                        duration: 1000,
                        type: "error"
                    });
                }
            }).catch(function (error) {
                that.fullscreenLoading = false;
                that.$message.error('请联系信息部！');
            });
        },
    },
    mounted() {
        this.userId = JSON.parse(localStorage.getItem('userinif')).userInfo.userId;
        this.ApprovalJourneyInit();
    },
    beforeDestroy() {
        // 组件销毁时清理
        if (this.streamController) {
            this.streamController.abort();
        }
        if (this.typewriterTimer) {
            clearTimeout(this.typewriterTimer);
        }
        const container = document.querySelector('.RequestDocument-box');
        if (container) {
            container.removeEventListener('scroll', this.handleScroll);
        }
    }
}
</script>
<style>
.VisitSchedule-all {
    background-color: #fff;
    padding: 10px;
    box-shadow: 0 0 5px #0005;
    border-radius: 10px;
    min-height: 830px;
}

.VisitSchedule-search-head {
    display: flex;
    justify-content: space-between;
}

.VisitSchedule-search-head .el-select {
    width: 100%;
}

.VisitSchedule-content-table {
    padding: 10px 0;
    border: 1px solid #DCDFE6;
}

.VisitSchedule-content-li {
    border-top: 1px solid #DCDFE6;
    display: flex;
    align-items: center;
}

.VisitSchedule-content-time {
    padding: 10px;
    width: 25%;
}

.VisitSchedule-content-remark {
    width: 70%;
    padding: 10px;
}

.VisitSchedule-content-btn {
    width: 5%;
    padding: 10px;
}

.VisitSchedule-content-time .el-range-editor.el-input__inner {
    width: 100%;
}

.content-ul-title {
    padding: 10px;
}

.VisitSchedule-content-ul .VisitSchedule-content-li:last-child {
    border-bottom: 1px solid #DCDFE6;
}

.VisitSchedule-content-title {
    text-align: center;
    margin-bottom: 10px;
    color: #555;
    font-size: 17px;
    font-weight: 600;
}

.VisitSchedule-content-info {
    text-align: center;
    color: #555;
    font-size: 15px;
    margin-bottom: 20px;
}
.RequestDocument-btn{
    text-align: right;
}
</style>